hgbook
diff fr/complete.xml @ 1017:77b4f62bed20
some typo and better french translation
author | André Sintzoff <andre.sintzoff@gmail.com> |
---|---|
date | Wed Nov 25 15:33:52 2009 +0100 (2009-11-25) |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/fr/complete.xml Wed Nov 25 15:33:52 2009 +0100 1.3 @@ -0,0 +1,16711 @@ 1.4 +<?xml version="1.0"?> 1.5 + 1.6 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" 1.7 + "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> 1.8 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.9 +<book id="hg"> 1.10 + <title>Mercurial: The Definitive Guide</title> 1.11 + 1.12 + <!-- hg parents --template '{node|short} ({date|shortdate})' 1.13 + <subtitle>Compiled from 8a1d3f1aff17 (2009-03-10)</subtitle> 1.14 + --> 1.15 + <subtitle>Compiled from $rev_id$</subtitle> 1.16 + <bookinfo> 1.17 + <edition>1</edition> 1.18 + <isbn>9780596800673</isbn> 1.19 + <authorgroup> 1.20 + <author> 1.21 + <firstname>Bryan</firstname> 1.22 + <surname>O'Sullivan</surname> 1.23 + </author> 1.24 + </authorgroup> 1.25 + 1.26 + <editor> 1.27 + <firstname>Mike</firstname> 1.28 + <surname>Loukides</surname> 1.29 + </editor> 1.30 + 1.31 + <copyright> 1.32 + <year>2006</year> 1.33 + <year>2007</year> 1.34 + <year>2008</year> 1.35 + <year>2009</year> 1.36 + <holder>Bryan O'Sullivan</holder> 1.37 + </copyright> 1.38 + </bookinfo> 1.39 + 1.40 + <!-- BEGIN ch00 --> 1.41 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.42 + 1.43 +<preface id="chap:preface"> 1.44 + <?dbhtml filename="preface.html"?> 1.45 + <title>Preface</title> 1.46 + 1.47 + <sect1> 1.48 + <title>Un conte technique</title> 1.49 + 1.50 + <para id="x_72e">Il y a quelques années, quand j'ai voulu expliqué 1.51 + pourquoi je pensais que le gestion de révision distribuée est importante, 1.52 + le domaine était encore si nouveau qu'il n'y avait presque aucune 1.53 + littérature publiée pour servir de référence aux personnes intéressées.</para> 1.54 + 1.55 + <para id="x_72f">Bien qu'à cette époque je passais beaucoup de temps 1.56 + à travailler sur les entrailles de Mercurial, je me suis mis à la 1.57 + rédaction de ce livre parce qu'il me semblait la manière la plus efficace 1.58 + d'aider notre logiciel à atteindre un vaste auditoire, toujours avec 1.59 + l'idée que la gestion de révision devrait être distribuée par nature. J'ai 1.60 + publié ce libre en ligne sous une licence libre pour la même raison : pour 1.61 + diffuser la parole auprès du monde.</para> 1.62 + 1.63 + <para id="x_730">Il y a un rythme familier à un bon livre sur un logiciel 1.64 + qui ressemble de près au fait de conter une histoire : Pourquoi ceci est ? 1.65 + Pourquoi ceci est important ? Comment peut il m'aider ? Comment m'en 1.66 + servir ? Dans ce livre, j'essaye de répondre à toutes ces questions pour 1.67 + la gestion de révision distribuée en général, et pour Mercurial en 1.68 + particulier.</para> 1.69 + </sect1> 1.70 + 1.71 + <sect1> 1.72 + <title>Merci de votre soutien à Mercurial</title> 1.73 + 1.74 + <para id="x_731">En achetant une copie de ce livre, vous soutenez le 1.75 + développement et la liberté de Mercurial en particulier, et dans 1.76 + l'Open Source, au logiciel libre en général. O'Reilly Media et 1.77 + moi-même donnons les revenus issus des ventes de ce livre à la 1.78 + Software Freedom Conservancy (<ulink url="http://www.softwarefreedom.org/">http://www.softwarefreedom.org/</ulink>) 1.79 + qui fournit un support juridique à Mercurial et à de 1.80 + nombreux autres projets Open Source proéminents et de qualité.</para> 1.81 + </sect1> 1.82 + 1.83 + <sect1> 1.84 + <title>Remerciements</title> 1.85 + 1.86 + <para id="x_732">Ce livre n'aurait pas vu le jour sans les 1.87 + efforts de Matt Mackal, l'auteur et le chef du projet Mercurial. 1.88 + Il est assisté très efficacement par des centaines de contributeurs 1.89 + volontaires à travers le monde.</para> 1.90 + 1.91 + <para id="x_733">Les enfants, Cian et Ruairi, ont toujours été prêt 1.92 + à m'aider à me reposer avec de merveilleux et impulsif jeux d'enfants. 1.93 + Je tiens aussi à remercier mon ex-femme, Shannon, pour son soutien. 1.94 + </para> 1.95 + 1.96 + <para id="x_734">Mes collègues et amis m'ont aidé et assisté de 1.97 + de nombreuses manières. Cette liste de personne est nécessaire mais très 1.98 + incomplète : Stephen Hahn, Karyn Ritter, Bonnie Corwin, James Vasile, 1.99 + Matt Norwood, Eben Moglen, Bradley Kuhn, Robert Walsh, Jeremy 1.100 + Fitzhardinge, Rachel Chalmers.</para> 1.101 + 1.102 + <para id="x_735">J'ai conçu ce livre de manière ouverte, en publiant 1.103 + des brouillons des chapitres du livre sur des site web, au fur et à 1.104 + mesure que je les réalisais. Leurs lecteurs m'ont fait des retours 1.105 + utilisant l'application web que j'avais développée. A la fin de sa 1.106 + conception, plus de 100 personnes m'avaient fait des commentaires, 1.107 + un chiffre incroyable quand l'on considère que ce système de 1.108 + commentaire n'a tourné que dans les deux derniers mois de la 1.109 + rédaction du livre.</para> 1.110 + 1.111 + <para id="x_736">J'aimerais particulièrement remercier les 1.112 + personnes suivantes, dont les commentaires représentent plus 1.113 + d'un tiers de l'ensemble de ces derniers. Je voudrais les 1.114 + remercier pour leur attention et effort à me faire des retours 1.115 + très détaillés.</para> 1.116 + 1.117 + <para id="x_737">Martin Geisler, Damien Cassou, Alexey Bakhirkin, Till Plewe, 1.118 + Dan Himes, Paul Sargent, Gokberk Hamurcu, Matthijs van der 1.119 + Vleuten, Michael Chermside, John Mulligan, Jordi Fita, Jon 1.120 + Parise.</para> 1.121 + 1.122 + <para id="x_738">Je souhaite aussi remercier l'aide des personnes 1.123 + qui ont découvert des erreurs et fournit des suggestions avisées 1.124 + à travers tout le livre.</para> 1.125 + 1.126 + <para id="x_739">Jeremy W. Sherman, Brian Mearns, Vincent Furia, Iwan 1.127 + Luijks, Billy Edwards, Andreas Sliwka, Paweł Sołyga, Eric 1.128 + Hanchrow, Steve Nicolai, Michał Masłowski, Kevin Fitch, Johan 1.129 + Holmberg, Hal Wine, Volker Simonis, Thomas P Jakobsen, Ted 1.130 + Stresen-Reuter, Stephen Rasku, Raphael Das Gupta, Ned 1.131 + Batchelder, Lou Keeble, Li Linxiao, Kao Cardoso Félix, Joseph 1.132 + Wecker, Jon Prescot, Jon Maken, John Yeary, Jason Harris, 1.133 + Geoffrey Zheng, Fredrik Jonson, Ed Davies, David Zumbrunnen, 1.134 + David Mercer, David Cabana, Ben Karel, Alan Franzoni, Yousry 1.135 + Abdallah, Whitney Young, Vinay Sajip, Tom Towle, Tim Ottinger, 1.136 + Thomas Schraitle, Tero Saarni, Ted Mielczarek, Svetoslav 1.137 + Agafonkin, Shaun Rowland, Rocco Rutte, Polo-Francois Poli, 1.138 + Philip Jenvey, Petr Tesałék, Peter R. Annema, Paul Bonser, 1.139 + Olivier Scherler, Olivier Fournier, Nick Parker, Nick Fabry, 1.140 + Nicholas Guarracino, Mike Driscoll, Mike Coleman, Mietek Bák, 1.141 + Michael Maloney, László Nagy, Kent Johnson, Julio Nobrega, Jord 1.142 + Fita, Jonathan March, Jonas Nockert, Jim Tittsler, Jeduan 1.143 + Cornejo Legorreta, Jan Larres, James Murphy, Henri Wiechers, 1.144 + Hagen Möbius, Gábor Farkas, Fabien Engels, Evert Rol, Evan 1.145 + Willms, Eduardo Felipe Castegnaro, Dennis Decker Jensen, Deniz 1.146 + Dogan, David Smith, Daed Lee, Christine Slotty, Charles Merriam, 1.147 + Guillaume Catto, Brian Dorsey, Bob Nystrom, Benoit Boissinot, 1.148 + Avi Rosenschein, Andrew Watts, Andrew Donkin, Alexey Rodriguez, 1.149 + Ahmed Chaudhary.</para> 1.150 + </sect1> 1.151 + 1.152 + <sect1> 1.153 + <title>Conventions utilisées dans ce livre</title> 1.154 + 1.155 + <para id="x_73a">Les conventions typographiques suivantes sont utilisées dans ce livre :</para> 1.156 + 1.157 + <variablelist> 1.158 + <varlistentry> 1.159 + <term>Italique</term> 1.160 + 1.161 + <listitem> 1.162 + <para id="x_73b">Indique les termes nouveaux, les URLs, les 1.163 + adresses mail, les noms de fichiers et les extensions de 1.164 + fichier.</para> 1.165 + </listitem> 1.166 + </varlistentry> 1.167 + 1.168 + <varlistentry> 1.169 + <term><literal moreinfo="none">Taille constante</literal></term> 1.170 + 1.171 + <listitem> 1.172 + <para id="x_73c">Utilisé pour les extraits de code, comme 1.173 + dans les paragraphes pour référer aux éléments du programme, 1.174 + tels que les variables ou les noms de fonctions, de bases 1.175 + de données, de types de données, de variables d'environnement, 1.176 + d'instructions, et de mots clés.</para> 1.177 + </listitem> 1.178 + </varlistentry> 1.179 + 1.180 + <varlistentry> 1.181 + <term><userinput moreinfo="none">Taille constante avec gras</userinput></term> 1.182 + 1.183 + <listitem> 1.184 + <para id="x_73d">Afficher les commandes ou autres textes qui 1.185 + devraient être saisis par l'utilisateur.</para> 1.186 + </listitem> 1.187 + </varlistentry> 1.188 + 1.189 + <varlistentry> 1.190 + <term><replaceable>Constante avec italique</replaceable></term> 1.191 + 1.192 + <listitem> 1.193 + <para id="x_73e">Affiche les textes qui devraient être remplacés 1.194 + par une valeur définie par l'utilisateur ou des valeurs définies 1.195 + selon le contexte.</para> 1.196 + </listitem> 1.197 + </varlistentry> 1.198 + </variablelist> 1.199 + 1.200 + <tip> 1.201 + <para id="x_73f">Cette icône indique une astuce, une suggestion ou 1.202 + une note d'ordre général.</para> 1.203 + </tip> 1.204 + 1.205 + <caution> 1.206 + <para id="x_740">Cette icône est un message d'alerte ou de prudence.</para> 1.207 + </caution> 1.208 + </sect1> 1.209 + 1.210 + <sect1> 1.211 + <title>Utiliser les exemples de code</title> 1.212 + 1.213 + <para id="x_741">Ce livre est ici pour vous aider dans votre 1.214 + travail. De manière générale, vous pouvez donc utiliser le code 1.215 + de ce livre dans vos programmes et votre documentation. Vous 1.216 + n'avez pas à nous contacter pour nous demander la permission 1.217 + de le faire, à moins que vous ne reproduisiez une partie significative 1.218 + du code. Par exemple, écrire un programme qui utilise plusieurs 1.219 + extraits de code du livre ne demande aucune autorisation particulière. 1.220 + Vendre ou distribuer un CD-ROM provenant des livres O'Reilly demande 1.221 + à l'inverse une autorisation. Répondre à une question en citant ce 1.222 + livre ou ses exemples de code ne demande aucune autorisation préalable. 1.223 + Intégrer une grande quantité des codes d'exemples de ce livre dans 1.224 + votre propre ouvrage demande une autorisation de notre part.</para> 1.225 + 1.226 + <para id="x_742">Nous apprécions, sans l'exiger, que vous citiez 1.227 + l'ouvrage dans vos écrits l'utilisant, en indiquant le titre, 1.228 + l'auteur, l'éditeur et son ISBN. Par exemple: “<emphasis>Titre du 1.229 + livre</emphasis> par Son Auteur. Copyright 2008 O’Reilly Media, Inc., 1.230 + 978-0-596-xxxx-x.”</para> 1.231 + 1.232 + <para id="x_743">Si vous estimez que votre usage des exemples de code 1.233 + dépasse le cadre défini ci dessus, n'hésitez pas à nous contacter : 1.234 + <email>permissions@oreilly.com</email>.</para> 1.235 + </sect1> 1.236 + 1.237 + <sect1> 1.238 + <title>Safari® Books Online</title> 1.239 + 1.240 + <note role="safarienabled"> 1.241 + <para id="x_744">Quand vous voyez l'icône de Safari® Books Online 1.242 + sur la couverture d'un de vos livres techniques préférés, cela signifie 1.243 + que le livre est disponible, en ligne, à travers le O’Reilly Network Safari 1.244 + Bookshelf.</para> 1.245 + </note> 1.246 + 1.247 + <para id="x_745">Safari offre une solution qui est meilleure que 1.248 + les e-books. C'est une bibliothèque virtuelle qui vous laisse 1.249 + aisément rechercher dans des milliers de livres, mais aussi 1.250 + copier-coller leurs exemples, télécharger des chapitres, et 1.251 + trouver des réponses rapides quand vous avez besoin d'une 1.252 + information précise et à jour. Essayez le gratuitement : 1.253 + <ulink role="orm:hideurl:ital" url="http://my.safaribooksonline.com/?portal=oreilly">http://my.safaribooksonline.com</ulink>.</para> 1.254 + </sect1> 1.255 + 1.256 + <sect1> 1.257 + <title>Comment nous contacter</title> 1.258 + 1.259 + <para id="x_746">Merci d'adresser vos commentaires et vos questions 1.260 + sur ce livre à son éditeur:</para> 1.261 + 1.262 + <simplelist type="vert"> 1.263 + <member>O’Reilly Media, Inc.</member> 1.264 + 1.265 + <member>1005 Gravenstein Highway North</member> 1.266 + 1.267 + <member>Sebastopol, CA 95472</member> 1.268 + 1.269 + <member>800-998-9938 (in the United States or Canada)</member> 1.270 + 1.271 + <member>707-829-0515 (international or local)</member> 1.272 + 1.273 + <member>707 829-0104 (fax)</member> 1.274 + </simplelist> 1.275 + 1.276 + <para id="x_747">Nous avons une page web pour cet ouvrage, où nous 1.277 + publions des errata, des exemples, et encore d'autres informations 1.278 + additionnelles. Vous pouvez accéder à cette page par l'URL suivante: 1.279 + </para> 1.280 + 1.281 + <simplelist type="vert"> 1.282 + <member><ulink url="http://www.oreilly.com/catalog/<catalog page>"/></member> 1.283 + </simplelist> 1.284 + 1.285 + <remark>N'oubliez pas de mettre à jour l'attribut <url> aussi.</remark> 1.286 + 1.287 + <para id="x_748">Pour commenter ou poser des questions techniques 1.288 + sur cet ouvrage, envoyez un email à :</para> 1.289 + 1.290 + <simplelist type="vert"> 1.291 + <member><email>bookquestions@oreilly.com</email></member> 1.292 + </simplelist> 1.293 + 1.294 + <para id="x_749">Pour plus d'informations sur nos livres, nos 1.295 + conférences, nos centres d'informations, et le réseau O’Reilly, 1.296 + voyez notre site web :</para> 1.297 + 1.298 + <simplelist type="vert"> 1.299 + <member><ulink url="http://www.oreilly.com"/></member> 1.300 + </simplelist> 1.301 + </sect1> 1.302 +</preface> 1.303 + 1.304 +<!-- 1.305 +local variables: 1.306 +sgml-parent-document: ("00book.xml" "book" "preface") 1.307 +end: 1.308 +--> 1.309 + 1.310 + <!-- BEGIN ch01 --> 1.311 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.312 + 1.313 +<chapter id="chap:intro"> 1.314 + <?dbhtml filename="how-did-we-get-here.html"?> 1.315 + <title>Comment en est on arrivé là ?</title> 1.316 + 1.317 +<sect1> 1.318 +<title>À propos de la gestion source</title> 1.319 + 1.320 + <para id="x_6d">La gestion de sources est un processus permettant de gérer différentes 1.321 +versions de la même information. Dans sa forme la plus simple, c'est 1.322 +ce que tout le monde fait manuellement : quand vous modifiez 1.323 +un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro, 1.324 +à chaque fois plus grand que celui de la version précédente.</para> 1.325 + 1.326 + <para id="x_6e">Ce genre de gestion de version manuelle est cependant facilement sujette 1.327 +aux erreurs, ainsi, depuis longtemps, des logiciels existent pour 1.328 +résoudre cette problématique. Les premiers outils de gestion de sources 1.329 +étaient destinés à aider un seul utilisateur, à automatiser la gestion 1.330 +des versions d'un seul fichier. Dans les dernières décades, cette cible 1.331 +s'est largement agrandie, ils gèrent désormais de multiples fichiers, et 1.332 +aident un grand nombre de personnes à travailler ensemble. Les outils les 1.333 +plus modernes n'ont aucune difficulté à gérer plusieurs milliers de 1.334 +personnes travaillant ensemble sur des projets regroupant plusieurs 1.335 +centaines de milliers de fichiers.</para> 1.336 + 1.337 + <para id="x_6f">L'arrivée de la gestion de révision distribuée est 1.338 + relativement récente, et, pour le moment, ce nouveau domaine a grandi 1.339 + grâce à la volonté des gens d'explorer ces territoires encore inconnus. 1.340 + </para> 1.341 + 1.342 + <para id="x_70">J'écris un livre sur la gestion de révision distribuée 1.343 + parce que je pense qu'il s'agit d'un sujet important qui mérite un guide 1.344 + du terrain. J'ai choisi d'écrire un livre sur Mercurial car il est 1.345 + l'outil le plus facile pour découvrir ce nouveau domaine, tout en étant 1.346 + un outil efficace qui répond aux demandes d'environnements réels et 1.347 + difficiles, là où d'autres outils de gestions de versions s'effondrent.</para> 1.348 + 1.349 + <sect2> 1.350 + <title>Pourquoi utiliser un gestionnaire de source ?</title> 1.351 + 1.352 + <para id="x_71">Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez 1.353 +utiliser un outil automatisant la gestion de version pour votre projet.</para> 1.354 + 1.355 + <itemizedlist> 1.356 + <listitem><para id="x_72">L'outil se chargera de suivre l'évolution de votre projet, sans 1.357 +que vous ayez à le faire. Pour chaque modification, vous aurez à votre 1.358 +disposition un journal indiquant <emphasis>qui</emphasis> a fait quoi, <emphasis>pourquoi</emphasis> 1.359 +il l'a fait, <emphasis>quand</emphasis> il l'a fait, et 1.360 +<emphasis>ce</emphasis> qu'il a modifié.</para> 1.361 +</listitem> 1.362 +<listitem><para id="x_73">Quand vous travaillez avec d'autres personnes, les logiciels de 1.363 +gestion de source facilitent le travail collaboratif. Par exemple, quand 1.364 +plusieurs personnes font, plus ou moins simultanément, des modifications 1.365 +incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits.</para> 1.366 +</listitem> 1.367 +<listitem><para id="x_74">L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement 1.368 +qui se révèle être une erreur, vous pourrez revenir à une version 1.369 +antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de 1.370 +gestion de source <emphasis>vraiment</emphasis> efficace vous permettra d'identifier à quel 1.371 +moment le problème est apparu (voir la section <xref linkend="sec:undo:bisect"/> pour plus 1.372 +de détails).</para> 1.373 +</listitem> 1.374 +<listitem><para id="x_75">L'outil vous permettra aussi de travailler sur plusieurs versions différentes 1.375 +de votre projet et de gérer l'écart entre chacune.</para> 1.376 +</listitem></itemizedlist> 1.377 +<para id="x_76">La plupart de ces raisons ont autant d'importances —du 1.378 + moins en théorie— que vous travailliez sur un projet pour vous, ou 1.379 + avec une centaine d'autres personnes. 1.380 +</para> 1.381 + 1.382 +<para id="x_77">Une question fondamentale à propos des outils de gestion de 1.383 + source, qu'il s'agisse du projet d'une personne ou d'une grande équipe, est 1.384 + quels sont ses <emphasis>avantages</emphasis> par rapport à ses 1.385 + <emphasis>coûts</emphasis>. Un outil qui est difficile à utiliser ou à 1.386 + comprendre exigera un lourd effort d'adaptation. 1.387 +</para> 1.388 + 1.389 +<para id="x_78">)Un projet de cinq milles personnes s'effondrera très 1.390 + certainement de lui même sans aucun processus et outil de gestion de 1.391 + source. Dans ce cas, le coût d'utilisation d'un logiciel de gestion de 1.392 + source est dérisoire puisque <emphasis>sans</emphasis>, l'échec est presque 1.393 + garanti. 1.394 +</para> 1.395 + 1.396 +<para id="x_79">D'un autre coté, un <quote>rapide hack</quote> d'une personne 1.397 + peut sembler un contexte bien pauvre pour utiliser un outil de gestion de 1.398 + source, car, bien évidement le coût d'utilisation dépasse le coût total du 1.399 + projet. N'est ce pas ? 1.400 +</para> 1.401 + 1.402 + <para id="x_7a">Mercurial supporte ces <emphasis>deux</emphasis> 1.403 + échelles de travail. Vous pouvez apprendre les bases en quelques 1.404 + minutes seulement, et, grâce à sa performance, vous pouvez l'utiliser 1.405 + avec facilité sur le plus petit des projets. Cette simplicité 1.406 + signifie que vous n'avez pas de concept obscurs ou de séquence de 1.407 + commandes défiant l'imagination, sans aucune corrélation avec 1.408 + <emphasis>ce que vous êtes entrain de faire</emphasis>. En même 1.409 + temps, ces mêmes performances et sa nature 1.410 + <quote>peer-to-peer</quote> vous permettent d'adapter, sans 1.411 + difficulté, son utilisation à de très grands projets. 1.412 +</para> 1.413 + 1.414 + <para id="x_7b">Aucun outil de gestion de source ne peut sauver un 1.415 + projet mal mené, mais un bon outil peut rendre beaucoup plus fluide 1.416 + votre travail. 1.417 +</para> 1.418 + 1.419 + </sect2> 1.420 + 1.421 + <sect2> 1.422 + <title>Les multiples noms de la gestion de source</title> 1.423 + 1.424 + <para id="x_7c">La gestion de source 1.425 + <!-- TODO:<footnote><J'ai utilisé systématiquement le terme 1.426 + <quote>gestion de source</quote> à travers tout l'ouvrage. Ce 1.427 + n'est pas forcement la meilleure traduction, et ceci peut rendre 1.428 + la lecture un peu lourde, mais je pense que le document y gagne 1.429 + en clarté et en précision. --> 1.430 + est un domaine tellement large qu'il n'existe pas qu'un seul nom ou 1.431 + acronyme pour le désigner. Voici quelques noms ou acronymes que vous 1.432 + rencontrerez le plus souvent. 1.433 + <!-- TODO:<footnote> J'ai conservé la liste des noms en anglais pour 1.434 + des raisons de commodité (ils sont plus <quote>googelable</quote>). 1.435 + En outre, j'ai opté pour conserver l'ensemble des opérations de 1.436 + Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en 1.437 + anglais, là aussi pour faciliter la lecture d'autres documents en 1.438 + anglais, ainsi que l'utilisation de Mercurial. --> 1.439 +</para> 1.440 + 1.441 +<para>: 1.442 +</para> 1.443 + 1.444 + <itemizedlist> 1.445 + <listitem><para id="x_7d">Revision control (RCS)</para></listitem> 1.446 + <listitem><para id="x_7e">Software configuration management (SCM), ou 1.447 + configuration management</para></listitem> 1.448 + <listitem><para id="x_7f">Source code management</para></listitem> 1.449 + <listitem><para id="x_80">Source code control, ou source control</para></listitem> 1.450 + <listitem><para id="x_81">Version control (VCS)</para></listitem></itemizedlist> 1.451 + 1.452 + <para id="x_82">Certaines personnes prétendent que ces termes ont en fait 1.453 + des sens différents mais en pratique ils se recouvrent tellement qu'il n'y 1.454 + a pas réellement de manière pertinente de les distinguer. </para> 1.455 + 1.456 + </sect2> 1.457 + </sect1> 1.458 + 1.459 + <sect1> 1.460 + 1.461 +<title>A propos des exemples dans ce livre</title> 1.462 + 1.463 + <para id="x_84">Ce livre prend une approche non usuel pour les exemples 1.464 + de code. Tous les exemples sont en <quote>live</quote> — Chacun 1.465 + est actuellement le résultat d'un script shell qui exécute les 1.466 + commandes Mercurial que vous voyez. A chaque fois qu'une image du livre 1.467 + est construite à partir des sources, tous les scripts d'exemple sont 1.468 + lancés automatiquement, et leurs résultats effectifs sont comparés aux 1.469 + résultats attendus.</para> 1.470 + 1.471 + <para id="x_85">L'avantage de dette approche est que les exemples sont 1.472 + toujours précis ; ils décrivent <emphasis>exactement</emphasis> la 1.473 + conduite de la version de Mercurial qui est mentionnée en entête du 1.474 + livre. Si je met à jour la version de Mercurial que je suis en train de 1.475 + documenter, et que la sortie de certaines commandes change, la 1.476 + construction du livre échoue.</para> 1.477 + 1.478 + <para id="x_86"> 1.479 + Il existe un petit désavantage à cette approche qui est que les dates et 1.480 + heures que vous verrez dans les exemples tendent à être 1.481 + <quote>écrasés</quote> ensemble, dans le sens où elles ne sont pas 1.482 + celles qu'elles auraient été si un humain avait tapé les commandes. En 1.483 + effet, humain ne peut pas taper plus d'une commande toutes les quelques 1.484 + secondes, avec le temps qui s'écoule, mes scripts d'exemples exécutent 1.485 + plusieurs commandes en une seconde. 1.486 + </para> 1.487 + 1.488 + <para id="x_87">Une circonstance de ceci est que plusieurs commits 1.489 + consécutifs dans un exemple peuvent apparaître comme ayant eu lieu 1.490 + durant la même seconde. 1.491 + Vous pouvez observer le phénomène dans l'exemple <literal role="hg-ext" moreinfo="none">bisect</literal> dans <xref linkend="sec:undo:bisect"/> 1.492 + </para> 1.493 + 1.494 + <para id="x_88">Donc, lorsque vous lisez ces exemples, ne prêtez pas trop 1.495 + d'importance aux dates et heures que vous voyez dans la sortie des 1.496 + commandes. Cependant, <emphasis>soyez</emphasis> confiants que le 1.497 + comportement que vous voyez est consistent et reproductible 1.498 + </para> 1.499 + 1.500 + </sect1> 1.501 + 1.502 +<!-- The next section has disapper from this part of the book. it may be splaced somewhere else... t--> 1.503 + 1.504 + <sect1> 1.505 + <title>Tendances de la gestion de source</title> 1.506 + 1.507 + <para id="x_89">Il y a eu une tendance évidente dans le développement et 1.508 + l'utilisation d'outils de gestion de source depuis les quatre dernières 1.509 + décades, au fur et à mesure que les utilisateurs se sont habitués à 1.510 + leur outils et se sont sentis contraints par leurs limitations. 1.511 + </para> 1.512 + 1.513 + <para id="x_8a">La première génération commença simplement par gérer un 1.514 + fichier unique sur un ordinateur individuel. Cependant, même si ces 1.515 + outils présentaient une grande avancée par rapport à la gestion 1.516 + manuelle des versions, leur modèle de verrouillage et leur utilisation 1.517 + limitée à un seul ordinateur rendaient leur utilisation possible 1.518 + uniquement dans une très petite équipe. 1.519 + </para> 1.520 + 1.521 + <para id="x_8b">La seconde génération a assoupli ces contraintes en 1.522 + adoptant une architecture réseau et centralisée, permettant de gérer 1.523 + plusieurs projets entiers en même temps. Alors que les projets 1.524 + grandirent en taille, ils rencontrèrent de nouveaux problèmes. Avec les 1.525 + clients discutant régulièrement avec le serveurs, la montée en charge 1.526 + devint un réel problème sur les gros projets. Une connexion réseau peu 1.527 + fiable pouvait complètement empêcher les utilisateurs distants de 1.528 + dialoguer avec le serveur. Alors que les projets <emphasis remap="it">Open Source</emphasis> commencèrent à mettre en place des 1.529 + accès en lecture seule disponible anonymement, les utilisateurs sans 1.530 + les privilèges de <quote>commit</quote> réalisèrent qu'ils ne pouvaient 1.531 + pas utiliser les outils pour collaborer naturellement avec le projet, 1.532 + comme ils ne pouvaient pas non plus enregistrer leurs modifications. 1.533 + </para> 1.534 + 1.535 + <para id="x_8c">La génération actuelle des outils de gestion de source 1.536 + est <quote>peer-to-peer</quote> par nature. Tous ces systèmes ont 1.537 + abandonné la dépendance à un serveur central, et ont permis à leur 1.538 + utilisateur de distribuer les données de leur gestion de source à qui 1.539 + en a besoin. La collaboration à travers Internet a transformé la 1.540 + contrainte technologique en une simple question de choix et de 1.541 + consensus. Les outils modernes peuvent maintenant fonctionner en mode 1.542 + déconnecté sans limite et de manière autonome, la connexion au réseau 1.543 + n'étant nécessaire que pour synchroniser les modifications avec les 1.544 + autres dépôts. 1.545 + </para> 1.546 + </sect1> 1.547 + 1.548 + <sect1> 1.549 + <title>Quelques avantages des gestionnaires de source distribués</title> 1.550 + 1.551 + <para id="x_8d">Même si les gestionnaire de source distribués sont depuis 1.552 + plusieurs années assez robustes et aussi utilisables que leurs 1.553 + prédécesseurs, les utilisateurs d'autres outils n'y ont pas encore été 1.554 + sensibilisés. Les gestionnaires de source distribués se distinguent 1.555 + particulièrement de leurs équivalents centralisés de nombreuses 1.556 + manières. 1.557 + </para> 1.558 + 1.559 + <para id="x_8e">Pour un développeur individuel, ils restent beaucoup plus 1.560 + rapides que les outils centralisés. Cela pour une raison simple : un 1.561 + outil centralisé doit toujours dialoguer à travers le réseau pour la 1.562 + plupart des opérations, car presque toutes les métadonnées sont 1.563 + stockées sur la seule copie du serveur central. Un outil distribué 1.564 + stocke toute ses métadonnées localement. À tâche égale, effectuer un 1.565 + échange avec le réseau ajoute un délai aux outils centralisés. Ne 1.566 + sous-estimez pas la valeur d'un outil rapide : vous allez passer 1.567 + beaucoup de temps à interagir avec un logiciel de gestion de source. 1.568 + </para> 1.569 + 1.570 + <para id="x_8f">Les outils distribués sont complètement indépendants des 1.571 + aléas de votre serveur, d'autant plus qu'ils répliquent les métadonnées 1.572 + à beaucoup d'endroits. Si votre serveur central prend feu, vous avez 1.573 + intérêt à ce que les médias de sauvegardes soient fiables, et que votre 1.574 + dernier <quote>backup</quote> soit récent et fonctionne sans problème. 1.575 + Avec un outil distribué, vous avez autant de <quote>backup</quote> que 1.576 + de contributeurs. 1.577 + </para> 1.578 + 1.579 + <para id="x_90">En outre, la fiabilité de votre réseau affectera beaucoup 1.580 + moins les outils distribués. Vous ne pouvez même pas utiliser un outil 1.581 + centralisé sans connexion réseau, à l'exception de quelques commandes, 1.582 + très limitées. Avec un outil distribué, si votre connexion réseau tombe 1.583 + pendant que vous travaillez, vous pouvez ne même pas vous en rendre 1.584 + compte. La seule chose que vous ne serez pas capable de faire sera de 1.585 + communiquer avec des dépôts distants, opération somme toute assez rare 1.586 + en comparaison aux opérations locales. Si vous avez une équipe de 1.587 + collaborateurs très dispersée ceci peut être significatif. 1.588 + </para> 1.589 + 1.590 + <sect2> 1.591 + <title>Avantages pour les projets Open Source</title> 1.592 + 1.593 + <para id="x_91">Si vous prenez goût à un projet <emphasis remap="it">Open Source</emphasis> et que vous décidez de commencer 1.594 + à toucher à son code, et que le projet utilise un gestionnaire de 1.595 + source distribué, vous êtes immédiatement un "pair" avec les 1.596 + personnes formant le <quote>cœur</quote> du projet. S'ils publient 1.597 + leurs dépôts, vous pouvez immédiatement copier leurs historiques de 1.598 + projet, faire des modifications, enregistrer votre travail en 1.599 + utilisant les mêmes outils qu'eux. Par comparaison avec un outil 1.600 + centralisé, vous devez utiliser un logiciel en mode <quote>lecture 1.601 + seule</quote> à moins que quelqu'un ne vous donne les privilèges de 1.602 + <quote>commit</quote> sur le serveur central. Avant ça, vous ne serez 1.603 + pas capable d'enregistrer vos modifications, et vos propres 1.604 + modifications risqueront de se corrompre chaque fois que vous 1.605 + essayerez de mettre à jour à votre espace de travail avec le serveur 1.606 + central. 1.607 + </para> 1.608 + 1.609 + <sect3> 1.610 + <title>Le non-problème du "fork"</title> 1.611 + 1.612 + <para id="x_92">Il a été souvent suggéré que les gestionnaires de 1.613 + source distribués posent un risque pour les projets <emphasis remap="it">Open Source</emphasis> car ils facilitent grandement la 1.614 + création de <quote>fork</quote>. 1.615 + <!--footnote{NdT:Création d'une <ulink url="version alternative du 1.616 + logiciel">version alternative du 1.617 + logiciel</ulink>{http://fr.wikipedia.org/wiki/Fork#Embranchement_d.27un_projet_informatique} 1.618 + --> 1.619 + Un <quote>fork</quote> apparait quand il y des divergences d'opinion 1.620 + ou d'attitude au sein d'un groupe de développeurs qui aboutissent à 1.621 + la décision de ne plus travailler ensemble. Chaque parti s'empare 1.622 + d'une copie plus ou moins complète du code source du projet et 1.623 + continue dans sa propre direction. 1.624 + </para> 1.625 + 1.626 + 1.627 + <para id="x_93">Parfois ces différents partis décident de se 1.628 + réconcilier. Avec un serveur central, l'aspect 1.629 + <emphasis>technique</emphasis> de cette réconciliation est un 1.630 + processus douloureux, et essentiellement manuel. Vous devez décider 1.631 + quelle modification est <quote>la gagnante</quote>, et replacer, par 1.632 + un moyen ou un autre, les modifications de l'autre équipe dans 1.633 + l'arborescence du projet. Ceci implique généralement la perte d'une 1.634 + partie de l'historique d'un des partis, ou même des deux. 1.635 + </para> 1.636 + 1.637 + <para id="x_94">Ce que les outils distribués permettent à ce sujet est 1.638 + probablement la <emphasis>meilleure</emphasis> façon de développer un 1.639 + projet. Chaque modification que vous effectuez est potentiellement un 1.640 + <quote>fork</quote>. La grande force de cette approche est que les 1.641 + gestionnaires de source distribués doivent être vraiment très 1.642 + efficaces pour <emphasis>fusionner (merge)</emphasis> 1.643 + <!-- TODO footnote{NdT:j'ai choisi de traduire ici <emphasis 1.644 + remap="it">merging</emphasis> par <quote>fusionner</quote> pour des 1.645 + raisons de clarté} --> 1.646 + des <quote>forks</quote>, car les <quote>forks</quote>, dans ce 1.647 + contexte, arrivent tout le temps. 1.648 + </para> 1.649 + 1.650 + <para id="x_95">Si chaque altération que n'importe qui effectue, à tout 1.651 + moment, est vue comme un <quote>fork</quote> à fusionner, alors ce 1.652 + que le monde de l'<emphasis remap="it">Open Source</emphasis> voit 1.653 + comme un <quote>fork</quote> devient <emphasis>uniquement</emphasis> 1.654 + une problématique sociale. En fait, les outils de gestions de source 1.655 + distribués <emphasis>réduisent</emphasis> les chances de 1.656 + <quote>fork</quote> : 1.657 + </para> 1.658 + 1.659 + <itemizedlist> 1.660 + <listitem> 1.661 + <para>Ils éliminent la distinction sociale qu'imposent les outils 1.662 + centralisés entre les membres du projets (ceux qui ont accès au 1.663 + <quote>commit</quote>) et ceux de l'extérieur (ce qui ne l'ont 1.664 + pas). 1.665 + </para> 1.666 + <para>Ils rendent plus facile la réconciliation après un 1.667 + <quote>fork</quote> social, car tout ce qu'elle implique est une 1.668 + simple fusion. 1.669 + </para> 1.670 + </listitem> 1.671 + </itemizedlist> 1.672 + 1.673 + <para id="x_98">Certaines personnes font de la résistance envers les 1.674 + gestionnaires de source distribués parce qu'ils veulent garder un 1.675 + contrôle ferme sur leur projet, et ils pensent que les outils 1.676 + centralisés leur fournissent ce contrôle. Néanmoins, si c'est votre 1.677 + cas, sachez que si vous publiez votre dépôt CVS ou Subversion de 1.678 + manière publique, il existe une quantité d'outils disponibles pour 1.679 + récupérer entièrement votre projet et son historique (quoique 1.680 + lentement) et le récréer ailleurs, sans votre contrôle. En fait, 1.681 + votre contrôle sur votre projet est illusoire, vous ne faites 1.682 + qu'interdire à vos collaborateurs de travailler de manière fluide, en 1.683 + disposant d'un miroir ou d'un <quote>fork</quote> de votre 1.684 + historique. 1.685 + </para> 1.686 + 1.687 + </sect3> 1.688 + </sect2> 1.689 + <sect2> 1.690 + <title>Avantages pour les projets commerciaux</title> 1.691 + 1.692 + <para id="x_99">Beaucoup de projets commerciaux sont réalisés par des 1.693 + équipes éparpillées à travers le globe. Les contributeurs qui sont 1.694 + loin du serveur central devront subir des commandes lentes et même 1.695 + parfois peu fiables. Les solutions propriétaires de gestion de source 1.696 + tentent de palier ce problème avec des réplications de sites distants 1.697 + qui sont à la fois coûteuses à mettre en place et lourdes à 1.698 + administrer. Un système distribué ne souffre pas de ce genre de 1.699 + problèmes. En outre, il est très aisé de mettre en place plusieurs 1.700 + serveurs de références, disons un par site, de manière à ce qu'il n'y 1.701 + ait pas de communication redondante entre les dépôts, sur une 1.702 + connexion longue distance souvent onéreuse. 1.703 + </para> 1.704 + 1.705 + <para id="x_9a">Les systèmes de gestion de source supportent 1.706 + généralement assez mal la monté en charge. Il n'est pas rare pour un 1.707 + gestionnaire de source centralisé pourtant onéreux de s'effondrer 1.708 + sous la charge combinée d'une douzaine d'utilisateurs concurrents 1.709 + seulement. Une fois encore, la réponse à cette problématique est 1.710 + généralement encore la mise en place d'un ensemble complexe de 1.711 + serveurs synchronisés par un mécanisme de réplication. Dans le cas 1.712 + d'un gestionnaire de source distribué, la charge du serveur central 1.713 + — si vous avez un— est plusieurs fois inférieure (car 1.714 + toutes les données sont déjà répliquées ailleurs), un simple serveur, 1.715 + pas très cher, peut gérer les besoins d'une plus grande équipe, et la 1.716 + réplication pour balancer la charge devient le travail d'un simple 1.717 + script. 1.718 + </para> 1.719 + 1.720 + <para id="x_9b">Si vous avez des employés sur le terrain, en train de 1.721 + chercher à résoudre un souci sur le site d'un client, ils 1.722 + bénéficieront aussi d'un gestionnaire de source distribué. Cet outil 1.723 + leur permettra de générer des versions personnalisées, d'essayer 1.724 + différentes solutions, en les isolant aisément les unes des autres, 1.725 + et de rechercher efficacement à travers l'historique des sources, la 1.726 + cause des bugs ou des régressions, tout ceci sans avoir besoin de la 1.727 + moindre connexion au réseau de votre compagnie. 1.728 + </para> 1.729 + 1.730 + </sect2> 1.731 + </sect1> 1.732 + <sect1> 1.733 + <title>Pourquoi choisir Mercurial?</title> 1.734 + 1.735 + <para id="x_9c">Mercurial a plusieurs caractéristiques qui en font un 1.736 + choix particulièrement pertinent pour la gestion de source : 1.737 + </para> 1.738 + <itemizedlist> 1.739 + <listitem><para id="x_9d">Il est simple à apprendre et à utiliser.</para></listitem> 1.740 + <listitem><para id="x_9e">Il est léger.</para></listitem> 1.741 + <listitem><para id="x_9f">Il s'adapte très bien à la charge.</para></listitem> 1.742 + <listitem><para id="x_a0">Il se personnalise facilement.</para></listitem> 1.743 + </itemizedlist> 1.744 + 1.745 + <para id="x_a1">Si vous êtes déjà familier d'un outil de gestion de 1.746 + source, vous serez capable de l'utiliser en moins de 5 minutes. Sinon, 1.747 + ça ne sera pas beaucoup plus long. Les commandes utilisées par 1.748 + Mercurial, comme ses fonctionnalités, sont généralement uniformes et 1.749 + cohérentes, et vous pouvez ainsi garder en tête simplement quelques 1.750 + règles générales, plutôt qu'un lot complexe d'exceptions. 1.751 + </para> 1.752 + 1.753 + <para id="x_a2">Sur un petit projet, vous pouvez commencer à travailler 1.754 + avec Mercurial en quelques instants. Ajouter des modifications ou des 1.755 + branches, transférer ces modifications (localement ou via le réseau), 1.756 + et les opérations d'historique ou de statut sont aussi très rapides. 1.757 + Mercurial reste hors de votre chemin grâce à sa simplicité 1.758 + d'utilisation et sa rapidité d'exécution. 1.759 + </para> 1.760 + 1.761 + <para id="x_a3">L'utilité de Mercurial ne se limite pas à de petits 1.762 + projets: il est aussi utilisé par des projets ayant des centaines ou 1.763 + même des milliers de contributeurs, avec plusieurs dizaines de milliers 1.764 + de fichiers, et des centaines de méga octets de code source. 1.765 + </para> 1.766 + 1.767 + <para id="x_a4">Si les fonctionnalités au cœur de Mercurial ne sont pas 1.768 + suffisantes pour vous, il est très aisé d'en construire d'autres. 1.769 + Mercurial est adapté à l'utilisation de scripts, et son implémentation 1.770 + interne en Python, propre et claire, rend encore plus facile l'ajout de 1.771 + fonctionnalités sous forme d'extensions. Il en existe déjà un certain 1.772 + nombre de très populaires et très utiles, dont le périmètre va de la 1.773 + recherche de bugs à l'amélioration des performances. 1.774 + </para> 1.775 + 1.776 + </sect1> 1.777 + <sect1> 1.778 + <title>Mercurial comparé aux autres outils</title> 1.779 + 1.780 + <para id="x_a5">Avant que vous n'alliez plus loin, comprenez bien que 1.781 + cette section reflète mes propres expériences, et elle est donc (j'ose 1.782 + le dire) peu objective. Néanmoins, j'ai utilisé les outils de gestion 1.783 + de source listés ci dessous, dans la plupart des cas, pendant plusieurs 1.784 + années. 1.785 + </para> 1.786 + 1.787 + <sect2> 1.788 + <title>Subversion</title> 1.789 + 1.790 + <para id="x_a6">Subversion est un des outils de gestion de source les 1.791 + plus populaire, il fût développé pour remplacer CVS. Il a une 1.792 + architecture client/server centralisée. 1.793 + </para> 1.794 + 1.795 + <para id="x_a7">Subversion et Mercurial ont des noms de commandes très 1.796 + similaires pour les mêmes opérations, ainsi si vous êtes familier 1.797 + avec l'un, c'est facile d'apprendre l'autre. Ces deux outils sont 1.798 + portables sur les systèmes d'exploitation les plus populaires. 1.799 + </para> 1.800 + 1.801 + <para id="x_a8">Avant la version 1.5, Subversion n'offrait aucune forme 1.802 + de support pour les fusions. Lors de l'écriture de ce livre, ses 1.803 + 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"> 1.804 + complexes et buguées</ulink>. 1.805 + </para> 1.806 + 1.807 + <para id="x_a9">Mercurial dispose d'un avantage substantiel en terme de 1.808 + performance par rapport à Subversion sur la plupart des opérations 1.809 + que j'ai pu tester. J'ai mesuré une différence de performance allant 1.810 + de deux à six fois plus rapide avec le système de stockage de fichier 1.811 + local de Subversion 1.4.3 (<emphasis>ra_local</emphasis>), qui est la 1.812 + méthode d'accès la plus rapide disponible. Dans un déploiement plus 1.813 + réaliste, impliquant un stockage réseau, Subversion serait encore 1.814 + plus désavantagé. Parce que la plupart des commandes Subversion 1.815 + doivent communiquer avec le serveur et que Subversion n'a pas de 1.816 + mécanisme de réplication, la capacité du serveur et la bande passante 1.817 + sont devenues des goulots d'étranglement pour les projets de taille 1.818 + moyenne ou grande. 1.819 + </para> 1.820 + 1.821 + <para id="x_aa">En outre, Subversion implique une surcharge 1.822 + substantielle dans le stockage local de certaines données, pour 1.823 + éviter des transactions avec le serveur, pour certaines opérations 1.824 + communes, telles que la recherche des fichiers modifiés 1.825 + (<literal moreinfo="none">status</literal>) et l'affichage des modifications par 1.826 + rapport à la révision courante (<literal moreinfo="none">diff</literal>). En 1.827 + conséquence, un répertoire de travail Subversion a souvent la même 1.828 + taille, ou est plus grand, qu'un dépôt Mercurial et son espace de 1.829 + travail, et ceci bien que le dépôt Mercurial contienne l'intégralité 1.830 + de l'historique. 1.831 + </para> 1.832 + 1.833 + <para id="x_ab">Subversion est largement supporté par les outils 1.834 + tierces. Mercurial est actuellement encore en retrait de ce point de 1.835 + vue. L'écart se réduit néanmoins, en effet, certains des outils 1.836 + graphiques sont maintenant supérieurs à leurs équivalents Subversion. 1.837 + Comme Mercurial, Subversion dispose d'un excellent manuel 1.838 + utilisateur. 1.839 + </para> 1.840 + 1.841 + <para id="x_ac">Parce que Subversion ne stocke pas l'historique chez 1.842 + ses clients, il est parfaitement adapté à la gestion de projets qui 1.843 + doivent suivre un ensemble de larges fichiers binaires et opaques. Si 1.844 + vous suivez une cinquantaine de versions d'un fichier incompressible 1.845 + de 10MB, l'occupation disque coté client d'un projet sous Subversion 1.846 + restera à peu près constante. A l'inverse, l'occupation disque du 1.847 + même projet sous n'importe lequel des gestionnaires de source 1.848 + distribués grandira rapidement, proportionnellement aux nombres de 1.849 + versions, car les différences entre chaque révisions seront très 1.850 + grandes. 1.851 + </para> 1.852 + 1.853 + <para id="x_ad">En outre, c'est souvent difficile ou, généralement, 1.854 + impossible de fusionner des différences dans un fichier binaire. La 1.855 + capacité de Subversion de verrouiller des fichiers, pour permettre à 1.856 + l'utilisateur d'être le seul à le mettre à jour 1.857 + (<quote>commit</quote>) temporairement, est un avantage significatif 1.858 + dans un projet doté de beaucoup de fichiers binaires. 1.859 + </para> 1.860 + 1.861 + <para id="x_ae">Mercurial peut importer l'historique depuis un dépôt 1.862 + Subversion. Il peut aussi exporter l'ensemble des révisions d'un 1.863 + projet vers un dépôt Subversion. Ceci rend très facile de 1.864 + <quote>prendre la température</quote> et d'utiliser Mercurial et 1.865 + Subversion en parallèle, avant de décider de migrer vers Mercurial. 1.866 + La conversion de l'historique est incrémentale, donc vous pouvez 1.867 + effectuer une conversion initiale, puis de petites additions par la 1.868 + suite pour ajouter les nouvelle modifications. 1.869 + </para> 1.870 + 1.871 + 1.872 + </sect2> 1.873 + <sect2> 1.874 + <title>Git</title> 1.875 + 1.876 + <para id="x_af">Git est un outil de gestion de source distribué qui fût 1.877 + développé pour gérer le code source de noyau de Linux. Comme 1.878 + Mercurial, sa conception initiale a été inspirée par Monotone. 1.879 + </para> 1.880 + 1.881 + <para id="x_b0">Git dispose d'un ensemble conséquent de commandes, avec 1.882 + plus de 139 commandes individuelles pour la version 1.5.0. Il a aussi 1.883 + la réputation d'être difficile à apprendre. Comparé à Git, le point 1.884 + fort de Mercurial est clairement sa simplicité. 1.885 + </para> 1.886 + 1.887 + <para id="x_b1">En terme de performance, Git est extrêmement rapide. 1.888 + Dans la plupart des cas, il est plus rapide que Mercurial, tout du 1.889 + moins sur Linux, alors que Mercurial peut être plus performant sur 1.890 + d'autres opérations. Néanmoins, sur Windows, les performances et le 1.891 + niveau de support général fourni par Git, au moment de l'écriture de 1.892 + cet ouvrage, est bien derrière celui de Mercurial. 1.893 + </para> 1.894 + 1.895 + <para id="x_b2">Alors que le dépôt Mercurial ne demande aucune 1.896 + maintenance, un dépôt Git exige d'exécuter manuellement et 1.897 + régulièrement la commande <quote>repacks</quote> sur ses métadonnées. 1.898 + Sans ceci, les performances de git se dégradent et la consommation de 1.899 + l'espace disque augmente rapidement. Un serveur qui contient 1.900 + plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment 1.901 + <quote>repacked</quote> deviendra un vrai problème lors des 1.902 + <quote>backups</quote> du disque, et il y eu des cas, où un 1.903 + <quote>backup</quote> journalier pouvait durer plus de 24 heures. Un 1.904 + dépôt fraichement <quote>repacked</quote> sera légèrement plus petit 1.905 + qu'un dépôt Mercurial, mais un dépôt non <quote>repacked</quote> est 1.906 + beaucoup plus grand. 1.907 + </para> 1.908 + 1.909 + <para id="x_b3">Le cœur de Git est écrit en C. La plupart des commandes 1.910 + Git sont implémentées sous forme de scripts Shell ou Perl, et la 1.911 + qualité de ces scripts varie grandement. J'ai plusieurs fois constaté 1.912 + que certains de ces scripts étaient chargés en mémoire aveuglément et 1.913 + que la présence d'erreurs pouvait s'avérer fatal. 1.914 + </para> 1.915 + 1.916 + <para id="x_b4">Mercurial peut importer l'historique d'un dépôt Git.</para> 1.917 + 1.918 + </sect2> 1.919 + <sect2> 1.920 + <title>CVS</title> 1.921 + 1.922 + <para id="x_b5">CVS est probablement l'outil de gestion de source le 1.923 + plus utilisé aujourd'hui dans le monde. À cause de son manque de 1.924 + clarté interne, il n'est plus maintenu depuis plusieurs années. 1.925 + </para> 1.926 + 1.927 + <para id="x_b6">Il a une architecture client/serveur centralisée. Il ne 1.928 + regroupe pas les modifications de fichiers dans une opération de 1.929 + <quote>commit</quote> atomique, ce qui permet à ses utilisateurs de 1.930 + <quote>casser le <emphasis>build</emphasis></quote> assez facilement 1.931 + : une personne peut effectuer une opération de <quote>commit</quote> 1.932 + sans problème puis être bloquée par besoin de fusion, avec comme 1.933 + conséquence néfaste, que les autres utilisateurs ne récupèreront 1.934 + qu'une partie de ses modifications. Ce problème affecte aussi la 1.935 + manière de travailler avec l'historique du projet. Si vous voulez 1.936 + voir toutes les modifications d'une personne du projet, vous devrez 1.937 + injecter manuellement les descriptions et les <emphasis remap="it">timestamps</emphasis> des modifications de chacun des 1.938 + fichiers impliqués (si vous savez au moins quels sont ces fichiers). 1.939 + </para> 1.940 + 1.941 + <para id="x_b7">CVS a une notion étrange des <emphasis remap="it">tags</emphasis> et des branches que je n'essayerai même 1.942 + pas de décrire ici. Il ne supporte pas bien les opérations de 1.943 + renommage d'un fichier ou d'un répertoire, ce qui facilite la 1.944 + corruption de son dépôt. Il n'a presque pas pour ainsi dire de 1.945 + contrôle de cohérence interne, il est donc pratiquement impossible de 1.946 + dire si un dépôt est corrompu ni à quel point. Je ne recommanderai 1.947 + pas CVS pour un projet existant ou nouveau. 1.948 + </para> 1.949 + 1.950 + <para id="x_b8">Mercurial peut importer l'historique d'un projet CVS. 1.951 + Néanmoins, il y a quelques principes à respecter; ce qui est vrai 1.952 + aussi pour les autres outils d'import de projet CVS. À cause de 1.953 + l'absence de <quote>commit</quote> atomique et gestion de version de 1.954 + l'arborescence, il n'est pas possible de reconstruire de manière 1.955 + précise l'ensemble de l'historique. Un travail de 1.956 + <quote>devinette</quote> est donc nécessaire, et les fichiers 1.957 + renommés ne sont pas détectés. Parce qu'une bonne part de 1.958 + l'administration d'un dépôt CVS est effectuée manuellement, et est 1.959 + donc, sujette à erreur, il est courant que les imports CVS 1.960 + rencontrent de nombreux problèmes avec les dépôt corrompus (des 1.961 + <emphasis remap="it">timestamps</emphasis> de révision complètement 1.962 + buggés et des fichiers verrouillés depuis des années sont deux des 1.963 + problèmes les moins intéressants dont je me souvienne). 1.964 + </para> 1.965 + 1.966 + <para id="x_b9">Mercurial peut importer l'historique depuis un dépôt CVS. 1.967 + </para> 1.968 + 1.969 + 1.970 + </sect2> 1.971 + <sect2> 1.972 + <title>Outils propriétaires</title> 1.973 + 1.974 + <para id="x_ba">Perforce a une architecture client/serveur centralisée, 1.975 + sans aucun mécanisme de mise en cache de données coté client. 1.976 + Contrairement à la plupart des outils modernes de gestion de source, 1.977 + Perforce exige de ses utilisateurs d'exécuter une commande pour 1.978 + informer le serveur central de tout fichier qu'ils souhaitent 1.979 + modifier. 1.980 + </para> 1.981 + 1.982 + <para id="x_bb">Les performances de Perforce sont plutôt bonnes pour 1.983 + des petites équipes, mais elles s'effondrent rapidement lorsque le 1.984 + nombre d'utilisateurs augmente au delà de la douzaine. Des 1.985 + installations de Perforce assez larges nécessitent le déploiement de 1.986 + proxies pour supporter la montée en charge associée. 1.987 + </para> 1.988 + 1.989 + </sect2> 1.990 + <sect2> 1.991 + <title>Choisir un outil de gestion de source</title> 1.992 + 1.993 + <para id="x_bc">A l'exception de CVS, tous les outils listés ci-dessus 1.994 + ont des forces qui leur sont propres et qui correspondent à certaines 1.995 + formes de projet. Il n'y a pas un seul meilleur outil de gestion de 1.996 + source qui correspondrait le mieux à toutes les situations. 1.997 + </para> 1.998 + 1.999 + <para id="x_bd">En guise exemple, Subversion est un très bon choix 1.1000 + lorsqu'on travaille avec beaucoup de fichiers binaires, qui évoluent 1.1001 + régulièrement, grâce à sa nature centralisée et sa capacité à 1.1002 + verrouiller des fichiers. 1.1003 + </para> 1.1004 + 1.1005 + <para id="x_be">Personnellement, je préfère Mercurial pour sa 1.1006 + simplicité, ses performances et sa bonne capacité de fusion, et il 1.1007 + m'a très bien rendu service de plusieurs années maintenant. 1.1008 + </para> 1.1009 + 1.1010 + </sect2> 1.1011 + </sect1> 1.1012 + <sect1> 1.1013 + <title>Migrer depuis un outil à Mercurial</title> 1.1014 + 1.1015 + <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 1.1016 + importer des révisions depuis différents autres outils de gestion de 1.1017 + source. Par <quote>incrémental</quote>, j'entends que vous pouvez 1.1018 + convertir l'historique entier du projet en une seule fois, puis 1.1019 + relancer l'outil d'import plus tard pour obtenir les modifications 1.1020 + effectuées depuis votre import initial. 1.1021 + </para> 1.1022 + 1.1023 + <para id="x_c0">Les outils de gestion de source supportés par <literal role="hg-ext" moreinfo="none">convert</literal> sont : 1.1024 + </para> 1.1025 + <itemizedlist> 1.1026 + <listitem><para id="x_c1">Subversion</para></listitem> 1.1027 + <listitem><para id="x_c2">CVS</para></listitem> 1.1028 + <listitem><para id="x_c3">Git</para></listitem> 1.1029 + <listitem><para id="x_c4">Darcs</para></listitem> 1.1030 + </itemizedlist> 1.1031 + 1.1032 + <para id="x_c5">En outre, <literal role="hg-ext" moreinfo="none">convert</literal> peut 1.1033 + exporter les modifications depuis Mercurial vers Subversion. Ceci rend 1.1034 + possible d'essayer Subversion en parallèle avant de choisir une 1.1035 + solution définitive, sans aucun risque de perte de données. 1.1036 + </para> 1.1037 + 1.1038 + <para id="x_c6">La commande <command role="hg-ext-conver" moreinfo="none">convert</command> est très simple à utiliser. 1.1039 + Simplement, indiquez le chemin ou l'URL du dépôt de source, en lui 1.1040 + indiquant éventuellement le nom du chemin de destination, et la 1.1041 + conversion se met en route. Après cet import initial, il suffit de 1.1042 + relancer la commande encore une fois pour importer les modifications 1.1043 + effectuées depuis. 1.1044 + </para> 1.1045 + </sect1> 1.1046 + 1.1047 + <sect1> 1.1048 + <title>Une courte histoire de la gestion de source</title> 1.1049 + 1.1050 + <para id="x_c7">Le plus célèbre des anciens outils de gestion de source 1.1051 + est <emphasis remap="it">SCCS</emphasis> (Source Code Control System)}, 1.1052 + que Marc Rochkind conçu dans les laboratoires de recherche de Bell 1.1053 + (<emphasis remap="it">Bell Labs</emphasis>), dans le début des années 1.1054 + 70. <emphasis remap="it">SCCS</emphasis> ne fonctionnait que sur des 1.1055 + fichiers individuels, et obligeait chaque personne travaillant sur le 1.1056 + projet d'avoir un accès à un répertoire de travail commun, sur le même 1.1057 + système. Seulement une seule personne pouvait modifier un fichier au 1.1058 + même moment, ce fonctionnement était assuré par l'utilisation de verrou 1.1059 + (<quote>lock</quote>). Il était courant que des personnes verrouillent 1.1060 + des fichiers, et plus tard, oublient de le déverrouiller ; empêchant 1.1061 + n'importe qui d'autre de travailler sur ces fichiers sans l'aide de 1.1062 + l'administrateur... 1.1063 + </para> 1.1064 + 1.1065 + <para id="x_c8">Walter Tichy a développé une alternative libre à 1.1066 + <emphasis remap="it">SCCS</emphasis> au début des années 80, qu'il 1.1067 + nomma <emphasis remap="it">RCS (Revision Control System)</emphasis>. 1.1068 + Comme <emphasis remap="it">SCCS</emphasis>, <emphasis remap="it">RCS</emphasis> demandait aux développeurs de travailler 1.1069 + sur le même répertoire partagé, et de verrouiller les fichiers pour se 1.1070 + prémunir de tout conflit issu de modifications concurrentes. 1.1071 + </para> 1.1072 + 1.1073 + <para id="x_c9">Un peu plus tard dans les années 1980, Dick Grune utilisa 1.1074 + <emphasis remap="it">RCS</emphasis> comme une brique de base pour un 1.1075 + ensemble de scripts <emphasis remap="it">shell</emphasis> qu'il 1.1076 + intitula cmt, avant de la renommer en <emphasis remap="it">CVS 1.1077 + (Concurrent Versions System)</emphasis>. La grande innovation de CVS 1.1078 + était que les développeurs pouvaient travailler simultanément et 1.1079 + indépendamment dans leur propre espace de travail. Ces espaces de 1.1080 + travail privés assuraient que les développeurs ne se marchent pas 1.1081 + mutuellement sur les pieds, comme c'était souvent le cas avec RCS et 1.1082 + SCCS. Tous les développeurs disposaient donc de leur copie de tous les 1.1083 + fichiers du projet, et ils pouvaient donc librement les modifier. Ils 1.1084 + devaient néanmoins effectuer la <quote>fusion</quote> (<emphasis remap="it"><quote>merge</quote></emphasis>) de leurs fichiers, avant 1.1085 + d'effectuer le <quote>commit</quote> de leurs modifications sur le dépôt 1.1086 + central. 1.1087 + </para> 1.1088 + 1.1089 + <para>Brian Berliner reprit les scripts de Grune's et les réécrit en C, 1.1090 + qu'il publia en 1989. Depuis, ce code a été modifié jusqu'à devenir la 1.1091 + version moderne de CVS. CVS a acquis ainsi la capacité de fonctionner 1.1092 + en réseau, transformant son architecture en client/serveur. 1.1093 + L'architecture de CVS est centralisée, seul le serveur a une copie de 1.1094 + l'historique du projet. L'espace de travail client ne contient qu'une 1.1095 + copie de la dernière version du projet, et quelques métadonnées pour 1.1096 + indiquer où le serveur se trouve. CVS a été un grand succès, 1.1097 + aujourd'hui il est probablement l'outil de gestion de contrôle le plus 1.1098 + utilisé au monde. 1.1099 + </para> 1.1100 + 1.1101 + <para>Au début des années 1990, Sun Microsystems développa un premier 1.1102 + outil de gestion de source distribué, nommé TeamWare. Un espace de 1.1103 + travail TeamWare contient une copie complète de l'historique du projet. 1.1104 + TeamWare n'a pas de notion de dépôt central. (CVS utilisait RCS pour le 1.1105 + stockage de l'historique, TeamWare utilisait SCCS). 1.1106 + </para> 1.1107 + 1.1108 + <para>Alors que les années 1990 avançaient, les utilisateurs ont pris 1.1109 + conscience d'un certain nombre de problèmes avec CVS. Il enregistrait 1.1110 + simultanément des modifications sur différents fichiers 1.1111 + individuellement, au lieu de les regrouper dans une seule opération 1.1112 + cohérente et atomique. Il ne gère pas bien sa hiérarchie de fichier, il 1.1113 + est donc assez aisé de créer le chaos en renommant les fichiers et les 1.1114 + répertoires. Pire encore, son code source est difficile à lire et à 1.1115 + maintenir, ce qui agrandit largement le <quote>niveau de 1.1116 + souffrance</quote> associé à la réparation de ces problèmes 1.1117 + d'architecture de manière prohibitive. 1.1118 + </para> 1.1119 + 1.1120 + <para>En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient 1.1121 + travaillé sur CVS, initièrent un projet pour le remplacer par un outil 1.1122 + qui aurait une meilleure architecture et un code plus propre. Le 1.1123 + résultat, Subversion, ne quitte pas le modèle centralisé et 1.1124 + client/server de CVS, mais ajoute les opérations de 1.1125 + <quote>commit</quote> atomique sur de multiples fichiers, une meilleure 1.1126 + gestion des espaces de noms, et d'autres fonctionnalités qui en font un 1.1127 + meilleur outil que CVS. Depuis sa première publication, il est 1.1128 + rapidement devenu très populaire. 1.1129 + </para> 1.1130 + 1.1131 + <para>Plus ou moins simultanément, Graydon Hoare a commencé sur 1.1132 + l'ambitieux système de gestion distribué Monotone. Bien que Monotone 1.1133 + corrige plusieurs défauts de CVS tout en offrant une architecture 1.1134 + <quote>peer-to-peer</quote>, il va aussi plus loin que la plupart des 1.1135 + outils de révision de manière assez innovante. Il utilise des 1.1136 + <quote>hashs</quote> cryptographiques comme identifiants, et il a une 1.1137 + notion complète de <quote>confiance</quote> du code issu des 1.1138 + différentes sources. 1.1139 + </para> 1.1140 + 1.1141 + <para>Mercurial est né en 2005. Bien que très influencé par Monotone, 1.1142 + Mercurial se concentre sur la facilité d'utilisation, les performances 1.1143 + et la capacité à monter en charge pour de très gros projets. 1.1144 + </para> 1.1145 + 1.1146 + </sect1> 1.1147 + 1.1148 +</chapter> 1.1149 + 1.1150 +<!-- 1.1151 +local variables: 1.1152 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.1153 +end: 1.1154 +--> 1.1155 + 1.1156 + <!-- BEGIN ch02 --> 1.1157 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.1158 + 1.1159 +<chapter id="chap:tour-basic"> 1.1160 + <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?> 1.1161 + <title>Une rapide présentation de Mercurial : les bases</title> 1.1162 + 1.1163 + <sect1> 1.1164 + <title>Installer Mercurial sur votre système</title> 1.1165 + 1.1166 + <para id="x_1">Des paquetages binaires de Mercurial sont disponibles pour la 1.1167 + plupart des systèmes d'exploitation, ce qui rend facile l'utilisation 1.1168 + immédiate de Mercurial sur votre ordinateur.</para> 1.1169 + 1.1170 + <sect2> 1.1171 + <title>Windows</title> 1.1172 + 1.1173 + <para id="x_c">La meilleur version de Mercurial pour Windows est 1.1174 + 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>. 1.1175 + Ce logiciel n'a aucune dépendance exterieure; il fonctionne <quote>et 1.1176 + c'est tout</quote>. Il fournit aussi bien les outils en ligne de 1.1177 + commmande qu'une interface graphique.</para> 1.1178 + 1.1179 + </sect2> 1.1180 + 1.1181 + <sect2> 1.1182 + <title>Mac OS X</title> 1.1183 + 1.1184 + <para id="x_a">Lee Cantey publie un installeur de Mercurial pour Mac OS 1.1185 + X sur <ulink url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>.</para> 1.1186 + </sect2> 1.1187 + 1.1188 + <sect2> 1.1189 + <title>Linux</title> 1.1190 + 1.1191 + <para id="x_2">Parce que chaque distribution de Linux a ses propres 1.1192 + outils de gestion de paquets, politiques et rythmes de 1.1193 + développements, il est difficile de donner un ensemble 1.1194 + d'instructions unique pour installer les binaires de Mercurial. La 1.1195 + version de Mercurial avec laquelle vous vous retrouverez dépendra 1.1196 + grandement de l'activité de la personne en charge du paquetage pour 1.1197 + la distribution.</para> 1.1198 + 1.1199 + <para id="x_3">Pour rester simple, je me concentrerai sur 1.1200 + l'installation de Mercurial en ligne de commande, sous les 1.1201 + distributions les plus courantes. La plupart des distributions 1.1202 + fournissent des gestionnaires graphiques de paquetage qui vous 1.1203 + permettront d'installer Mercurial en quelques clicks. Le paquetage 1.1204 + devrait se nommer <literal moreinfo="none">mercurial</literal>.</para> 1.1205 + 1.1206 + <itemizedlist> 1.1207 + <listitem><para id="x_4">Ubuntu et Debian:</para> 1.1208 + <programlisting format="linespecific">apt-get install mercurial</programlisting></listitem> 1.1209 + <listitem><para id="x_5">Fedora:</para> 1.1210 + <programlisting format="linespecific">yum install mercurial</programlisting></listitem> 1.1211 + <listitem><para id="x_6">Gentoo:</para> 1.1212 + <programlisting format="linespecific">emerge mercurial</programlisting></listitem> 1.1213 + <listitem><para id="x_715">OpenSUSE:</para> 1.1214 + <programlisting format="linespecific">zypper install 1.1215 + mercurial</programlisting></listitem> 1.1216 + </itemizedlist> 1.1217 + 1.1218 + </sect2> 1.1219 + <sect2> 1.1220 + <title>Solaris</title> 1.1221 + 1.1222 + <para id="x_09">SunFreeWare, à <ulink url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>, 1.1223 + fournit des paquets précompilés pour Mercurial.</para> 1.1224 + </sect2> 1.1225 + </sect1> 1.1226 + 1.1227 + <sect1> 1.1228 + <title>Commencer à utiliser Mercurial</title> 1.1229 + 1.1230 + <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 1.1231 + installé proprement. Les informations affichées sur la version ne sont 1.1232 + pas réellement importantes en soit, c'est surtout de savoir si elles 1.1233 + s'affichent qui nous intéresse.</para> 1.1234 + 1.1235 + <!-- BEGIN tour.version --> 1.1236 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg version</userinput> 1.1237 +Mercurial Distributed SCM (version 1.2.1) 1.1238 + 1.1239 +Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others 1.1240 +This is free software; see the source for copying conditions. There is NO 1.1241 +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 1.1242 +</screen> 1.1243 +<!-- END tour.version --> 1.1244 + 1.1245 + 1.1246 + <sect2> 1.1247 + <title>L'aide intégrée</title> 1.1248 + 1.1249 + <para id="x_f">Mercurial fournit un système d'aide intégré, ce qui est 1.1250 + inestimable quand vous vous retrouvez coincé à essayer de vous 1.1251 + rappeler comment lancer une commande. Si vous êtes bloqué, exécutez 1.1252 + simplement <command role="hg-cmd" moreinfo="none">hg help</command>; elle affichera 1.1253 + une brève liste des commandes, avec une description pour chacune. Si 1.1254 + vous demandez de l'aide sur une commande spécifique (voir 1.1255 + ci-dessous), elle affichera des informations plus détaillées.</para> 1.1256 + 1.1257 + <!-- BEGIN tour.help --> 1.1258 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help init</userinput> 1.1259 +hg init [-e CMD] [--remotecmd CMD] [DEST] 1.1260 + 1.1261 +create a new repository in the given directory 1.1262 + 1.1263 + Initialize a new repository in the given directory. If the given 1.1264 + directory does not exist, it is created. 1.1265 + 1.1266 + If no directory is given, the current directory is used. 1.1267 + 1.1268 + It is possible to specify an ssh:// URL as the destination. 1.1269 + See 'hg help urls' for more information. 1.1270 + 1.1271 +options: 1.1272 + 1.1273 + -e --ssh specify ssh command to use 1.1274 + --remotecmd specify hg command to run on the remote side 1.1275 + 1.1276 +use "hg -v help init" to show global options 1.1277 +</screen> 1.1278 +<!-- END tour.help --> 1.1279 + 1.1280 + 1.1281 + <para id="x_10">Pour un niveau d'informations encore plus détaillé 1.1282 + (ce dont vous aurez rarement besoin), exécuter <command role="hg-cmd" moreinfo="none">hg 1.1283 + help <option role="hg-opt-global">-v</option></command>. L'option 1.1284 + <option role="hg-opt-global">-v</option> est l'abréviation de 1.1285 + <option role="hg-opt-global">--verbose</option>, et indique à Mercurial 1.1286 + d'ficher plus d'informations que d'habitude.</para> 1.1287 + 1.1288 + </sect2> 1.1289 + </sect1> 1.1290 + <sect1> 1.1291 + <title>Travailler avec un dépôt</title> 1.1292 + 1.1293 + <para id="x_11">Avec Mercurial, tout se déroule au sein du 1.1294 + <emphasis>dépôt</emphasis>. Le dépôt d'un projet contient tous 1.1295 + les fichiers qui <quote>appartiennent</quote> au projet.</para> 1.1296 + 1.1297 + <para id="x_12">Il n'y a rien de particulièrement magique au sujet de 1.1298 + ce dépôt, c'est simplement une arborescence sur votre système de fichiers 1.1299 + que Mercurial traite de manière spéciale. Vous pouvez renommer ou effacer 1.1300 + ce répertoire à n'impporte quel moment, en utilisant la ligne de commande 1.1301 + ou votre explorateur de fichiers.</para> 1.1302 + 1.1303 + <sect2> 1.1304 + <title>Faire une copie locale de votre dépôt</title> 1.1305 + 1.1306 + <para id="x_13"><emphasis>Copier</emphasis> un dépôt est juste un 1.1307 + peu spécial. Bien que vous puissiez utiliser une commande habituelle de 1.1308 + copie pour copier votre dépôt, il vaut mieux utiliser une commande fournie par 1.1309 + Mercurial. Cette commande est appelée <command role="hg-cmd" moreinfo="none">hg clone</command>, 1.1310 + car elle crée une copie identique à un dépôt existant.</para> 1.1311 + 1.1312 + <!-- BEGIN tour.clone --> 1.1313 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone http://hg.serpentine.com/tutorial/hello</userinput> 1.1314 +destination directory: hello 1.1315 +requesting all changes 1.1316 +adding changesets 1.1317 +adding manifests 1.1318 +adding file changes 1.1319 +added 5 changesets with 5 changes to 2 files 1.1320 +updating working directory 1.1321 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.1322 +</screen> 1.1323 +<!-- END tour.clone --> 1.1324 + 1.1325 + 1.1326 + <para id="x_67c">Un avantage de la commande <command role="hg-cmd" moreinfo="none">hg 1.1327 + clone</command> est que, comme nous l'avons vu ci dessus, elle nous 1.1328 + permet de faire de cloner les dépôts à travers le réseau. Un autre 1.1329 + est qu'elle se rappelle d'où a été cloné un dépôt, ce qui est utile 1.1330 + quand on veut mettre à jour le clone.</para> 1.1331 + 1.1332 + <para id="x_14">Si votre opération de clonage réussit, vous devriez maintenant 1.1333 + avoir un répertoire local appelé <filename class="directory" moreinfo="none">hello</filename>. 1.1334 + Ce répertoire contiendra quelques fichiers.</para> 1.1335 + 1.1336 + <!-- BEGIN tour.ls --> 1.1337 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput> 1.1338 +total 4 1.1339 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:05 hello 1.1340 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls hello</userinput> 1.1341 +Makefile hello.c 1.1342 +</screen> 1.1343 +<!-- END tour.ls --> 1.1344 + 1.1345 + 1.1346 + <para id="x_15">Ces fichiers ont le même contenu et historique dans votre dépôt 1.1347 + qu'ils ont dans le dépôt que vous avez cloné.</para> 1.1348 + 1.1349 + <para id="x_16">Chaque dépôt Mercurial est complet, autonome et 1.1350 + indépendant. Il contient sa propre copie privée des fichiers du 1.1351 + projet et de leur historique. Le clone d'un dépôt se souvient de la 1.1352 + localisation du dépôt à partir duquel il a été clôné, mais il ne 1.1353 + communique pas avec ce dernier, ou un autre, à moins que vous ne lui 1.1354 + demandiez.</para> 1.1355 + 1.1356 + <para id="x_17">Ce que tout ceci signifie pour le moment est que nous 1.1357 + sommes libres d'expérimenter avec ce dépôt, confiants dans le fait 1.1358 + qu'il s'agit d'un <quote>bac à sable</quote> qui n'affectera personne 1.1359 + d'autre.</para> 1.1360 + 1.1361 + </sect2> 1.1362 + <sect2> 1.1363 + <title>Quel est le contenu d'un dépôt ?</title> 1.1364 + 1.1365 + <para id="x_18">Prêtons plus attention un instant au contenu d'un dépôt. 1.1366 + Nous voyons qu'il contient un répertoire nommé <filename class="directory" moreinfo="none">.hg 1.1367 + </filename>. C'est ici que Mercurial conserve toutes ses 1.1368 + métadonnées.</para> 1.1369 + 1.1370 + <!-- BEGIN tour.ls-a --> 1.1371 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello</userinput> 1.1372 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -a</userinput> 1.1373 +. .. .hg Makefile hello.c 1.1374 +</screen> 1.1375 +<!-- END tour.ls-a --> 1.1376 + 1.1377 + 1.1378 + <para id="x_19">Le contenu du répertoire <filename class="directory" moreinfo="none">.hg 1.1379 + </filename> et ses sous répertoires sont les seuls propres à Mercurial. 1.1380 + Tous les autres fichiers et répertoires dans le dépôt sont à vous, et 1.1381 + vous pouvez en faire ce que vous voulez.</para> 1.1382 + 1.1383 + <para id="x_1a">Pour introduire un peu de terminologie, le répertoire 1.1384 + <filename class="directory" moreinfo="none">.hg</filename> est un <quote>vrai</quote> 1.1385 + dépôt, et tous les fichiers et les répertoires qui coexistent avec lui, 1.1386 + sont désignés sous le nom <emphasis>espace de travail</emphasis>. Une 1.1387 + manière facile de se rappeler cette distinction est de retenir que le 1.1388 + <emphasis>dépôt</emphasis> contient l'<emphasis>historique</emphasis> 1.1389 + de votre projet, alors que l'<emphasis>espace de travail</emphasis> 1.1390 + contient un "<emphasis>snapshot</emphasis>" de votre projet à un certain 1.1391 + point de son historique.</para> 1.1392 + 1.1393 + </sect2> 1.1394 + </sect1> 1.1395 + <sect1> 1.1396 + <title>Une promenade dans l'historique</title> 1.1397 + 1.1398 + <para id="x_1b">Une des premières choses que vous aurez envie 1.1399 + de faire avec un nouveau dépôt, sera de comprendre son historique. 1.1400 + La commande <command role="hg-cmd" moreinfo="none">hg log</command> vous donne une 1.1401 + vue de l'historique.</para> 1.1402 + 1.1403 + <!-- BEGIN tour.log --> 1.1404 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput> 1.1405 +changeset: 4:2278160e78d4 1.1406 +tag: tip 1.1407 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1408 +date: Sat Aug 16 22:16:53 2008 +0200 1.1409 +summary: Trim comments. 1.1410 + 1.1411 +changeset: 3:0272e0d5a517 1.1412 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1413 +date: Sat Aug 16 22:08:02 2008 +0200 1.1414 +summary: Get make to generate the final binary from a .o file. 1.1415 + 1.1416 +changeset: 2:fef857204a0c 1.1417 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1418 +date: Sat Aug 16 22:05:04 2008 +0200 1.1419 +summary: Introduce a typo into hello.c. 1.1420 + 1.1421 +changeset: 1:82e55d328c8c 1.1422 +user: mpm@selenic.com 1.1423 +date: Fri Aug 26 01:21:28 2005 -0700 1.1424 +summary: Create a makefile 1.1425 + 1.1426 +changeset: 0:0a04b987be5a 1.1427 +user: mpm@selenic.com 1.1428 +date: Fri Aug 26 01:20:50 2005 -0700 1.1429 +summary: Create a standard "hello, world" program 1.1430 + 1.1431 +</screen> 1.1432 +<!-- END tour.log --> 1.1433 + 1.1434 + 1.1435 + <para id="x_1c">Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque 1.1436 + révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous 1.1437 + appelons chacun de ces évènements enregistrés un <emphasis>changeset</emphasis>, parce 1.1438 + qu'il contient un ensemble de modifications sur plusieurs fichiers.</para> 1.1439 + 1.1440 + <para id="x_1d">La commande <command role="hg-cmd" moreinfo="none">hg log</command> affiche 1.1441 + ainsi ces informations :</para> 1.1442 + 1.1443 + <itemizedlist> 1.1444 + <listitem><para id="x_1e"><literal moreinfo="none">changeset</literal> : Ce champ contient 1.1445 + un nombre, séparé par deux points (:), d'une chaine hexadécimale. Il 1.1446 + s'agit en fait d'<emphasis>identifiants</emphasis> d'un changeset. Il y a 1.1447 + deux identifiants car le numéro de la révision est plus court et plus à 1.1448 + facile à saisir qu'une séquence hexadécimale.</para> 1.1449 + </listitem> 1.1450 + <listitem><para id="x_1f"><literal moreinfo="none">user</literal> : L'identité de la personne 1.1451 + qui a créée ce %%% laisser le terme anglais car il sera affiché 1.1452 + changeset. C'est un champ libre de forme, mais la plupart du 1.1453 + temps il contient le nom et l'email de la personne.</para> 1.1454 + </listitem> 1.1455 + <listitem><para id="x_20"><literal moreinfo="none">date</literal> : La date et l'heure à 1.1456 + laquelle le \textit{changeset} a été créé, ainsi que le fuseau horaire dans 1.1457 + lequelle il a été créé. (La date et l'heure sont locales à ce 1.1458 + \textit{fuseau}, elles indiquent donc quelle date et heure il était 1.1459 + pour la personne qui a créé ce changeset.</para> 1.1460 + </listitem> 1.1461 + <listitem><para id="x_21"><literal moreinfo="none">résumé</literal>: La première ligne du 1.1462 + message que le créateur a associé à son changeset pour le décrire.</para> 1.1463 + </listitem> 1.1464 + <listitem><para id="x_67d">Certains changesets, comme le premier de la 1.1465 + liste ci-dessus ont un champ <literal moreinfo="none">tag</literal>. Le tag est une autre 1.1466 + façon d'identifier un changeset en lui donnant un nom simple à retenir. 1.1467 + (Le tag nommé <literal moreinfo="none">tip</literal> est spécial : il fait toujours 1.1468 + référence aux derniers changements dans le dépôt.)</para></listitem> 1.1469 + </itemizedlist> 1.1470 + 1.1471 + <para id="x_22">Par défaut, la commande <command role="hg-cmd" moreinfo="none">hg log</command> 1.1472 + n'affiche qu'un résumé, il manque beaucoup de détails.</para> 1.1473 + 1.1474 + <para id="x_23">La figure <xref linkend="fig:tour-basic:history"/> fournit une 1.1475 + représentation graphique de l'historique du dépôt <filename class="directory" moreinfo="none">hello 1.1476 + </filename>, pour rendre plus facile de voir dans quelle direction 1.1477 + l'historique se <quote>déroule</quote>. Nous reviendrons régulièrement 1.1478 + sur cette représentation dans ce chapitre et ceux qui suivent.</para> 1.1479 + 1.1480 + 1.1481 + <figure id="fig:tour-basic:history" float="0"> 1.1482 + <title>Graphical history of the <filename class="directory" moreinfo="none">hello</filename> repository</title> 1.1483 + <mediaobject> 1.1484 + <imageobject><imagedata fileref="figs/tour-history.png"/></imageobject> 1.1485 + <textobject><phrase>XXX add text</phrase></textobject> 1.1486 + </mediaobject> 1.1487 + </figure> 1.1488 + 1.1489 + 1.1490 + <sect2> 1.1491 + <title>Changesets, révisions, et collaboration</title> 1.1492 + 1.1493 + <para id="x_25">Comme l'anglais est réputé pour être un langage maladroit, 1.1494 + et que l'informatique est la source de bien des erreurs de terminologie 1.1495 + (pourquoi utiliser un seul terme quand quatre feront l'affaire ?), la 1.1496 + gestion de version a une variété de mots et de phrases qui veulent dire 1.1497 + la même chose. Si vous discutez d'historique de Mercurial avec d'autres 1.1498 + personnes, vous constaterez que souvent, le mot <quote>changeset</quote> 1.1499 + est contracté simplement en <quote>change</quote> ou (à l'écrit) 1.1500 + <quote>cset</quote>, et même parfois un changeset 1.1501 + <quote>révision</quote>, abrégé en <quote>rev</quote>.</para> 1.1502 + 1.1503 + <para id="x_26">Bien que le <emphasis>mot</emphasis> que vous utilisez pour 1.1504 + désigner le concept de changeset importe peu, l'<emphasis>identifiant</emphasis> 1.1505 + que vous utilisez pour désigner un <emphasis>changeset</emphasis> spécifique 1.1506 + a une grande importance. Rappelez vous que le champ changeset affiché par la 1.1507 + commande <command role="hg-cmd" moreinfo="none">hg log</command> identifie un changeset à 1.1508 + la fois avec un numéro de révision et une séquence hexadécimale.</para> 1.1509 + 1.1510 + <itemizedlist> 1.1511 + <listitem><para id="x_27">Le numéro de révision est <emphasis>seulement 1.1512 + valable dans ce dépôt</emphasis>,</para></listitem> 1.1513 + <listitem><para id="x_28">La séquence hexadécimale est un 1.1514 + <emphasis>identifiant permanent, et invariant</emphasis> qui 1.1515 + pourra toujours être associé au changeset exact de <emphasis>chaque</emphasis> 1.1516 + copie de votre dépôt.</para></listitem></itemizedlist> 1.1517 + 1.1518 + <para id="x_29">La distinction est importante. Si vous envoyez un email 1.1519 + à quelqu'un en parlant de la <quote>révision 33</quote>, il est très 1.1520 + probable que sa révision 33 <emphasis>ne sera pas la même</emphasis> 1.1521 + que la votre. La raison de ceci est que le numéro de révision dépend 1.1522 + de l'ordre dans lequel les modifications sont arrivées dans le dépôt, 1.1523 + et il n'y a aucune garantie que les mêmes changements soient arrivés 1.1524 + dans le même ordre dans différents dépôts. Trois modifications 1.1525 + <literal moreinfo="none">a,b,c</literal> peuvent aisément apparaitre dans un dépôt 1.1526 + comme <literal moreinfo="none">0,1,2</literal>, et dans un autre comme <literal moreinfo="none">0,2,1 1.1527 + </literal>.</para> 1.1528 + 1.1529 + <para id="x_2a">Mercurial utilise les numéros de révision uniquement comme des raccourcis 1.1530 + pratiques. Si vous devez discuter d'un \textit{changeset} avec quelqu'un, 1.1531 + ou identifer un \textit{changeset} pour une quelconque raison (par exemple, 1.1532 + un rapport de \textit{bug}), utilisez la séquence hexadécimale.</para> 1.1533 + 1.1534 + </sect2> 1.1535 + <sect2> 1.1536 + <title>Afficher une révision spécifique</title> 1.1537 + 1.1538 + <para id="x_2b">Pour réduire la sortie de <command role="hg-cmd" moreinfo="none">hg log 1.1539 + </command> à une seule révision, utilisez l'option <option role="hg-opt-log">-r 1.1540 + </option> (ou <option role="hg-opt-log">--rev</option>). Vous pouvez utiliser 1.1541 + le numéro de révision ou la séquence hexadécimale comme identifiant, et 1.1542 + demander autant de révisions que vous le souhaitez.</para> 1.1543 + 1.1544 + <!-- BEGIN tour.log-r --> 1.1545 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 3</userinput> 1.1546 +changeset: 3:0272e0d5a517 1.1547 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1548 +date: Sat Aug 16 22:08:02 2008 +0200 1.1549 +summary: Get make to generate the final binary from a .o file. 1.1550 + 1.1551 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 0272e0d5a517</userinput> 1.1552 +changeset: 3:0272e0d5a517 1.1553 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1554 +date: Sat Aug 16 22:08:02 2008 +0200 1.1555 +summary: Get make to generate the final binary from a .o file. 1.1556 + 1.1557 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 1 -r 4</userinput> 1.1558 +changeset: 1:82e55d328c8c 1.1559 +user: mpm@selenic.com 1.1560 +date: Fri Aug 26 01:21:28 2005 -0700 1.1561 +summary: Create a makefile 1.1562 + 1.1563 +changeset: 4:2278160e78d4 1.1564 +tag: tip 1.1565 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1566 +date: Sat Aug 16 22:16:53 2008 +0200 1.1567 +summary: Trim comments. 1.1568 + 1.1569 +</screen> 1.1570 +<!-- END tour.log-r --> 1.1571 + 1.1572 + 1.1573 + <para id="x_2c">Si vous voulez voir l'historique de plusieurs révisions 1.1574 + sans avoir à les énumérer, vous pouvez utiliser la <emphasis>intervalle 1.1575 + de numérotation</emphasis> qui vous permet d'exprimer l'idée <quote>je 1.1576 + veux toutes les révisions entre $a$ et $b$, inclus</quote></para> 1.1577 + 1.1578 + <!-- BEGIN tour.log.range --> 1.1579 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 2:4</userinput> 1.1580 +changeset: 2:fef857204a0c 1.1581 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1582 +date: Sat Aug 16 22:05:04 2008 +0200 1.1583 +summary: Introduce a typo into hello.c. 1.1584 + 1.1585 +changeset: 3:0272e0d5a517 1.1586 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1587 +date: Sat Aug 16 22:08:02 2008 +0200 1.1588 +summary: Get make to generate the final binary from a .o file. 1.1589 + 1.1590 +changeset: 4:2278160e78d4 1.1591 +tag: tip 1.1592 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1593 +date: Sat Aug 16 22:16:53 2008 +0200 1.1594 +summary: Trim comments. 1.1595 + 1.1596 +</screen> 1.1597 +<!-- END tour.log.range --> 1.1598 + 1.1599 + 1.1600 + <para id="x_2d">Mercurial respecte aussi l'ordre dans lequel vous spécifiez 1.1601 + les révisions, ainsi <command role="hg-cmd" moreinfo="none">hg log -r 2:4</command> 1.1602 + affichera <literal moreinfo="none">2,3,4</literal> alors que <command role="hg-cmd" moreinfo="none">hg 1.1603 + log -r 4:2</command> affichera <literal moreinfo="none">4,3,2</literal>.</para> 1.1604 + 1.1605 + </sect2> 1.1606 + <sect2> 1.1607 + <title>Informations détaillées</title> 1.1608 + 1.1609 + <para id="x_2e">Le résumé affiché par <command role="hg-cmd" moreinfo="none">hg log</command> 1.1610 + est suffisant si vous savez déjà ce que vous cherchez. En 1.1611 + revanche, vous aurez probablement besoin de voir une description 1.1612 + complète du changement, ou une liste des fichiers modifiés si vous 1.1613 + cherchez à déterminer qu'un changeset est bien celui que vous 1.1614 + recherchez. L'option \hgopt{-v} de la commande <command role="hg-cmd" moreinfo="none">hg 1.1615 + log</command> (ou <option role="hp-opt-global">--verbose</option>) vous 1.1616 + donne ces informations supplémentaires.</para> 1.1617 + 1.1618 + <!-- BEGIN tour.log-v --> 1.1619 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -r 3</userinput> 1.1620 +changeset: 3:0272e0d5a517 1.1621 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1622 +date: Sat Aug 16 22:08:02 2008 +0200 1.1623 +files: Makefile 1.1624 +description: 1.1625 +Get make to generate the final binary from a .o file. 1.1626 + 1.1627 + 1.1628 +</screen> 1.1629 +<!-- END tour.log-v --> 1.1630 + 1.1631 + 1.1632 + <para id="x_2f">Si vous voulez voir à la fois la description 1.1633 + et le contenu d'une modification, ajouter l'option <option role="hg-opt-log">-p</option> (ou <option role="hg-opt-log"> 1.1634 + --patch</option>). Ceci affiche le contenu d'une modification 1.1635 + comme un <emphasis>diff unifié</emphasis> 1.1636 + <!-- \footnote{NdT: \textit{unified diff}} --> 1.1637 + (si vous n'avez jamais vu de diff unifié avant, consultez la 1.1638 + section <xref linkend="sec:mq:patch"/> pour un rapide 1.1639 + survol).</para> 1.1640 + 1.1641 + <!-- BEGIN tour.log-vp --> 1.1642 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -p -r 2</userinput> 1.1643 +changeset: 2:fef857204a0c 1.1644 +user: Bryan O'Sullivan <bos@serpentine.com> 1.1645 +date: Sat Aug 16 22:05:04 2008 +0200 1.1646 +files: hello.c 1.1647 +description: 1.1648 +Introduce a typo into hello.c. 1.1649 + 1.1650 + 1.1651 +diff -r 82e55d328c8c -r fef857204a0c hello.c 1.1652 +--- a/hello.c Fri Aug 26 01:21:28 2005 -0700 1.1653 ++++ b/hello.c Sat Aug 16 22:05:04 2008 +0200 1.1654 +@@ -11,6 +11,6 @@ 1.1655 + 1.1656 + int main(int argc, char **argv) 1.1657 + { 1.1658 +- printf("hello, world!\n"); 1.1659 ++ printf("hello, world!\"); 1.1660 + return 0; 1.1661 + } 1.1662 + 1.1663 +</screen> 1.1664 +<!-- END tour.log-vp --> 1.1665 + 1.1666 + 1.1667 + <para id="x_67e">L'option <option role="hg-opt-log">-p</option> est 1.1668 + incroyablement utile, il est donc important dans s'en rappeller.</para> 1.1669 + 1.1670 + </sect2> 1.1671 + </sect1> 1.1672 + <sect1> 1.1673 + <title>Tout sur les options de commandes</title> 1.1674 + 1.1675 + <para id="x_30">Avant d'aller plus loin sur le fonctionnement 1.1676 + des commandes de Mercurial, étudions un moment comment elles 1.1677 + fonctionnent de manière générale. Vous trouverez ça probablement 1.1678 + utile pour la suite de notre parcours.</para> 1.1679 + 1.1680 + <para id="x_31">Mercurial utilise une approche directe et cohérente 1.1681 + pour interpréter les options que vous passez aux commandes. Il suit une 1.1682 + convention commune à la plupart des systèmes Unix et Linux modernes.</para> 1.1683 + 1.1684 + <itemizedlist> 1.1685 + <listitem><para id="x_32">Chaque option a un nom complet. Par exemple, 1.1686 + comme nous l'avons déjà vu, la commande <command role="hg-cmd" moreinfo="none">hg 1.1687 + log</command> accepte l'option <option role="hg-opt-log">--rev 1.1688 + </option>.</para> 1.1689 + </listitem> 1.1690 + <listitem><para id="x_33">La plupart des options disposent de 1.1691 + noms abrégés. Aussi, au lieu d'utiliser <option role="hg-opt-log">--rev 1.1692 + </option>, vous pouvez utiliser <option role="hg-opt-log">-r</option>. 1.1693 + (Les options qui n'ont pas de noms abrégés sont généralement 1.1694 + rarement utilisées).</para> 1.1695 + </listitem> 1.1696 + <listitem><para id="x_34">Les noms complets commencent par deux 1.1697 + tirets (i.e. <option role="hg-opt-log">--rev</option>), 1.1698 + alors que les options courtes commencent avec un seul (i.e. 1.1699 + <option role="hg-opt-log">-r</option>).</para> 1.1700 + </listitem> 1.1701 + <listitem><para id="x_35">Les noms des options sont cohérents 1.1702 + entre les commandes. Par exemple, chaque commande qui accepte 1.1703 + 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 1.1704 + </option> comme arguments.</para> 1.1705 + </listitem> 1.1706 + </itemizedlist> 1.1707 + 1.1708 + <para id="x_36">Dans les exemples de ce livre, j'utilise les noms abrégés 1.1709 + plutôt que les noms complets. Ceci est une préférence personnelle, pas 1.1710 + une recommandation.</para> 1.1711 + 1.1712 + <para id="x_37">La plupart des commandes qui affichent une quelconque sortie 1.1713 + à l'écran, afficheront davantage avec l'option <option role="hg-opt-global"> 1.1714 + -v</option> (ou <option role="hg-opt-global">--verbose</option>), et 1.1715 + moins avec l'option <option role="hg-opt-global">-q</option> (ou 1.1716 + <option role="hg-opt-global">--quiet</option>).</para> 1.1717 + 1.1718 + <note> 1.1719 + <title>Option naming consistency</title> 1.1720 + 1.1721 + <para id="x_680">Presque toujours, les commandes de Mercurial utilisent 1.1722 + des noms d'options cohérentes pour référer à des concepts identiques. 1.1723 + Par exemple, si une commande concerne les changesets, vous les 1.1724 + identifierez toujours avec l'option <option role="hg-opt-log">-r</option>. 1.1725 + Cette utilisation cohérente des noms d'options permet de mémoriser plus 1.1726 + facilement quelles options accepte une commande.</para> 1.1727 + </note> 1.1728 + 1.1729 + 1.1730 + </sect1> 1.1731 + <sect1> 1.1732 + <title>Faire et vérifier des modifications</title> 1.1733 + 1.1734 + <para id="x_38">Maintenant que nous avons une bonne idée des 1.1735 + commandes pour consulter l'historique de Mercurial, regardons 1.1736 + comment faire des modifications et les examiner.</para> 1.1737 + 1.1738 + <para id="x_39">La première chose que nous allons faire c'est isoler notre 1.1739 + 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 1.1740 + une copie de dépôt distant. Comme nous avons déjà une copie locale, nous 1.1741 + pouvons juste faire un clone de celle-ci à la place. C'est beaucoup plus 1.1742 + rapide que de faire une copie à travers le réseau, et un dépôt cloné 1.1743 + localement prend également moins d'espace disque<footnote> 1.1744 + <para id="x_681">L'économie d'espace disque apparait clairement quand les 1.1745 + dépôts source et destination sont sur le même système de fichier, où, dans 1.1746 + ce cas, Mercurial utilisera des liens physiques pour effectuer des partages 1.1747 + copie-lors-des-écritures de ses métadonnées internes. Si cette explication 1.1748 + ne signifie rien pour vous, ne vous inquietez pas : tout ceci se passe de 1.1749 + manière transparente et automatiquement. Vous n'avez pas du tout besoin de 1.1750 + comprendre ceci.</para></footnote>.</para> 1.1751 + 1.1752 + <!-- BEGIN tour.reclone --> 1.1753 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.1754 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-hello</userinput> 1.1755 +updating working directory 1.1756 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.1757 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput> 1.1758 +</screen> 1.1759 +<!-- END tour.reclone --> 1.1760 + 1.1761 + 1.1762 + <para id="x_3a">On notera au passage qu'il est souvent considéré comme 1.1763 + une bonne pratique de conserver une copie <quote>immaculée</quote> 1.1764 + du dépôt distant, à partir de laquelle vous pourrez faire des 1.1765 + copies locales temporaires pour créer des <quote>bacs à sable</quote> 1.1766 + pour chaque tâche sur laquelle vous souhaitez travailler. Ceci 1.1767 + vous permet de travailler sur plusieurs choses en parallèle, 1.1768 + chacune isolée les unes des autres en attendant que ces tâches 1.1769 + soient finies et que vous soyez prêt à les réintégrer. Parce 1.1770 + que les copies locales sont peu coûteuses, il est très rapide 1.1771 + de créer ou détruire des dépôts dès que vous n'en avez plus 1.1772 + besoin.</para> 1.1773 + 1.1774 + <para id="x_3b">Dans notre dépôt <filename class="directory" moreinfo="none">my-hello</filename>, nous avons un fichier 1.1775 + <filename moreinfo="none">hello.c</filename> qui contient le classique <quote>hello, 1.1776 + world</quote>.</para> 1.1777 + 1.1778 + <!-- BEGIN tour.cat1 --> 1.1779 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> 1.1780 +/* 1.1781 + * Placed in the public domain by Bryan O'Sullivan. This program is 1.1782 + * not covered by patents in the United States or other countries. 1.1783 + */ 1.1784 + 1.1785 +#include <stdio.h> 1.1786 + 1.1787 +int main(int argc, char **argv) 1.1788 +{ 1.1789 + printf("hello, world!\"); 1.1790 + return 0; 1.1791 +} 1.1792 +</screen> 1.1793 +<!-- END tour.cat1 --> 1.1794 + 1.1795 + 1.1796 + <para id="x_682">Editons ce fichier pour qu'il affiche une autre ligne 1.1797 + sur la sortie standard.</para> 1.1798 + 1.1799 + <!-- BEGIN tour.cat2 --> 1.1800 +<screen format="linespecific"># ... edit edit edit ... 1.1801 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> 1.1802 +/* 1.1803 + * Placed in the public domain by Bryan O'Sullivan. This program is 1.1804 + * not covered by patents in the United States or other countries. 1.1805 + */ 1.1806 + 1.1807 +#include <stdio.h> 1.1808 + 1.1809 +int main(int argc, char **argv) 1.1810 +{ 1.1811 + printf("hello, world!\"); 1.1812 + printf("hello again!\n"); 1.1813 + return 0; 1.1814 +} 1.1815 +</screen> 1.1816 +<!-- END tour.cat2 --> 1.1817 + 1.1818 + 1.1819 + <para id="x_3c">La commande Mercurial <command role="hg-cmd" moreinfo="none">hg 1.1820 + status</command> nous dira ce que Mercurial sait des fichiers du 1.1821 + dépôts.</para> 1.1822 + 1.1823 + <!-- BEGIN tour.status --> 1.1824 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput> 1.1825 +Makefile hello.c 1.1826 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.1827 +M hello.c 1.1828 +</screen> 1.1829 +<!-- END tour.status --> 1.1830 + 1.1831 + 1.1832 + <para id="x_3d">La commande <command role="hg-cmd" moreinfo="none">hg status</command> 1.1833 + n'affichera pas le contenu des fichiers, mais une ligne commençant par 1.1834 + <quote><literal moreinfo="none">M</literal></quote> pour <filename moreinfo="none">hello.c</filename>. 1.1835 + A moins que vous lui demandiez, la commande <command role="hg-cmd" moreinfo="none">hg 1.1836 + status</command> n'affichera aucune information sur les fichiers que 1.1837 + vous n'avez pas modifiés.</para> 1.1838 + 1.1839 + <para id="x_3e">Le <quote><literal moreinfo="none">M</literal></quote> indique que 1.1840 + Mercurial a remarqué que nous avons modifié le fichier 1.1841 + <filename moreinfo="none">hello.c</filename>. Nous n'avons pas besoin 1.1842 + <emphasis>d'informer</emphasis> Mercurial que nous allons modifier un 1.1843 + fichier avant de commencer à le faire, ou que nous avons modifié un 1.1844 + fichier après avoir commencé à le faire, il est capable de découvrir ça 1.1845 + tout seul. </para> 1.1846 + 1.1847 + <para id="x_3f">C'est déjà pratique de savoir que nous avons modifié le 1.1848 + fichier <filename moreinfo="none">hello.c</filename>, mais nous préférerions savoir 1.1849 + exactement <emphasis>ce que</emphasis> nous avons changé. Pour ceci, nous 1.1850 + utilisons la commande <command role="hg-cmd" moreinfo="none">hg diff</command>.</para> 1.1851 + 1.1852 + <!-- BEGIN tour.diff --> 1.1853 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> 1.1854 +diff -r 2278160e78d4 hello.c 1.1855 +--- a/hello.c Sat Aug 16 22:16:53 2008 +0200 1.1856 ++++ b/hello.c Sun Aug 16 14:05:26 2009 +0000 1.1857 +@@ -8,5 +8,6 @@ 1.1858 + int main(int argc, char **argv) 1.1859 + { 1.1860 + printf("hello, world!\"); 1.1861 ++ printf("hello again!\n"); 1.1862 + return 0; 1.1863 + } 1.1864 +</screen> 1.1865 +<!-- END tour.diff --> 1.1866 + 1.1867 + 1.1868 + <tip> 1.1869 + <title>Comprendre les patches</title> 1.1870 + 1.1871 + <para id="x_683">Penser à jeter un oeil à <xref linkend="sec:mq:patch"/> si vous n'arrivez pas à lire la sortie 1.1872 + ci-dessus.</para> 1.1873 + </tip> 1.1874 + </sect1> 1.1875 + <sect1> 1.1876 + <title>Enregister vos modifications dans une nouvelle révision</title> 1.1877 + 1.1878 + <para id="x_40">Nous pouvons modifier des fichiers, compiler et tester 1.1879 + nos modifications, et utiliser les commandes <command role="hg-cmd" moreinfo="none">hg 1.1880 + status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command> pour 1.1881 + voir les modifications effectuées, jusqu'à ce que nous soyons assez 1.1882 + satisfaits pour décider d'enregistrer notre travail dans un 1.1883 + \textit{changeset}.</para> 1.1884 + 1.1885 + <para id="x_41">La commande <command role="hg-cmd" moreinfo="none">hg commit</command> 1.1886 + vous laisse créer une nouvelle révision, nous désignerons généralement 1.1887 + cette opération par <quote>faire un commit</quote> ou 1.1888 + <quote>committer</quote>.</para> 1.1889 + 1.1890 + <sect2> 1.1891 + <title>Définir le nom d'utilisateur</title> 1.1892 + 1.1893 + <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 1.1894 + pas garanti qu'elle réussisse du premier coup. En effet, Mercurial 1.1895 + enregistre votre nom et votre adresse avec chaque modification que 1.1896 + vous effectuez, de manière à ce que vous soyez capable (ou d'autres 1.1897 + le soient) de savoir qui a fait quelle modification. Mercurial essaye 1.1898 + automatiquement de découvrir un nom d'utilisateur qui ait un minimum 1.1899 + de sens pour effectuer l'opération de commit avec. Il va essayer 1.1900 + chacune des méthodes suivantes, dans l'ordre :</para> 1.1901 + 1.1902 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.1903 + <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 1.1904 + d'utilisateur, ceci aura toujours la priorité sur les autres 1.1905 + méthodes ci dessous.</para></listitem> 1.1906 + <listitem><para id="x_44">Si vous avez défini une variable 1.1907 + d'environnement <envar>HGUSER</envar>, c'est cette valeur qui est 1.1908 + alors utilisée.</para></listitem> 1.1909 + <listitem><para id="x_45">Si vous créez un fichier nommé <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire 1.1910 + \textit{home}, avec une entrée <envar role="rc-item-ui">username</envar>, c'est la valeur associée 1.1911 + qui sera utilisée. Pour voir à quoi ressemble le contenu de ce 1.1912 + fichier regardez la section <xref linkend="sec:tour-basic:username"/> 1.1913 + ci-dessous.</para></listitem> 1.1914 + <listitem><para id="x_46">Si vous avez défini une variable 1.1915 + d'environnement <envar>EMAIL</envar> celle ci sera utilisée 1.1916 + ensuite.</para></listitem> 1.1917 + <listitem><para id="x_47">Enfin, Mercurial interrogera votre système 1.1918 + pour trouver votre nom d'utilisateur local ainsi que le nom de la 1.1919 + machine hôte, et il fabriquera un nom d'utilisateur à partir de 1.1920 + ces données. Comme il arrive souvent que ce genre de noms soit 1.1921 + totalement inutile, il vous préviendra en affichant un message 1.1922 + d'avertissement.</para></listitem> 1.1923 + </orderedlist> 1.1924 + 1.1925 + <para id="x_48">Si tous ces mécanismes échouent, Mercurial n'exécutera 1.1926 + pas la commande, affichant un message d'erreur. Dans ce cas, il ne 1.1927 + vous laissera pas effectuer de commit tant que vous n'aurez pas 1.1928 + défini un nom d'utilisateur.</para> 1.1929 + 1.1930 + <para id="x_49">Vous devriez penser à utiliser la variable 1.1931 + d'environement <envar>HGUSER</envar> et l'option <option role="hg-opt-commit">-u</option> comme moyen pour 1.1932 + <emphasis>changer</emphasis> le nom d'utilisateur par défaut. Pour 1.1933 + une utilisation normale, la manière la plus simple et robuste 1.1934 + d'opérer est de créer un fichier <filename role="special" moreinfo="none">.hgrc</filename>, voir ci-dessous pour les détails 1.1935 + à ce sujet.</para> 1.1936 + 1.1937 + <sect3 id="sec:tour-basic:username"> 1.1938 + <title>Créer un fichier de configuration pour Mercurial</title> 1.1939 + 1.1940 + <para id="x_4a">Pour définir un nom d'utilisateur, utilisez votre 1.1941 + éditeur de texte favori pour créer un fichier <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire home. 1.1942 + Mercurial va utiliser ce fichier pour retrouver votre 1.1943 + configuration personnelle. Le contenu initial devrait 1.1944 + ressembler à ceci :</para> 1.1945 + 1.1946 + <tip> 1.1947 + <title><quote>Home directory</quote> sous Windows</title> 1.1948 + 1.1949 + <para id="x_716">Quand on parle de répertoire home, sur une version 1.1950 + anglaise d'une installation de Windows, il s'agira habituellement 1.1951 + d'un répertoire nommée comme votre nom dans <filename moreinfo="none">C:\Documents 1.1952 + and Settings</filename>. Vous pouvez trouver de quelle répertoire 1.1953 + il s'agit en lançant une fenêtre d'interpréteur de commande et en 1.1954 + exécutant la commande suivante :</para> 1.1955 + 1.1956 + <screen format="linespecific"><prompt moreinfo="none">C:\</prompt> <userinput moreinfo="none">echo 1.1957 + %UserProfile</userinput></screen> 1.1958 + </tip> 1.1959 + 1.1960 + <programlisting format="linespecific"># This is a Mercurial configuration file. 1.1961 +[ui] 1.1962 +username = Firstname Lastname <email.address@domain.net></programlisting> 1.1963 + 1.1964 + <para id="x_4b">La ligne avec <literal moreinfo="none">[ui]</literal> commence une 1.1965 + <emphasis>section</emphasis> du fichier de configuration, ainsi la ligne 1.1966 + <quote><literal moreinfo="none">username = ...</literal></quote> signifie <quote> 1.1967 + définir la valeur de l'élément <literal moreinfo="none">username</literal> dans la 1.1968 + section <literal moreinfo="none">ui</literal></quote>. Une section continue jusqu'à ce 1.1969 + qu'une nouvelle commence, ou que la fin du fichier soit atteinte. 1.1970 + Mercurial ignore les lignes vides et traite tout texte situé à la suite 1.1971 + d'un <quote><literal moreinfo="none">#</literal></quote> jusqu'à la fin de la ligne 1.1972 + comme un commentaire.</para> 1.1973 + 1.1974 + </sect3> 1.1975 + <sect3> 1.1976 + <title>Choisir un nom d'utilisateur</title> 1.1977 + 1.1978 + <para id="x_4c">Vous pouvez utiliser n'importe quelle valeur 1.1979 + pour votre <literal moreinfo="none">username</literal>, car cette information 1.1980 + est destinée à d'autres personnes et non à être interprétée 1.1981 + par Mercurial. La convention que la plupart des personnes 1.1982 + suivent est d'utiliser leurs noms suivies de leurs adresses emails, 1.1983 + comme montré ci-dessus :</para> 1.1984 + <note> 1.1985 + <para id="x_4d">Le mécanisme interne du serveur web intégré à Mercurial, 1.1986 + masque les adresses emails, pour rendre plus difficile leurs 1.1987 + récupérations par les outils utilisés par les spammmers. 1.1988 + Ceci réduit la probabilité que de recevoir encore plus de 1.1989 + spam si vous vous publiez un dépôt sur internet.</para> 1.1990 + </note> 1.1991 + </sect3> 1.1992 + </sect2> 1.1993 + <sect2> 1.1994 + <title>Rédiger un message de \textit{commit}</title> 1.1995 + 1.1996 + <para id="x_4e">Lorsqu'on effectue une opération de commit, Mercurial 1.1997 + lance automatiquement un éditeur de texte pour permettre de saisir 1.1998 + un message qui décrira les modifications effectuées dans cette 1.1999 + révision. Ce message est nommé le <emphasis>message de commit</emphasis>. 1.2000 + Ce sera un enregistrement pour tout lecteur expliquant le pourquoi 1.2001 + et le comment de vos modifications, et il sera affiché par la 1.2002 + commande <command role="hg-cmd" moreinfo="none">hg log</command>.</para> 1.2003 + 1.2004 + <!-- BEGIN tour.commit --> 1.2005 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit</userinput> 1.2006 +</screen> 1.2007 +<!-- END tour.commit --> 1.2008 + 1.2009 + 1.2010 + <para id="x_4f">L'éditeur que la commande <command role="hg-cmd" moreinfo="none">hg 1.2011 + commit</command> déclenche ne contiendra qu'une ligne vide suivi 1.2012 + d'un certain nombre de lignes commençant par <quote><literal moreinfo="none">HG: 1.2013 + </literal></quote>.</para> 1.2014 + 1.2015 + <programlisting format="linespecific"> 1.2016 + This is where I type my commit comment. 1.2017 + 1.2018 + HG: Enter commit message. Lines beginning with 'HG:' are removed. 1.2019 + HG: -- 1.2020 + HG: user: Bryan O'Sullivan <bos@serpentine.com> 1.2021 + HG: branch 'default' 1.2022 + HG: changed hello.c</programlisting> 1.2023 + 1.2024 + 1.2025 + <para id="x_50">Mercurial ignore les lignes qui commencent 1.2026 + avec <quote><literal moreinfo="none">HG:</literal></quote>, il ne les 1.2027 + utilise que pour nous indiquer quels fichiers modifiés il se 1.2028 + prépare à \textit{commiter}. Modifier ou effacer ces lignes n'a 1.2029 + aucune conséquence sur l'opération de commit. 1.2030 + </para> 1.2031 + 1.2032 + </sect2> 1.2033 + <sect2> 1.2034 + <title>Rédiger un message \textit{approprié}</title> 1.2035 + 1.2036 + <para id="x_51">Comme <command role="hg-cmd" moreinfo="none">hg log</command> n'affiche 1.2037 + que la première ligne du message de commit par défaut, il est souvent 1.2038 + considéré comme une bonne pratique de rédiger des messages de commit 1.2039 + qui tiennent sur une seule ligne. Voilà un exemple concret de message 1.2040 + de commit qui <emphasis>ne suit pas</emphasis> cette directive, et 1.2041 + qui a donc un résumé peu lisible.</para> 1.2042 + 1.2043 + <programlisting format="linespecific"> 1.2044 +changeset: 73:584af0e231be 1.2045 +user: Censored Person <censored.person@example.org> 1.2046 +date: Tue Sep 26 21:37:07 2006 -0700 1.2047 +summary: include buildmeister/commondefs. Add an exports and install 1.2048 + </programlisting> 1.2049 + 1.2050 + <para id="x_52">A ce sujet, il faut noter qu'il n'existe pas de règle 1.2051 + absolue dans ce domaine. Mercurial lui-même n'interprète pas les 1.2052 + contenus des messages de commit, ainsi votre projet est libre de 1.2053 + concevoir différentes politiques de mise en page des messages.</para> 1.2054 + 1.2055 + <para id="x_53">Ma préférence personnelle va au message court, mais 1.2056 + informatif, qui offre des précisions supplémentaires par rapport à ce 1.2057 + que pourrait m'apprendre une commande <command role="hg-cmd" moreinfo="none">hg log 1.2058 + --patch</command>.</para> 1.2059 + 1.2060 + <para id="x_55">Si vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg 1.2061 + commit</command> sans aucun argument, elle enregistre tous les 1.2062 + changements qui ont été fait, et qui sont indiqué par les commandes 1.2063 + <command role="hg-cmd" moreinfo="none">hg status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command>.</para> 1.2064 + 1.2065 + <note> 1.2066 + <title>Une surprise pour les utilisateurs habitués à Subversion</title> 1.2067 + 1.2068 + <para id="x_717">Comme n'importe quel autre commande de Mercurial, si 1.2069 + vous soumettez pas de manière explicite les noms des fichiers à 1.2070 + committer à la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, elle 1.2071 + va travailler sur l'ensemble du répertoire de travail. Soyez conscient 1.2072 + de ceci si vous venez du monde Subversion ou CVS, car vous pourriez 1.2073 + attendre qu'elle opère uniquement le répertoire courant et ses sous 1.2074 + répertoires.</para> 1.2075 + </note> 1.2076 + </sect2> 1.2077 + <sect2> 1.2078 + <title>Annuler un \textit{commit}</title> 1.2079 + 1.2080 + <para id="x_54">Si, en rédigeant le message, vous décidez que 1.2081 + finalement vous ne voulez pas effectuer ce commit, il suffit 1.2082 + de quitter simplement l'éditeur sans sauver. Ceci n'aura aucune 1.2083 + conséquence sur le dépôt ou les fichiers du répertoire de 1.2084 + travail.</para> 1.2085 + </sect2> 1.2086 + 1.2087 + <sect2> 1.2088 + <title>Admirer votre travail</title> 1.2089 + 1.2090 + <para id="x_56">Une fois que votre \textit{commit} est terminé, vous 1.2091 + pouvez utiliser la commande <command role="hg-cmd" moreinfo="none">hg tip</command> 1.2092 + pour afficher le \textit{changeset} que vous venez de créer. Cette 1.2093 + commande produit une sortie à l'écran qui est identique à celle du 1.2094 + <command role="hg-cmd" moreinfo="none">hg log</command>, mais qui n'affiche que la 1.2095 + dernière révision du dépôt.</para> 1.2096 + 1.2097 + <!-- BEGIN tour.tip --> 1.2098 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -vp</userinput> 1.2099 +changeset: 5:c94f208d1dfb 1.2100 +tag: tip 1.2101 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2102 +date: Sun Aug 16 14:05:26 2009 +0000 1.2103 +files: hello.c 1.2104 +description: 1.2105 +Added an extra line of output 1.2106 + 1.2107 + 1.2108 +diff -r 2278160e78d4 -r c94f208d1dfb hello.c 1.2109 +--- a/hello.c Sat Aug 16 22:16:53 2008 +0200 1.2110 ++++ b/hello.c Sun Aug 16 14:05:26 2009 +0000 1.2111 +@@ -8,5 +8,6 @@ 1.2112 + int main(int argc, char **argv) 1.2113 + { 1.2114 + printf("hello, world!\"); 1.2115 ++ printf("hello again!\n"); 1.2116 + return 0; 1.2117 + } 1.2118 + 1.2119 +</screen> 1.2120 +<!-- END tour.tip --> 1.2121 + 1.2122 + 1.2123 + <para id="x_57">On fait couramment référence à la dernière révision 1.2124 + du dépôt comme étant la <emphasis>révision tip</emphasis>, ou plus 1.2125 + simplement le <emphasis>tip</emphasis>.</para> 1.2126 + 1.2127 + <para id="x_684">Au passage, la commande <command role="hg-cmd" moreinfo="none">hg 1.2128 + tip</command> accepte la plupart des options qu'accepte 1.2129 + <command role="hg-cmd" moreinfo="none">hg log</command>. Ainsi <option role="hg-opt-global">-v</option> ci dessus implique <quote>soit 1.2130 + verbeux</quote>, <option role="hg-opt-tip">-p</option> 1.2131 + veux dire <quote>affiche le patch</quote>. L'utilisation de l'option 1.2132 + <option role="hg-opt-tip">-p</option> pour afficher un patch est un 1.2133 + autre exemple de la cohérence des commandes évoquée plus tôt.</para> 1.2134 + 1.2135 + </sect2> 1.2136 + </sect1> 1.2137 + <sect1> 1.2138 + <title>Partager ses modifications</title> 1.2139 + 1.2140 + <para id="x_58">Nous avons mentionné plus haut que les dépôts 1.2141 + de Mercurial sont autosuffisants. Ce qui signifie que la nouvelle 1.2142 + révision que vous venez de créer existe seulement dans votre 1.2143 + répertoire <filename class="directory" moreinfo="none">my-hello</filename>. Étudions 1.2144 + comment propager cette modification dans d'autres dépôts.</para> 1.2145 + 1.2146 + <sect2 id="sec:tour:pull"> 1.2147 + <title>Récupérer les modifications d'autres dépôts</title> 1.2148 + 1.2149 + <para id="x_59">Pour commencer, construisons un clone de notre dépôt 1.2150 + <filename class="directory" moreinfo="none">hello</filename> qui ne contiendra pas 1.2151 + le changement que nous venons d'effectuer. Nous l'appellerons notre 1.2152 + dépôt temporaire <filename class="directory" moreinfo="none">hello-pull</filename>.</para> 1.2153 + 1.2154 + <!-- BEGIN tour.clone-pull --> 1.2155 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.2156 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-pull</userinput> 1.2157 +updating working directory 1.2158 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.2159 +</screen> 1.2160 +<!-- END tour.clone-pull --> 1.2161 + 1.2162 + 1.2163 + <para id="x_5a">Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg pull</command> pour envoyer les modifications 1.2164 + depuis <filename class="directory" moreinfo="none">my-hello</filename> dans <filename class="directory" moreinfo="none">hello-pull</filename>. Néanmoins, récupérer 1.2165 + aveuglement des modifications depuis un dépôt a quelque chose d'un 1.2166 + peu effrayant. Mercurial propose donc une commande <command role="hg-cmd" moreinfo="none">hg incoming</command> qui permet de savoir quelles 1.2167 + modifications la commande <command role="hg-cmd" moreinfo="none">hg pull</command> 1.2168 + <emphasis>pourrait</emphasis> entraîner dans notre dépôt, et ceci 1.2169 + sans effectuer réellement de modification dessus.</para> 1.2170 + 1.2171 + <!-- BEGIN tour.incoming --> 1.2172 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello-pull</userinput> 1.2173 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg incoming ../my-hello</userinput> 1.2174 +comparing with ../my-hello 1.2175 +searching for changes 1.2176 +changeset: 5:c94f208d1dfb 1.2177 +tag: tip 1.2178 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2179 +date: Sun Aug 16 14:05:26 2009 +0000 1.2180 +summary: Added an extra line of output 1.2181 + 1.2182 +</screen> 1.2183 +<!-- END tour.incoming --> 1.2184 + 1.2185 + 1.2186 + <para id="x_5c">Apporter les modifications rapatriées dans un dépôt se 1.2187 + résume donc à exécuter la commande <command role="hg-cmd" moreinfo="none">hg 1.2188 + pull</command>, et préciser depuis quel dépôt effectuer le <command role="hg-cmd" moreinfo="none">hg pull</command>.</para> 1.2189 + 1.2190 + <!-- BEGIN tour.pull --> 1.2191 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.2192 +changeset: 4:2278160e78d4 1.2193 +tag: tip 1.2194 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2195 +date: Sat Aug 16 22:16:53 2008 +0200 1.2196 +summary: Trim comments. 1.2197 + 1.2198 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput> 1.2199 +pulling from ../my-hello 1.2200 +searching for changes 1.2201 +adding changesets 1.2202 +adding manifests 1.2203 +adding file changes 1.2204 +added 1 changesets with 1 changes to 1 files 1.2205 +(run 'hg update' to get a working copy) 1.2206 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.2207 +changeset: 5:c94f208d1dfb 1.2208 +tag: tip 1.2209 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2210 +date: Sun Aug 16 14:05:26 2009 +0000 1.2211 +summary: Added an extra line of output 1.2212 + 1.2213 +</screen> 1.2214 +<!-- END tour.pull --> 1.2215 + 1.2216 + 1.2217 + <para id="x_5d">Comme vous le voyez avec une sortie avant et après de la 1.2218 + commande <command role="hg-cmd" moreinfo="none">hg tip</command>, nous avons réussi à 1.2219 + récupérer aisément les modifications dans notre dépôt. Il reste néanmoins 1.2220 + quelque chose à faire avant de placer ces modifications dans l'espace de 1.2221 + travail.</para> 1.2222 + 1.2223 + <tip> 1.2224 + <title>Récupérer des changements précis</title> 1.2225 + 1.2226 + <para id="x_5b">Il est possible à cause du délai entre l'exécution de la 1.2227 + commande <command role="hg-cmd" moreinfo="none">hg incoming</command> et l'exécution de 1.2228 + la commande <command role="hg-cmd" moreinfo="none">hg pull</command>, que vous ne 1.2229 + puissiez pas voir toutes les modifications que vous rapporterez d'un 1.2230 + autre dépôt. Supposons que vous récupériez les modifications d'un dépôt 1.2231 + situé quelque part sur le réseau. Alors que vous regardez le résultat de 1.2232 + la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>, et avant que 1.2233 + vous ne décidiez de récupérer ces modifications, quelqu'un peut ajouter 1.2234 + de nouvelles révisions dans le dépôt distant. Ce qui signifie que vous 1.2235 + récupérez plus de révision que ce que vous aviez regardées en utilisant 1.2236 + la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>.</para> 1.2237 + 1.2238 + <para id="x_718">Si vous voulez seulement récupérer ce que vous aviez 1.2239 + vérifier à l'aide de la commande <command role="hg-cmd" moreinfo="none">hg 1.2240 + incoming</command>, ou que pour d'autres raisons vous souhaitiez ne 1.2241 + récupérer qu'un sous ensemble des révisions supplémentaires 1.2242 + disponibles, indiquant simplement les modifications que vous souhaitez 1.2243 + récupérer par leurs ID de révision, soit <command moreinfo="none">hg pull 1.2244 + -r7e95bb</command>. </para> 1.2245 + </tip> 1.2246 + 1.2247 + </sect2> 1.2248 + <sect2> 1.2249 + <title>Mise à jour de l'espace de travail</title> 1.2250 + 1.2251 + <para id="x_5e">Nous avons jusqu'à maintenant grossièrement défini la 1.2252 + 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 1.2253 + <xref linkend="sec:tour:pull"/> a apporté des modifications, que nous 1.2254 + avons vérifiées, dans notre dépôt, mais il n'y a aucune trace de ces 1.2255 + 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 1.2256 + de travail. C'est la commande <command role="hg-cmd" moreinfo="none">hg update</command> 1.2257 + qui s'en charge.</para> 1.2258 + 1.2259 + <!-- BEGIN tour.update --> 1.2260 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput> 1.2261 + printf("hello, world!\"); 1.2262 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update tip</userinput> 1.2263 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.2264 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput> 1.2265 + printf("hello, world!\"); 1.2266 + printf("hello again!\n"); 1.2267 +</screen> 1.2268 +<!-- END tour.update --> 1.2269 + 1.2270 + 1.2271 + <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 1.2272 + automatiquement. Il y a en fait une très bonne raison à cela : vous 1.2273 + pouvez utilisez la commande <command role="hg-cmd" moreinfo="none">hg update</command> 1.2274 + pour mettre à jour votre espace de travail à l'état dans lequel il était 1.2275 + à <emphasis>n'importe quelle révision</emphasis> de l'historique du dépôt. 1.2276 + Si vous aviez un espace de travail contenant une ancienne 1.2277 + révision—pour chercher l'origine d'un bug, par exemple—et 1.2278 + que vous effectuiez un <command role="hg-cmd" moreinfo="none">hg pull</command> qui 1.2279 + mettrait à jour automatiquement votre espace de travail, vous ne seriez 1.2280 + probablement pas très satisfait.</para> 1.2281 + 1.2282 + <para id="x_60">Néanmoins, comme les opérations de pull sont très souvent 1.2283 + suivies d'un update, Mercurial vous permet de combiner les 1.2284 + deux aisément en passant l'option <option role="hg-opt-pull">-u</option> 1.2285 + à la commande <command role="hg-cmd" moreinfo="none">hg pull</command>.</para> 1.2286 + 1.2287 + <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 1.2288 + <option role="hg-opt-pull">-u</option>, vous pouvez constater qu'elle a 1.2289 + affiché un rappel assez utile : vous devez encore effectuer une 1.2290 + opération pour mettre à jour votre espace de travail.</para> 1.2291 + 1.2292 + <para id="x_62">Pour découvrir sur quelle révision de l'espace de 1.2293 + travail on se trouve, utilisez la commande <command role="hg-cmd" moreinfo="none">hg 1.2294 + parents</command>.</para> 1.2295 + 1.2296 + <!-- BEGIN tour.parents --> 1.2297 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.2298 +changeset: 5:c94f208d1dfb 1.2299 +tag: tip 1.2300 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2301 +date: Sun Aug 16 14:05:26 2009 +0000 1.2302 +summary: Added an extra line of output 1.2303 + 1.2304 +</screen> 1.2305 +<!-- END tour.parents --> 1.2306 + 1.2307 + 1.2308 + <para id="x_63">Si vous regardez de nouveau le dessin <xref linkend="fig:tour-basic:history"/>, vous verrez les flèches reliant 1.2309 + entre elles les révisions. Le nœud d'où la flèche 1.2310 + <emphasis>part</emphasis> est dans chaque cas un parent, 1.2311 + et le nœud où la flèche <emphasis>arrive</emphasis> est un 1.2312 + enfant.</para> 1.2313 + 1.2314 + <para id="x_64">Pour mettre à jour l'espace de travail d'une révision 1.2315 + particulière, indiquez un numéro de révision ou un \textit{changeset 1.2316 + ID} à la commande <command role="hg-cmd" moreinfo="none">hg update</command>.</para> 1.2317 + 1.2318 + <!-- BEGIN tour.older --> 1.2319 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update 2</userinput> 1.2320 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.2321 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.2322 +changeset: 2:fef857204a0c 1.2323 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2324 +date: Sat Aug 16 22:05:04 2008 +0200 1.2325 +summary: Introduce a typo into hello.c. 1.2326 + 1.2327 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput> 1.2328 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.2329 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.2330 +changeset: 5:c94f208d1dfb 1.2331 +tag: tip 1.2332 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2333 +date: Sun Aug 16 14:05:26 2009 +0000 1.2334 +summary: Added an extra line of output 1.2335 + 1.2336 +</screen> 1.2337 +<!-- END tour.older --> 1.2338 + 1.2339 + 1.2340 + <para id="x_65">Si vous ne précisez pas de manière explicite de numéro 1.2341 + de révision la commande <command role="hg-cmd" moreinfo="none">hg update</command> 1.2342 + mettra à jour votre espace de travail avec le contenu de la révison 1.2343 + \textit{tip}, comme montré dans l'exemple ci dessus lors du second 1.2344 + appel à <command role="hg-cmd" moreinfo="none">hg update</command>.</para> 1.2345 + 1.2346 + </sect2> 1.2347 + <sect2> 1.2348 + <title>Transférer les modifications vers un autre dépôt</title> 1.2349 + 1.2350 + <para id="x_66">Mercurial vous laisse transférer les modifications vers 1.2351 + un autre dépôt, depuis votre dépôt actuel. Comme dans l'exemple du 1.2352 + <command role="hg-cmd" moreinfo="none">hg pull</command> ci-dessus, nous allons créer 1.2353 + un dépôt temporaire vers lequel transférer nos modifications.</para> 1.2354 + 1.2355 + <!-- BEGIN tour.clone-push --> 1.2356 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.2357 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-push</userinput> 1.2358 +updating working directory 1.2359 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.2360 +</screen> 1.2361 +<!-- END tour.clone-push --> 1.2362 + 1.2363 + 1.2364 + <para id="x_67">La commande <command role="hg-cmd" moreinfo="none">hg outgoing</command> 1.2365 + nous indique quels changements nous allons transférer vers l'autre 1.2366 + serveur.</para> 1.2367 + 1.2368 + <!-- BEGIN tour.outgoing --> 1.2369 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput> 1.2370 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing ../hello-push</userinput> 1.2371 +comparing with ../hello-push 1.2372 +searching for changes 1.2373 +changeset: 5:c94f208d1dfb 1.2374 +tag: tip 1.2375 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2376 +date: Sun Aug 16 14:05:26 2009 +0000 1.2377 +summary: Added an extra line of output 1.2378 + 1.2379 +</screen> 1.2380 +<!-- END tour.outgoing --> 1.2381 + 1.2382 + 1.2383 + <para id="x_68">Et la commande <command role="hg-cmd" moreinfo="none">hg push</command> 1.2384 + effectue réellement le transfert.</para> 1.2385 + 1.2386 + <!-- BEGIN tour.push --> 1.2387 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput> 1.2388 +pushing to ../hello-push 1.2389 +searching for changes 1.2390 +adding changesets 1.2391 +adding manifests 1.2392 +adding file changes 1.2393 +added 1 changesets with 1 changes to 1 files 1.2394 +</screen> 1.2395 +<!-- END tour.push --> 1.2396 + 1.2397 + 1.2398 + <para id="x_69">Comme avec <command role="hg-cmd" moreinfo="none">hg pull</command>, la 1.2399 + commande <command role="hg-cmd" moreinfo="none">hg push</command> ne met pas à jour 1.2400 + le répertoire de travail du dépôt dans lequel il transfère les 1.2401 + modifications. À l'inverse de <command role="hg-cmd" moreinfo="none">hg 1.2402 + pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> ne fournit 1.2403 + pas d'option <literal moreinfo="none">-u</literal> pour forcer la mise à jour de 1.2404 + l'espace de travail cible. Cette asymétrie est délibéré : le dépot 1.2405 + vers lequel nous transférons peut très bien être un serveur distant 1.2406 + et partagé par plusieurs personnes. Si nous devions mettre à jour son 1.2407 + répertoire de travail alors que quelqu'un d'autre travaille dessus, 1.2408 + nous risquerions de perturber son travail.</para> 1.2409 + 1.2410 + <para id="x_6a">Qu'est ce qui se passe lorsque vous essayez de récupérer 1.2411 + ou de transférer vos modifications et que le dépôt cible a déjà reçu 1.2412 + ces modifications ? Rien de bien excitant.</para> 1.2413 + 1.2414 + <!-- BEGIN tour.push.nothing --> 1.2415 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput> 1.2416 +pushing to ../hello-push 1.2417 +searching for changes 1.2418 +no changes found 1.2419 +</screen> 1.2420 +<!-- END tour.push.nothing --> 1.2421 + 1.2422 + 1.2423 + </sect2> 1.2424 + 1.2425 + <sect2> 1.2426 + <title>Emplacements par défaut</title> 1.2427 + 1.2428 + <para id="x_719">Quand nous faisons un clone d'un dépôt, Mercurial 1.2429 + enregistre l'emplacement du dépôt d'origine dans le fichier 1.2430 + <filename moreinfo="none">.hg/hgrc</filename> de notre nouveau dépôt. Si nous ne 1.2431 + fournissons pas d'emplacement à la commande <command moreinfo="none">hg 1.2432 + pull</command> ou à la commande <command moreinfo="none">hg push</command>, ces 1.2433 + commandes utiliseront alors cet emplacement comme valeur par défaut. 1.2434 + Les commandes <command moreinfo="none">hg incoming</command> et <command moreinfo="none">hg 1.2435 + outgoing</command> feront de même.</para> 1.2436 + 1.2437 + <para id="x_71a">Si vous regardez le fichier 1.2438 + <filename moreinfo="none">.hg/hgrc</filename>, vous constaterez que son contenu 1.2439 + ressemble à ce qui suit.</para> 1.2440 + 1.2441 + <programlisting format="linespecific">[paths] 1.2442 +default = http://www.selenic.com/repo/hg</programlisting> 1.2443 + 1.2444 + <para id="x_71b">Il est possible—et souvent 1.2445 + pratique—d'avoir un emplacement par défaut pour les commandes 1.2446 + <command moreinfo="none">hg push</command> et <command moreinfo="none">hg outgoing</command> 1.2447 + différent de celui des commandes <command moreinfo="none">hg pull</command> et 1.2448 + <command moreinfo="none">hg incoming</command>. C'est faisable en ajoutant une entrée 1.2449 + <literal moreinfo="none">default-push</literal> à la section 1.2450 + <literal moreinfo="none">[paths]</literal> du <filename moreinfo="none">.hg/hgrc</filename>, comme 1.2451 + suit.</para> 1.2452 + 1.2453 + <programlisting format="linespecific">[paths] 1.2454 +default = http://www.selenic.com/repo/hg 1.2455 +default-push = http://hg.example.com/hg</programlisting> 1.2456 + 1.2457 + </sect2> 1.2458 + <sect2> 1.2459 + <title>Partager ses modifications à travers le réseau</title> 1.2460 + 1.2461 + <para id="x_6b">Les commandes que nous avons étudiées dans les sections 1.2462 + précédentes ne sont pas limitées aux dépôts locaux. Chacune fonctionne 1.2463 + de la même manière à travers une connexion réseau, il suffit de lui 1.2464 + passer une URL à la place d'un chemin de fichier local.</para> 1.2465 + 1.2466 + <!-- BEGIN tour.outgoing.net --> 1.2467 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing http://hg.serpentine.com/tutorial/hello</userinput> 1.2468 +comparing with http://hg.serpentine.com/tutorial/hello 1.2469 +searching for changes 1.2470 +changeset: 5:c94f208d1dfb 1.2471 +tag: tip 1.2472 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2473 +date: Sun Aug 16 14:05:26 2009 +0000 1.2474 +summary: Added an extra line of output 1.2475 + 1.2476 +</screen> 1.2477 +<!-- END tour.outgoing.net --> 1.2478 + 1.2479 + 1.2480 + <para id="x_6c">Dans cet exemple, nous allons voir quels changements 1.2481 + nous pourrions transférer vers le dépôt distant, mais le dépôt est, 1.2482 + de manière tout à fait compréhensible, pas configuré pour accepter 1.2483 + des modifications d'utilisateurs anonymes.</para> 1.2484 + 1.2485 + <!-- BEGIN tour.push.net --> 1.2486 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push http://hg.serpentine.com/tutorial/hello</userinput> 1.2487 +pushing to http://hg.serpentine.com/tutorial/hello 1.2488 +searching for changes 1.2489 +ssl required 1.2490 +</screen> 1.2491 +<!-- END tour.push.net --> 1.2492 + 1.2493 + 1.2494 + </sect2> 1.2495 + 1.2496 + </sect1> 1.2497 + 1.2498 + <sect1> 1.2499 + <title>Commencer un nouveau projet</title> 1.2500 + 1.2501 + <para id="x_71c">Il est tout aussi aisé de commencer un nouveau projet 1.2502 + que de travailler sur un qui existe déjà. La commande <command moreinfo="none">hg 1.2503 + init</command> crée un nouveau dépôt Mercurial vide.</para> 1.2504 + 1.2505 + <!-- BEGIN ch01/new.init --> 1.2506 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myproject</userinput> 1.2507 +</screen> 1.2508 +<!-- END ch01/new.init --> 1.2509 + 1.2510 + 1.2511 + <para id="x_71d">Ceci crée simplement un répertoire nommé 1.2512 + <filename moreinfo="none">myproject</filename> dans le répertoire courant.</para> 1.2513 + 1.2514 + <!-- BEGIN ch01/new.ls --> 1.2515 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput> 1.2516 +total 12 1.2517 +-rw-r--r-- 1 rpelisse rpelisse 47 Aug 16 14:04 goodbye.c 1.2518 +-rw-r--r-- 1 rpelisse rpelisse 45 Aug 16 14:04 hello.c 1.2519 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 myproject 1.2520 +</screen> 1.2521 +<!-- END ch01/new.ls --> 1.2522 + 1.2523 + 1.2524 + <para id="x_71e">Nous pouvons dire que <filename moreinfo="none">myproject</filename> est 1.2525 + un dépôt Mercurial car il contient un répertoire 1.2526 + <filename moreinfo="none">.hg</filename>.</para> 1.2527 + 1.2528 + <!-- BEGIN ch01/new.ls2 --> 1.2529 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -al myproject</userinput> 1.2530 +total 12 1.2531 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 . 1.2532 +drwx------ 3 rpelisse rpelisse 4096 Aug 16 14:04 .. 1.2533 +drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 .hg 1.2534 +</screen> 1.2535 +<!-- END ch01/new.ls2 --> 1.2536 + 1.2537 + 1.2538 + <para id="x_71f">Si vous voulons ajouter quelques fichiers préexistants 1.2539 + dans ce dépôt, il suffit de les recopier dans le répertoire de travail, 1.2540 + et demander à Mercurial de commencer à les suivre en utilisant la 1.2541 + commande <command moreinfo="none">hg add</command>.</para> 1.2542 + 1.2543 + <!-- BEGIN ch01/new.add --> 1.2544 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput> 1.2545 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../hello.c .</userinput> 1.2546 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../goodbye.c .</userinput> 1.2547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add</userinput> 1.2548 +adding goodbye.c 1.2549 +adding hello.c 1.2550 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.2551 +A goodbye.c 1.2552 +A hello.c 1.2553 +</screen> 1.2554 +<!-- END ch01/new.add --> 1.2555 + 1.2556 + 1.2557 + <para id="x_720">Une fois que nous sommes satisfaits de notre projet, 1.2558 + nous pouvons commencer à ajouter nos révisions.</para> 1.2559 + 1.2560 + <!-- BEGIN ch01/new.commit --> 1.2561 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Initial commit'</userinput> 1.2562 +</screen> 1.2563 +<!-- END ch01/new.commit --> 1.2564 + 1.2565 + 1.2566 + <para id="x_721">Il ne prend que quelques instants pour commencer à 1.2567 + utiliser Mercurial sur un nouveau projet, ce qui fait aussi de ses 1.2568 + points forts. Travailler avec une gestion de révision devient très 1.2569 + facile, nous pouvons même l'utiliser pour les plus petits projets où 1.2570 + nous aurions probablement jamais penser utiliser un outils aussi 1.2571 + complexe.</para> 1.2572 + </sect1> 1.2573 +</chapter> 1.2574 + 1.2575 +<!-- 1.2576 +local variables: 1.2577 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.2578 +end: 1.2579 +--> 1.2580 + 1.2581 + <!-- BEGIN ch03 --> 1.2582 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.2583 + 1.2584 +<chapter id="chap:tour-merge"> 1.2585 + <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?> 1.2586 + <title>Un rapide tour de Mercurial: fusionner les travaux</title> 1.2587 + 1.2588 + <para id="x_338">Nous avons maintenant étudié comment cloner un dépôt, effectuer 1.2589 + des changements dedans, et récupérer ou transférer depuis un 1.2590 + autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les 1.2591 + modifications de différents dépôts.</para> 1.2592 + 1.2593 + <sect1> 1.2594 + <title>Fusionner différents travaux</title> 1.2595 + <para id="x_339">La fusion est un aspect fondamental lorsqu'on 1.2596 + travaille iavec un gestionnaire de source distribué.</para> 1.2597 + 1.2598 + <itemizedlist> 1.2599 + <listitem> 1.2600 + <para id="x_33a">Alice et Bob ont chacun une copie personnelle du dépôt d'un 1.2601 + projet sur lequel ils collaborent. Alice corrige un bug 1.2602 + dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le 1.2603 + sien. Ils veulent un dépôt partagé avec à la fois le correctif du 1.2604 + bug et la nouvelle fonctionnalité.</para> 1.2605 + </listitem> 1.2606 + <listitem> 1.2607 + <para id="x_33b">Je travaille régulièrement sur plusieurs tâches différentes sur 1.2608 + un seul projet en même temps, chacun isolé dans son propre dépôt. 1.2609 + Travailler ainsi signifie que je dois régulièrement fusionner une 1.2610 + partie de mon code avec celui des autres.</para> 1.2611 + </listitem> 1.2612 + </itemizedlist> 1.2613 + 1.2614 + <para id="x_33c">Parce que la fusion est une opération si commune à réaliser, 1.2615 + Mercurial la rend facile. Étudions ensemble le déroulement des 1.2616 + opérations. Nous commencerons encore par faire un clone d'un autre 1.2617 + dépôt (vous voyez que l'on fait ça tout le temps ?) puis nous ferons 1.2618 + quelques modifications dessus.</para> 1.2619 + 1.2620 + <!-- BEGIN tour.merge.clone --> 1.2621 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.2622 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-new-hello</userinput> 1.2623 +updating working directory 1.2624 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.2625 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-new-hello</userinput> 1.2626 +# Make some simple edits to hello.c. 1.2627 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">my-text-editor hello.c</userinput> 1.2628 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'A new hello for a new day.'</userinput> 1.2629 +</screen> 1.2630 +<!-- END tour.merge.clone --> 1.2631 + 1.2632 + 1.2633 + <para id="x_33d">Nous devrions avoir maintenant deux copies de 1.2634 + <filename moreinfo="none">hello.c</filename> avec des contenus différents. Les 1.2635 + historiques de ces deux dépôts ont aussi divergés, comme illustré dans 1.2636 + la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para> 1.2637 + 1.2638 + <!-- BEGIN tour.merge.cat1 --> 1.2639 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> 1.2640 +/* 1.2641 + * Placed in the public domain by Bryan O'Sullivan. This program is 1.2642 + * not covered by patents in the United States or other countries. 1.2643 + */ 1.2644 + 1.2645 +#include <stdio.h> 1.2646 + 1.2647 +int main(int argc, char **argv) 1.2648 +{ 1.2649 + printf("once more, hello.\n"); 1.2650 + printf("hello, world!\"); 1.2651 + printf("hello again!\n"); 1.2652 + return 0; 1.2653 +} 1.2654 +</screen> 1.2655 +<!-- END tour.merge.cat1 --> 1.2656 + 1.2657 + 1.2658 + <para id="x_722">Et ici est notre légèrement différente version du 1.2659 + dépôt.</para> 1.2660 + 1.2661 + <!-- BEGIN tour.merge.cat2 --> 1.2662 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat ../my-hello/hello.c</userinput> 1.2663 +/* 1.2664 + * Placed in the public domain by Bryan O'Sullivan. This program is 1.2665 + * not covered by patents in the United States or other countries. 1.2666 + */ 1.2667 + 1.2668 +#include <stdio.h> 1.2669 + 1.2670 +int main(int argc, char **argv) 1.2671 +{ 1.2672 + printf("hello, world!\"); 1.2673 + printf("hello again!\n"); 1.2674 + return 0; 1.2675 +} 1.2676 +</screen> 1.2677 +<!-- END tour.merge.cat2 --> 1.2678 + 1.2679 + 1.2680 + <figure id="fig:tour-merge:sep-repos" float="0"> 1.2681 + <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> 1.2682 + <mediaobject> 1.2683 + <imageobject><imagedata fileref="figs/tour-merge-sep-repos.png"/></imageobject> 1.2684 + <textobject><phrase>XXX ajoute un test</phrase></textobject> 1.2685 + </mediaobject> 1.2686 + </figure> 1.2687 + 1.2688 + <para id="x_33f">Nous savons déjà que récupérer les modifications depuis 1.2689 + notre dépôt <filename class="directory" moreinfo="none">my-hello</filename> n'aura 1.2690 + aucun effet sur l'espace de travail.</para> 1.2691 + 1.2692 + <!-- BEGIN tour.merge.pull --> 1.2693 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput> 1.2694 +pulling from ../my-hello 1.2695 +searching for changes 1.2696 +adding changesets 1.2697 +adding manifests 1.2698 +adding file changes 1.2699 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.2700 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.2701 +</screen> 1.2702 +<!-- END tour.merge.pull --> 1.2703 + 1.2704 + 1.2705 + <para id="x_340">Néanmoins, la commande <command role="hg-cmd" moreinfo="none">hg 1.2706 + pull</command> nous indique quelque chose au sujet des 1.2707 + <quote>heads</quote>.</para> 1.2708 + 1.2709 + <sect2> 1.2710 + <title>Les révisions 'heads'</title> 1.2711 + 1.2712 + <para id="x_341">Rappellez vous que Mercurial enregistre quelle révision 1.2713 + est le parent de chaque révision. Si une révision a un parent, nous 1.2714 + l'appelons un enfant(child) ou un descendant de ce parent. Une 1.2715 + "head" est une révision qui n'a donc pas d'enfant. La révision tip 1.2716 + est donc une "head", car c'est la révision la plus récente du dépôt 1.2717 + qui n'a pas d'enfant. Il y a des moments où un dépôt peut contenir 1.2718 + plusieurs "head".</para> 1.2719 + 1.2720 + <figure id="fig:tour-merge:pull" float="0"> 1.2721 + <title>Contenu du dépôt après une récupération ("pull") depuis le 1.2722 + 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> 1.2723 + <mediaobject> 1.2724 + <imageobject> 1.2725 + <imagedata fileref="tour-merge-pull"/> 1.2726 + </imageobject> 1.2727 + <textobject><phrase>XXX ajoute un texte</phrase></textobject> 1.2728 + </mediaobject> 1.2729 + </figure> 1.2730 + 1.2731 + <para id="x_343">Dans la figure <xref linkend="fig:tour-merge:pull"/>, 1.2732 + vous pouvez constater l'effet d'un \textit{pull} depuis le dépôt 1.2733 + <filename class="directory" moreinfo="none">my-hello</filename> dans le dépôt 1.2734 + <filename class="directory" moreinfo="none">my-new-hello</filename>. L'historique qui 1.2735 + était déjà présent dans le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename> reste intact, mais une 1.2736 + nouvelle révision a été ajoutée. En vous reportant à la figure <xref linkend="fig:tour-merge:sep-repos"/>, vous pouvez voir que le 1.2737 + <emphasis>ID de révision (changeset ID)</emphasis> reste le même dans 1.2738 + le nouveau dépôt, mais que le <emphasis>numéro de 1.2739 + révision</emphasis> reste le même. (Ceci est un parfait exemple de 1.2740 + pourquoi il n'est fiable d'utiliser les numéros de révision lorsque 1.2741 + l'on discute d'un \textit{changeset}.) Vous pouvez voir les "heads" 1.2742 + présentes dans le dépôt en utilisant la commande <command role="hg-cmd" moreinfo="none">hg heads</command>.</para> 1.2743 + 1.2744 + <!-- BEGIN tour.merge.heads --> 1.2745 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> 1.2746 +changeset: 6:c94f208d1dfb 1.2747 +tag: tip 1.2748 +parent: 4:2278160e78d4 1.2749 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2750 +date: Sun Aug 16 14:05:26 2009 +0000 1.2751 +summary: Added an extra line of output 1.2752 + 1.2753 +changeset: 5:5f06f94fbeca 1.2754 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2755 +date: Sun Aug 16 14:05:31 2009 +0000 1.2756 +summary: A new hello for a new day. 1.2757 + 1.2758 +</screen> 1.2759 +<!-- END tour.merge.heads --> 1.2760 + 1.2761 + </sect2> 1.2762 + 1.2763 + <sect2> 1.2764 + <title>Effectuer la fusion</title> 1.2765 + 1.2766 + <para id="x_344">Que se passe-t-il quand vous essayez d'utiliser la 1.2767 + commande <command role="hg-cmd" moreinfo="none">hg update</command> pour mettre à 1.2768 + jour votre espace de travail au nouveau "tip"</para> 1.2769 + 1.2770 + <!-- BEGIN tour.merge.update --> 1.2771 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput> 1.2772 +abort: crosses branches (use 'hg merge' or 'hg update -C') 1.2773 +</screen> 1.2774 +<!-- END tour.merge.update --> 1.2775 + 1.2776 + 1.2777 + 1.2778 + <para id="x_345">Mercurial nous prévient que la commande <command role="hg-cmd" moreinfo="none">hg update</command> n'effectuera pas 1.2779 + la fusion, il ne veut pas mettre à jour l'espace de travail quand il 1.2780 + estime que nous pourrions avoir besoin d'une fusion, à moins de lui 1.2781 + forcer la main. À la place, il faut utiliser la commande <command role="hg-cmd" moreinfo="none">hg merge</command> pour fusionner les deux 1.2782 + "heads".</para> 1.2783 + 1.2784 + <para id="x_723">Pour commencer une fusion (merge) entre deux "heads", 1.2785 + nous utilisons la commande <command role="hg-cmd" moreinfo="none">hg merge</command>.</para> 1.2786 + 1.2787 + <!-- BEGIN tour.merge.merge --> 1.2788 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.2789 +merging hello.c 1.2790 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved 1.2791 +(branch merge, don't forget to commit) 1.2792 +</screen> 1.2793 +<!-- END tour.merge.merge --> 1.2794 + 1.2795 + 1.2796 + <para id="x_347">Nous résolvons les conflits dans le fichier 1.2797 + <filename moreinfo="none">hello.c</filename>. Ceci met à jour le répertoire de travail 1.2798 + de sorte qu'il ne contienne les modifications ne provenance des 1.2799 + <emphasis>deux</emphasis> "heads", ce qui est indiqué par la 1.2800 + la sortie de la commande <command role="hg-cmd" moreinfo="none">hg 1.2801 + parents</command> et le contenu du fichier 1.2802 + <filename moreinfo="none">hello.c</filename>.</para> 1.2803 + 1.2804 + <!-- BEGIN tour.merge.parents --> 1.2805 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.2806 +changeset: 5:5f06f94fbeca 1.2807 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2808 +date: Sun Aug 16 14:05:31 2009 +0000 1.2809 +summary: A new hello for a new day. 1.2810 + 1.2811 +changeset: 6:c94f208d1dfb 1.2812 +tag: tip 1.2813 +parent: 4:2278160e78d4 1.2814 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2815 +date: Sun Aug 16 14:05:26 2009 +0000 1.2816 +summary: Added an extra line of output 1.2817 + 1.2818 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> 1.2819 +/* 1.2820 + * Placed in the public domain by Bryan O'Sullivan. This program is 1.2821 + * not covered by patents in the United States or other countries. 1.2822 + */ 1.2823 + 1.2824 +#include <stdio.h> 1.2825 + 1.2826 +int main(int argc, char **argv) 1.2827 +{ 1.2828 + printf("once more, hello.\n"); 1.2829 + printf("hello, world!\"); 1.2830 + printf("hello again!\n"); 1.2831 + return 0; 1.2832 +} 1.2833 +</screen> 1.2834 +<!-- END tour.merge.parents --> 1.2835 + 1.2836 + </sect2> 1.2837 + 1.2838 + <sect2> 1.2839 + <title>Effectuer l'ajout (commit) du résultat de la fusion</title> 1.2840 + 1.2841 + <para id="x_348">Dès l'instant où vous avez effectué une fusion 1.2842 + (merge), <command role="hg-cmd" moreinfo="none">hg parents</command> vous 1.2843 + affichera deux parents, avant que vous n'exécutiez la commande 1.2844 + <command role="hg-cmd" moreinfo="none">hg commit</command> sur le résultat de la 1.2845 + fusion.</para> 1.2846 + 1.2847 + <!-- BEGIN tour.merge.commit --> 1.2848 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merged changes'</userinput> 1.2849 +</screen> 1.2850 +<!-- END tour.merge.commit --> 1.2851 + 1.2852 + 1.2853 + <para id="x_349">Nous avons maintenant un nouveau tip, remarquer qu'il 1.2854 + contient <emphasis>à la fois</emphasis> nos anciennes "heads" et leurs 1.2855 + parents. Ce sont les mêmes révisions que nous avions affichées avec 1.2856 + la commande <command role="hg-cmd" moreinfo="none">hg parents</command>.</para> 1.2857 + 1.2858 + <!-- BEGIN tour.merge.tip --> 1.2859 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.2860 +changeset: 7:b8e1e756ef55 1.2861 +tag: tip 1.2862 +parent: 5:5f06f94fbeca 1.2863 +parent: 6:c94f208d1dfb 1.2864 +user: Bryan O'Sullivan <bos@serpentine.com> 1.2865 +date: Sun Aug 16 14:05:33 2009 +0000 1.2866 +summary: Merged changes 1.2867 + 1.2868 +</screen> 1.2869 +<!-- END tour.merge.tip --> 1.2870 + 1.2871 + 1.2872 + <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>, 1.2873 + vous pouvez voir une représentation de ce qui se passe dans l'espace 1.2874 + de travail pendant la fusion, et comment ceci affecte le dépôt lors 1.2875 + du "commit". Pendant la fusion, l'espace de travail, qui a deux 1.2876 + révisions (changesets) comme parents, voit ces derniers devenir le parent 1.2877 + d'une nouvelle révision (changeset).</para> 1.2878 + 1.2879 + <figure id="fig:tour-merge:merge" float="0"> 1.2880 + <title>Working directory and repository during merge, and 1.2881 + following commit</title> 1.2882 + <mediaobject> 1.2883 + <imageobject> 1.2884 + <imagedata fileref="figs/tour-merge-merge.png"/> 1.2885 + </imageobject> 1.2886 + <textobject><phrase>XXX ajoute texte</phrase></textobject> 1.2887 + </mediaobject> 1.2888 + </figure> 1.2889 + 1.2890 + </sect2> 1.2891 + </sect1> 1.2892 + 1.2893 + <sect1> 1.2894 + <title>Fusionner les modifications en conflit</title> 1.2895 + 1.2896 + <para id="x_34b">La plupart des fusions sont assez simple à réaliser, mais 1.2897 + parfois vous vous retrouverez à fusionner des fichiers où la modification 1.2898 + touche la même portion de code, au sein d'un même fichier. À moins 1.2899 + que ces modification ne soient identiques, ceci aboutira à un 1.2900 + <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier 1.2901 + les différentes modifications dans un tout cohérent.</para> 1.2902 + 1.2903 + <figure id="fig:tour-merge:conflict" float="0"> 1.2904 + <title>Modifications en conflits dans un document</title> 1.2905 + <mediaobject> 1.2906 + <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject> 1.2907 + <textobject><phrase>XXX ajoute texte</phrase></textobject> 1.2908 + </mediaobject> 1.2909 + </figure> 1.2910 + 1.2911 + <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/> 1.2912 + illustre un cas de modifications conflictuelles dans un document. Nous 1.2913 + avons commencé avec une version simple de ce fichier, puis nous avons 1.2914 + ajouté des modifications, pendant que quelqu'un d'autre modifiait le même 1.2915 + texte. Notre tâche dans la résolution du conflit est de décider à quoi le 1.2916 + fichier devrait ressembler.</para> 1.2917 + 1.2918 + <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer 1.2919 + les conflits. À la place, il exécute un programme externe appelé 1.2920 + <command moreinfo="none">hgmerge</command>. Il s'agit d'un script shell qui est 1.2921 + embarqué par Mercurial, vous pouvez le modifier si vous le voulez. 1.2922 + Ce qu'il fait par défaut est d'essayer de trouver un des différents 1.2923 + outils de fusion qui seront probablement installés sur le système. 1.2924 + Il commence par les outils totalement automatiques, et si ils 1.2925 + échouent (parce que la résolution du conflit nécessite une 1.2926 + intervention humaine) ou si ils sont absents, le script tente 1.2927 + d'exécuter certains outils graphiques de fusion.</para> 1.2928 + 1.2929 + <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter 1.2930 + un autre programme ou un autre script en définissant la variable 1.2931 + d'environnement <envar>HGMERGE</envar> avec le nom 1.2932 + du programme de votre choix.</para> 1.2933 + 1.2934 + <sect2> 1.2935 + <title>Utiliser un outil graphique de fusion</title> 1.2936 + 1.2937 + <para id="x_350">Mon outil de fusion préféré est 1.2938 + <command moreinfo="none">kdiff3</command>, que j'utilise ici pour illustrer les 1.2939 + fonctionnalités classiques des outils graphiques de fusion. Vous pouvez 1.2940 + voir une capture d'écran de l'utilisation de <command moreinfo="none">kdiff3</command> 1.2941 + dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil 1.2942 + effectue une <emphasis>fusion \textit{three-way</emphasis>}, car il y a 1.2943 + trois différentes versions du fichier qui nous intéresse. Le fichier 1.2944 + découpe la partie supérieure de la fenêtre en trois panneaux:</para> 1.2945 + <itemizedlist> 1.2946 + <listitem><para id="x_351">A gauche on la version de 1.2947 + <emphasis>base</emphasis> du fichier, soit la plus récente version 1.2948 + des deux versions qu'on souhaite fusionner.</para></listitem> 1.2949 + <listitem><para id="x_352">Au centre, il y a <quote>notre</quote> 1.2950 + version du fichier, avec le contenu que nous avons modifié.</para></listitem> 1.2951 + <listitem><para id="x_353">Sur la droite, on trouve 1.2952 + <quote>leur</quote> version du fichier, celui qui contient la 1.2953 + révision que nous souhaitons intégré.</para> 1.2954 + </listitem></itemizedlist> 1.2955 + <para id="x_354">Dans le panneau en dessous, on trouve le 1.2956 + <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche 1.2957 + consiste donc à remplacement tous les textes en rouges, 1.2958 + qui indiquent des conflits non résolus, avec une fusion manuelle et 1.2959 + pertinente de <quote>notre</quote> version et de la <quote>leur</quote>. 1.2960 + </para> 1.2961 + 1.2962 + <para id="x_355">Tous les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>, 1.2963 + si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun 1.2964 + d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs 1.2965 + fichiers respectifs.</para> 1.2966 + 1.2967 + <figure id="fig:tour-merge:kdiff3" float="0"> 1.2968 + <title>Utiliser <command moreinfo="none">kdiff3</command> pour fusionner les 1.2969 + différentes version d'un fichier.</title> 1.2970 + <mediaobject> 1.2971 + <imageobject> 1.2972 + <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject> 1.2973 + <textobject> 1.2974 + <phrase>XXX ajoute texte</phrase> 1.2975 + </textobject> 1.2976 + </mediaobject> 1.2977 + </figure> 1.2978 + 1.2979 + <para id="x_357">Pour chaque portion de fichier posant problème, nous 1.2980 + pouvons choisir de résoudre le conflit en utilisant une combinaison de 1.2981 + texte depuis la version de base, la notre, ou la leur. Nous pouvons 1.2982 + aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para> 1.2983 + 1.2984 + <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de 1.2985 + fusion disponibles, bien trop pour en parler de tous ici. Leurs 1.2986 + disponibilités varient selon les plate formes ainsi que leurs 1.2987 + avantages et inconvénients. La plupart sont optimisé pour 1.2988 + la fusion de fichier contenant un texte plat, certains sont spécialisé 1.2989 + dans un format de fichier précis (généralement XML).</para> 1.2990 + </sect2> 1.2991 + 1.2992 + <sect2> 1.2993 + <title>Un exemple concret</title> 1.2994 + 1.2995 + <para id="x_359">Dans cet exemple, nous allons reproduire la 1.2996 + modification de l'historique du fichier de la figure <xref linkend="fig:tour-merge:conflict"/> ci dessus. Commençons par créer 1.2997 + un dépôt avec une version de base de notre document.</para> 1.2998 + 1.2999 + <!-- BEGIN tour-merge-conflict.wife --> 1.3000 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> 1.3001 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 1.3002 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Mariam Abacha, the wife of former</userinput> 1.3003 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 1.3004 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> 1.3005 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add letter.txt</userinput> 1.3006 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, first draft'</userinput> 1.3007 +</screen> 1.3008 +<!-- END tour-merge-conflict.wife --> 1.3009 + 1.3010 + 1.3011 + <para id="x_35a">Créons un clone de ce dépôt et faisons une 1.3012 + modification dans le fichier.</para> 1.3013 + 1.3014 + <!-- BEGIN tour-merge-conflict.cousin --> 1.3015 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.3016 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-cousin</userinput> 1.3017 +updating working directory 1.3018 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.3019 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-cousin</userinput> 1.3020 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> 1.3021 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 1.3022 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Shehu Musa Abacha, cousin to the former</userinput> 1.3023 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 1.3024 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> 1.3025 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with cousin'</userinput> 1.3026 +</screen> 1.3027 +<!-- END tour-merge-conflict.cousin --> 1.3028 + 1.3029 + 1.3030 + <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une 1.3031 + modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare 1.3032 + de devoir effectuer des fusions (merges) avec vos propres travaux quand 1.3033 + vous isolez les tâches dans des dépôts distincts. En effet, vous 1.3034 + aurez alors à trouver et résoudre certains conflits).</para> 1.3035 + 1.3036 + <!-- BEGIN tour-merge-conflict.son --> 1.3037 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.3038 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-son</userinput> 1.3039 +updating working directory 1.3040 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.3041 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-son</userinput> 1.3042 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> 1.3043 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 1.3044 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Alhaji Abba Abacha, son of the former</userinput> 1.3045 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 1.3046 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> 1.3047 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with son'</userinput> 1.3048 +</screen> 1.3049 +<!-- END tour-merge-conflict.son --> 1.3050 + 1.3051 + 1.3052 + <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont 1.3053 + créées, nous allons configurer l'environnement de manière appropriée pour 1.3054 + exécuter notre fusion (merge).</para> 1.3055 + 1.3056 + <!-- BEGIN tour-merge-conflict.pull --> 1.3057 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.3058 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam-cousin scam-merge</userinput> 1.3059 +updating working directory 1.3060 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.3061 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-merge</userinput> 1.3062 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../scam-son</userinput> 1.3063 +pulling from ../scam-son 1.3064 +searching for changes 1.3065 +adding changesets 1.3066 +adding manifests 1.3067 +adding file changes 1.3068 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.3069 +not updating, since new heads added 1.3070 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.3071 +</screen> 1.3072 +<!-- END tour-merge-conflict.pull --> 1.3073 + 1.3074 + 1.3075 + <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial 1.3076 + habituelle <command moreinfo="none">hgmerge</command> pour effectuer le 1.3077 + fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé 1.3078 + pour utiliser un outil graphique. À la place, je vais définir la 1.3079 + variable d'environnement <envar>HGMERGE</envar> pour indiquer à 1.3080 + Mercurial d'utiliser la commande non-interactive <command moreinfo="none">merge</command>. 1.3081 + Cette dernière est embarquée par de nombreux systèmes <quote>à la Unix</quote>. 1.3082 + Si vous exécutez cet exemple depuis votre ordinateur, ne vous 1.3083 + occupez pas de définir <envar>HGMERGE</envar>.</para> 1.3084 + 1.3085 + <!-- BEGIN tour-merge-conflict.merge --> 1.3086 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=merge</userinput> 1.3087 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.3088 +merging letter.txt 1.3089 +merge: warning: conflicts during merge 1.3090 +merging letter.txt failed! 1.3091 +0 files updated, 0 files merged, 0 files removed, 1 files unresolved 1.3092 +use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon 1.3093 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat letter.txt</userinput> 1.3094 +Greetings! 1.3095 +<<<<<<< /tmp/tour-merge-conflictk3twLJ/scam-merge/letter.txt 1.3096 +I am Shehu Musa Abacha, cousin to the former 1.3097 +======= 1.3098 +I am Alhaji Abba Abacha, son of the former 1.3099 +>>>>>>> /tmp/letter.txt~other.4O623C 1.3100 +Nigerian dictator Sani Abacha. 1.3101 +</screen> 1.3102 +<!-- END tour-merge-conflict.merge --> 1.3103 + 1.3104 + 1.3105 + 1.3106 + <para id="x_35f">Parce que <command moreinfo="none">merge</command> ne peut pas résoudre 1.3107 + les modifications conflictuelles, il laisse des <emphasis>marqueurs de 1.3108 + différences</emphasis> à l'intérieur du fichier qui a des conflits, 1.3109 + indiquant clairement quelles lignes sont en conflits, et si elles 1.3110 + viennent de notre fichier ou du fichier externe. 1.3111 + </para> 1.3112 + 1.3113 + <para id="x_360">Mercurial peut distinguer, à la manière dont la 1.3114 + commande <command moreinfo="none">merge</command> se termine, qu'elle n'a pas été 1.3115 + capable d'effectuer la fusion (merge), alors il nous indique que nous 1.3116 + devons effectuer de nouveau cette opération. Ceci peut être très utile 1.3117 + si, par exemple, nous exécutons un outil graphique de fusion et que 1.3118 + nous le quittons sans nous rendre compte qu'il reste des conflits ou 1.3119 + simplement par erreur.</para> 1.3120 + 1.3121 + <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue, 1.3122 + il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en 1.3123 + modifiant nous même les fichiers, et enfin effectuer le "commit" du 1.3124 + fichier:</para> 1.3125 + 1.3126 + <!-- BEGIN tour-merge-conflict.commit --> 1.3127 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> 1.3128 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> 1.3129 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Bryan O'Sullivan, no relation of the former</userinput> 1.3130 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> 1.3131 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> 1.3132 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -m letter.txt</userinput> 1.3133 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Send me your money'</userinput> 1.3134 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.3135 +changeset: 3:0954bda76c6b 1.3136 +tag: tip 1.3137 +parent: 1:1ac156b6e708 1.3138 +parent: 2:7ee20631b33b 1.3139 +user: Bryan O'Sullivan <bos@serpentine.com> 1.3140 +date: Sun Aug 16 14:05:34 2009 +0000 1.3141 +summary: Send me your money 1.3142 + 1.3143 +</screen> 1.3144 +<!-- END tour-merge-conflict.commit --> 1.3145 + 1.3146 + 1.3147 + <note> 1.3148 + <title>Où est la <command moreinfo="none">hg resolve</command> ?</title> 1.3149 + 1.3150 + <para id="x_724">La commande <command moreinfo="none">hg resolve</command> a été 1.3151 + introduit dans la version 1.1 de Mercurial, qui a été publié en 1.3152 + décembre 2008. Si vous utilisez une version plus anciennne de 1.3153 + Mercurial (exécutez la command <command moreinfo="none">hg version</command> pour en 1.3154 + avoir le coeur net), cette commande ne sera pas disponible. Si votre 1.3155 + version de Mercurial est plus ancienne que la 1.1, vous devriez très 1.3156 + fortement considérer une mise à jour à une version plus récente avant 1.3157 + d'essayer de régler des fusions complexes.</para> 1.3158 + </note> 1.3159 + </sect2> 1.3160 + </sect1> 1.3161 + 1.3162 + <sect1 id="sec:tour-merge:fetch"> 1.3163 + <title>Simplification de la séquence pull-merge-commit</title> 1.3164 + 1.3165 + <para id="x_362">La procédure pour effectuer la fusion indiquée 1.3166 + ci-dessus est simple, mais requiert le lancement de trois commandes à la 1.3167 + suite.</para> 1.3168 + 1.3169 + <programlisting format="linespecific">hg pull -u 1.3170 +hg merge 1.3171 +hg commit -m 'Merged remote changes'</programlisting> 1.3172 + 1.3173 + <para id="x_363">Lors du "commit" final, vous devez également saisir un 1.3174 + message, qui aura vraisemblablement assez peu d'intérêt.</para> 1.3175 + 1.3176 + <para id="x_364">Il serait assez sympathique de pouvoir réduire le 1.3177 + nombre d'opérations nécessaire, si possible. De fait Mercurial est 1.3178 + fourni avec une extension appelé <literal role="hg-ext" moreinfo="none">fetch</literal> 1.3179 + qui fait justement cela.</para> 1.3180 + 1.3181 + <para id="x_365">Mercurial fourni un mécanisme d'extension flexible qui permet à chacun 1.3182 + d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial 1.3183 + léger et facile à utiliser. Certains extensions ajoutent de nouvelles 1.3184 + commandes que vous pouvez utiliser en ligne de commande, alors que 1.3185 + d'autres travaillent <quote>en coulisse,</quote> par exemple en ajoutant des 1.3186 + possibilités au serveur.</para> 1.3187 + 1.3188 + <para id="x_366">L'extension <literal role="hg-ext" moreinfo="none">fetch</literal> 1.3189 + ajoute une nouvelle commande nommée, sans surprise, <command role="hg-cmd" moreinfo="none">hg fetch</command>. Cette extension résulte en une 1.3190 + 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 1.3191 + merge</command>. Elle commence par récupérer les modifications d'un 1.3192 + autre dépôt dans le dépôt courant. Si elle trouve que les 1.3193 + modifications ajoutent une nouvelle "head", elle effectue un "merge", 1.3194 + et ensuite "commit" le résultat du "merge" avec un message généré 1.3195 + automatiquement. Si aucune "head" n'ont été ajouté, elle met à jour le 1.3196 + répertoire de travail au niveau de la nouvelle révision tip.</para> 1.3197 + 1.3198 + <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 1.3199 + <literal role="rc-extensions" moreinfo="none">extensions</literal>. Ensuite ajoutez 1.3200 + une ligne qui consiste simplement en <quote>\Verb+fetch =</quote>.</para> 1.3201 + 1.3202 + <programlisting format="linespecific">[extensions] 1.3203 +fetch =</programlisting> 1.3204 + 1.3205 + <para id="x_368">(Normalement, sur la partie droite de 1.3206 + <quote><literal moreinfo="none">=</literal></quote> devrait apparaître le chemin de 1.3207 + l'extension, mais étant donné que l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> fait partie de la distribution standard, 1.3208 + Mercurial sait où la trouver.) </para> 1.3209 + 1.3210 + </sect1> 1.3211 + 1.3212 + <sect1> 1.3213 + <title>Renommer, copier, et fusionner (merge)</title> 1.3214 + 1.3215 + <para id="x_729">En cours de la vie d'un projet, nous allons souvent 1.3216 + vouloir changer la disposition de ses fichiers et de ses répertoires. 1.3217 + Ceci peut être aussi simple que de changer le nom d'un seul fichier, 1.3218 + et aussi compliqué que de restructurer une hiérarchie entiere de fichier 1.3219 + au sein du projet.</para> 1.3220 + 1.3221 + <para id="x_72a">Mercurial permet de faire ce genre de modification de 1.3222 + manière fluide, à condition de l'informer de ce que nous faisons. Si 1.3223 + vous voulez renommenr un ficher, vous devriez utiliser les commande 1.3224 + <command moreinfo="none">hg rename</command><footnote> 1.3225 + <para id="x_72b">Si vous un utilisateur de Unix, vous serez content 1.3226 + de savoir que la commande <command moreinfo="none">hg rename</command> command 1.3227 + peut être abrégée en <command moreinfo="none">hg mv</command>.</para> 1.3228 + </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre 1.3229 + la bonne décision, plus tard, en cas de fusionv (merge).</para> 1.3230 + 1.3231 + <para id="x_72c">Nous étudierojns en détail l'utilisation de ces commandes, 1.3232 + en détail, dans le chapitre <xref linkend="chap:daily.copy"/>.</para> 1.3233 + </sect1> 1.3234 +</chapter> 1.3235 + 1.3236 +<!-- 1.3237 +local variables: 1.3238 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.3239 +end: 1.3240 +--> 1.3241 + 1.3242 + <!-- BEGIN ch04 --> 1.3243 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.3244 + 1.3245 +<chapter id="chap:concepts"> 1.3246 + <?dbhtml filename="behind-the-scenes.html"?> 1.3247 + <title>Derrière le décor</title> 1.3248 + 1.3249 + <para id="x_2e8">À la différence de beaucoup d'outils de gestion de versions, 1.3250 + les concepts sur lesquels se base Mercurial sont assez simples pour 1.3251 + qu'il soit facile de comprendre comment le logiciel fonctionne. 1.3252 + Bien que leur connaissance ne soit pas nécéssaire, je trouve utile 1.3253 + d'avoir un <quote>modèle mental</quote> de ce qui se passe.</para> 1.3254 + 1.3255 + <para id="x_2e9">En effet, cette compréhension m'apporte la confiance que 1.3256 + Mercurial a été développé avec soin pour être à la fois 1.3257 + <emphasis>sûr</emphasis> et <emphasis>efficace</emphasis>. De surcroît, 1.3258 + si il m'est facile de garder en tête ce que le logiciel fait lorsque 1.3259 + j'accompli des tâches de révision, j'aurai moins de risques d'être 1.3260 + surpris par son comportement.</para> 1.3261 + 1.3262 + <para id="x_2ea">Dans ce chapitre, nous décrirons tout d'abord les concepts 1.3263 + essentiels de l'architecture de Mercurial, pour ensuite discuter quelques 1.3264 + uns des détails intéressants de son implémentation.</para> 1.3265 + 1.3266 + <sect1> 1.3267 + <title>Conservation de l'historique sous Mercurial</title> 1.3268 + <sect2> 1.3269 + <title>Suivi de l'historique pour un seul fichier</title> 1.3270 + 1.3271 + <para id="x_2eb">Lorsque Mercurial effectue un suivi des modifications 1.3272 + faites à un fichier, il conserve l'historique pour ce fichier dans un 1.3273 + <emphasis>filelog</emphasis> sous forme de métadonnées. Chaque entrée 1.3274 + dans le filelog contient assez d'informations pour reconstituer une 1.3275 + révision du fichier correspondant. Les filelogs sont des fichiers 1.3276 + stockés dans le répertoire <filename role="special" class="directory" moreinfo="none">.hg/store/data</filename>. Un filelog contient 1.3277 + des informations de deux types: les données de révision, et un index 1.3278 + pour permettre à Mercurial une recherche efficace d'une révision 1.3279 + donnée.</para> 1.3280 + 1.3281 + <para id="x_2ec">Lorsqu'un fichier devient trop gros ou a un long 1.3282 + historique, son filelog se voit stocker dans un fichier de données 1.3283 + (avec un suffixe <quote><literal moreinfo="none">.d</literal></quote>) et un fichier 1.3284 + index (avec un suffixe<quote><literal moreinfo="none">.i</literal></quote>) 1.3285 + distincts. La relation entre un fichier dans le répertoire de travail 1.3286 + et le filelog couvrant le suivi de son historique dans le dépôt est 1.3287 + illustré à la figure <xref linkend="fig:concepts:filelog"/>.</para> 1.3288 + 1.3289 + <figure id="fig:concepts:filelog" float="0"> 1.3290 + <title>Relations entre les fichiers dans le répertoire de travail et 1.3291 + leurs filelogs dans le dépôt</title> 1.3292 + <mediaobject> <imageobject><imagedata fileref="figs/filelog.png"/></imageobject> 1.3293 + <textobject><phrase>XXX add text</phrase></textobject> 1.3294 + </mediaobject> </figure> 1.3295 + 1.3296 + </sect2> 1.3297 + <sect2> 1.3298 + <title>Gestion des fichiers suivis</title> 1.3299 + 1.3300 + <para id="x_2ee">Mercurial a recours à une structure nommée 1.3301 + <emphasis>manifest</emphasis> pour rassembler les informations sur 1.3302 + les fichiers dont il gère le suivi. Chaque entrée dans ce manifest 1.3303 + contient des informations sur les fichiers présents dans une révision 1.3304 + donnée. Une entrée store la liste des fichiers faisant partie de la 1.3305 + révision, la version de chaque fichier, et quelques autres 1.3306 + métadonnées sur ces fichiers.</para> 1.3307 + 1.3308 + </sect2> 1.3309 + <sect2> 1.3310 + <title>Recording changeset information</title> 1.3311 + 1.3312 + <para id="x_2ef">The <emphasis>changelog</emphasis> contains 1.3313 + information about each changeset. Each revision records who 1.3314 + committed a change, the changeset comment, other pieces of 1.3315 + changeset-related information, and the revision of the manifest to 1.3316 + use.</para> 1.3317 + 1.3318 + </sect2> 1.3319 + <sect2> 1.3320 + <title>Relationships between revisions</title> 1.3321 + 1.3322 + <para id="x_2f0">Within a changelog, a manifest, or a filelog, each 1.3323 + revision stores a pointer to its immediate parent (or to its 1.3324 + two parents, if it's a merge revision). As I mentioned above, 1.3325 + there are also relationships between revisions 1.3326 + <emphasis>across</emphasis> these structures, and they are 1.3327 + hierarchical in nature.</para> 1.3328 + 1.3329 + <para id="x_2f1">For every changeset in a repository, there is exactly one 1.3330 + revision stored in the changelog. Each revision of the 1.3331 + changelog contains a pointer to a single revision of the 1.3332 + manifest. A revision of the manifest stores a pointer to a 1.3333 + single revision of each filelog tracked when that changeset 1.3334 + was created. These relationships are illustrated in 1.3335 + <xref linkend="fig:concepts:metadata"/>.</para> 1.3336 + 1.3337 + <figure id="fig:concepts:metadata" float="0"> 1.3338 + <title>Metadata relationships</title> 1.3339 + <mediaobject> 1.3340 + <imageobject><imagedata fileref="figs/metadata.png"/></imageobject> 1.3341 + <textobject><phrase>XXX add text</phrase></textobject> 1.3342 + </mediaobject> 1.3343 + </figure> 1.3344 + 1.3345 + <para id="x_2f3">As the illustration shows, there is 1.3346 + <emphasis>not</emphasis> a <quote>one to one</quote> 1.3347 + relationship between revisions in the changelog, manifest, or 1.3348 + filelog. If a file that 1.3349 + Mercurial tracks hasn't changed between two changesets, the 1.3350 + entry for that file in the two revisions of the manifest will 1.3351 + point to the same revision of its filelog<footnote> 1.3352 + <para id="x_725">It is possible (though unusual) for the manifest to 1.3353 + remain the same between two changesets, in which case the 1.3354 + changelog entries for those changesets will point to the 1.3355 + same revision of the manifest.</para> 1.3356 + </footnote>.</para> 1.3357 + 1.3358 + </sect2> 1.3359 + </sect1> 1.3360 + <sect1> 1.3361 + <title>Safe, efficient storage</title> 1.3362 + 1.3363 + <para id="x_2f4">The underpinnings of changelogs, manifests, and filelogs are 1.3364 + provided by a single structure called the 1.3365 + <emphasis>revlog</emphasis>.</para> 1.3366 + 1.3367 + <sect2> 1.3368 + <title>Efficient storage</title> 1.3369 + 1.3370 + <para id="x_2f5">The revlog provides efficient storage of revisions using a 1.3371 + <emphasis>delta</emphasis> mechanism. Instead of storing a 1.3372 + complete copy of a file for each revision, it stores the 1.3373 + changes needed to transform an older revision into the new 1.3374 + revision. For many kinds of file data, these deltas are 1.3375 + typically a fraction of a percent of the size of a full copy 1.3376 + of a file.</para> 1.3377 + 1.3378 + <para id="x_2f6">Some obsolete revision control systems can only work with 1.3379 + deltas of text files. They must either store binary files as 1.3380 + complete snapshots or encoded into a text representation, both 1.3381 + of which are wasteful approaches. Mercurial can efficiently 1.3382 + handle deltas of files with arbitrary binary contents; it 1.3383 + doesn't need to treat text as special.</para> 1.3384 + 1.3385 + </sect2> 1.3386 + <sect2 id="sec:concepts:txn"> 1.3387 + <title>Safe operation</title> 1.3388 + 1.3389 + <para id="x_2f7">Mercurial only ever <emphasis>appends</emphasis> data to 1.3390 + the end of a revlog file. It never modifies a section of a 1.3391 + file after it has written it. This is both more robust and 1.3392 + efficient than schemes that need to modify or rewrite 1.3393 + data.</para> 1.3394 + 1.3395 + <para id="x_2f8">In addition, Mercurial treats every write as part of a 1.3396 + <emphasis>transaction</emphasis> that can span a number of 1.3397 + files. A transaction is <emphasis>atomic</emphasis>: either 1.3398 + the entire transaction succeeds and its effects are all 1.3399 + visible to readers in one go, or the whole thing is undone. 1.3400 + This guarantee of atomicity means that if you're running two 1.3401 + copies of Mercurial, where one is reading data and one is 1.3402 + writing it, the reader will never see a partially written 1.3403 + result that might confuse it.</para> 1.3404 + 1.3405 + <para id="x_2f9">The fact that Mercurial only appends to files makes it 1.3406 + easier to provide this transactional guarantee. The easier it 1.3407 + is to do stuff like this, the more confident you should be 1.3408 + that it's done correctly.</para> 1.3409 + 1.3410 + </sect2> 1.3411 + <sect2> 1.3412 + <title>Fast retrieval</title> 1.3413 + 1.3414 + <para id="x_2fa">Mercurial cleverly avoids a pitfall common to 1.3415 + all earlier revision control systems: the problem of 1.3416 + <emphasis>inefficient retrieval</emphasis>. Most revision 1.3417 + control systems store the contents of a revision as an 1.3418 + incremental series of modifications against a 1.3419 + <quote>snapshot</quote>. (Some base the snapshot on the 1.3420 + oldest revision, others on the newest.) To reconstruct a 1.3421 + specific revision, you must first read the snapshot, and then 1.3422 + every one of the revisions between the snapshot and your 1.3423 + target revision. The more history that a file accumulates, 1.3424 + the more revisions you must read, hence the longer it takes to 1.3425 + reconstruct a particular revision.</para> 1.3426 + 1.3427 + <figure id="fig:concepts:snapshot" float="0"> 1.3428 + <title>Snapshot of a revlog, with incremental deltas</title> 1.3429 + <mediaobject> 1.3430 + <imageobject><imagedata fileref="figs/snapshot.png"/></imageobject> 1.3431 + <textobject><phrase>XXX add text</phrase></textobject> 1.3432 + </mediaobject> 1.3433 + </figure> 1.3434 + 1.3435 + <para id="x_2fc">The innovation that Mercurial applies to this problem is 1.3436 + simple but effective. Once the cumulative amount of delta 1.3437 + information stored since the last snapshot exceeds a fixed 1.3438 + threshold, it stores a new snapshot (compressed, of course), 1.3439 + instead of another delta. This makes it possible to 1.3440 + reconstruct <emphasis>any</emphasis> revision of a file 1.3441 + quickly. This approach works so well that it has since been 1.3442 + copied by several other revision control systems.</para> 1.3443 + 1.3444 + <para id="x_2fd"><xref linkend="fig:concepts:snapshot"/> illustrates 1.3445 + the idea. In an entry in a revlog's index file, Mercurial 1.3446 + stores the range of entries from the data file that it must 1.3447 + read to reconstruct a particular revision.</para> 1.3448 + 1.3449 + <sect3> 1.3450 + <title>Aside: the influence of video compression</title> 1.3451 + 1.3452 + <para id="x_2fe">If you're familiar with video compression or 1.3453 + have ever watched a TV feed through a digital cable or 1.3454 + satellite service, you may know that most video compression 1.3455 + schemes store each frame of video as a delta against its 1.3456 + predecessor frame.</para> 1.3457 + 1.3458 + <para id="x_2ff">Mercurial borrows this idea to make it 1.3459 + possible to reconstruct a revision from a snapshot and a 1.3460 + small number of deltas.</para> 1.3461 + 1.3462 + </sect3> 1.3463 + </sect2> 1.3464 + <sect2> 1.3465 + <title>Identification and strong integrity</title> 1.3466 + 1.3467 + <para id="x_300">Along with delta or snapshot information, a revlog entry 1.3468 + contains a cryptographic hash of the data that it represents. 1.3469 + This makes it difficult to forge the contents of a revision, 1.3470 + and easy to detect accidental corruption.</para> 1.3471 + 1.3472 + <para id="x_301">Hashes provide more than a mere check against corruption; 1.3473 + they are used as the identifiers for revisions. The changeset 1.3474 + identification hashes that you see as an end user are from 1.3475 + revisions of the changelog. Although filelogs and the 1.3476 + manifest also use hashes, Mercurial only uses these behind the 1.3477 + scenes.</para> 1.3478 + 1.3479 + <para id="x_302">Mercurial verifies that hashes are correct when it 1.3480 + retrieves file revisions and when it pulls changes from 1.3481 + another repository. If it encounters an integrity problem, it 1.3482 + will complain and stop whatever it's doing.</para> 1.3483 + 1.3484 + <para id="x_303">In addition to the effect it has on retrieval efficiency, 1.3485 + Mercurial's use of periodic snapshots makes it more robust 1.3486 + against partial data corruption. If a revlog becomes partly 1.3487 + corrupted due to a hardware error or system bug, it's often 1.3488 + possible to reconstruct some or most revisions from the 1.3489 + uncorrupted sections of the revlog, both before and after the 1.3490 + corrupted section. This would not be possible with a 1.3491 + delta-only storage model.</para> 1.3492 + </sect2> 1.3493 + </sect1> 1.3494 + 1.3495 + <sect1> 1.3496 + <title>Revision history, branching, and merging</title> 1.3497 + 1.3498 + <para id="x_304">Every entry in a Mercurial revlog knows the identity of its 1.3499 + immediate ancestor revision, usually referred to as its 1.3500 + <emphasis>parent</emphasis>. In fact, a revision contains room 1.3501 + for not one parent, but two. Mercurial uses a special hash, 1.3502 + called the <quote>null ID</quote>, to represent the idea 1.3503 + <quote>there is no parent here</quote>. This hash is simply a 1.3504 + string of zeroes.</para> 1.3505 + 1.3506 + <para id="x_305">In <xref linkend="fig:concepts:revlog"/>, you can see 1.3507 + an example of the conceptual structure of a revlog. Filelogs, 1.3508 + manifests, and changelogs all have this same structure; they 1.3509 + differ only in the kind of data stored in each delta or 1.3510 + snapshot.</para> 1.3511 + 1.3512 + <para id="x_306">The first revision in a revlog (at the bottom of the image) 1.3513 + has the null ID in both of its parent slots. For a 1.3514 + <quote>normal</quote> revision, its first parent slot contains 1.3515 + the ID of its parent revision, and its second contains the null 1.3516 + ID, indicating that the revision has only one real parent. Any 1.3517 + two revisions that have the same parent ID are branches. A 1.3518 + revision that represents a merge between branches has two normal 1.3519 + revision IDs in its parent slots.</para> 1.3520 + 1.3521 + <figure id="fig:concepts:revlog" float="0"> 1.3522 + <title>The conceptual structure of a revlog</title> 1.3523 + <mediaobject> 1.3524 + <imageobject><imagedata fileref="figs/revlog.png"/></imageobject> 1.3525 + <textobject><phrase>XXX add text</phrase></textobject> 1.3526 + </mediaobject> 1.3527 + </figure> 1.3528 + 1.3529 + </sect1> 1.3530 + <sect1> 1.3531 + <title>The working directory</title> 1.3532 + 1.3533 + <para id="x_307">In the working directory, Mercurial stores a snapshot of the 1.3534 + files from the repository as of a particular changeset.</para> 1.3535 + 1.3536 + <para id="x_308">The working directory <quote>knows</quote> which changeset 1.3537 + it contains. When you update the working directory to contain a 1.3538 + particular changeset, Mercurial looks up the appropriate 1.3539 + revision of the manifest to find out which files it was tracking 1.3540 + at the time that changeset was committed, and which revision of 1.3541 + each file was then current. It then recreates a copy of each of 1.3542 + those files, with the same contents it had when the changeset 1.3543 + was committed.</para> 1.3544 + 1.3545 + <para id="x_309">The <emphasis>dirstate</emphasis> is a special 1.3546 + structure that contains Mercurial's knowledge of the working 1.3547 + directory. It is maintained as a file named 1.3548 + <filename moreinfo="none">.hg/dirstate</filename> inside a repository. The 1.3549 + dirstate details which changeset the working directory is 1.3550 + updated to, and all of the files that Mercurial is tracking in 1.3551 + the working directory. It also lets Mercurial quickly notice 1.3552 + changed files, by recording their checkout times and 1.3553 + sizes.</para> 1.3554 + 1.3555 + <para id="x_30a">Just as a revision of a revlog has room for two parents, so 1.3556 + that it can represent either a normal revision (with one parent) 1.3557 + or a merge of two earlier revisions, the dirstate has slots for 1.3558 + two parents. When you use the <command role="hg-cmd" moreinfo="none">hg 1.3559 + update</command> command, the changeset that you update to is 1.3560 + stored in the <quote>first parent</quote> slot, and the null ID 1.3561 + in the second. When you <command role="hg-cmd" moreinfo="none">hg 1.3562 + merge</command> with another changeset, the first parent 1.3563 + remains unchanged, and the second parent is filled in with the 1.3564 + changeset you're merging with. The <command role="hg-cmd" moreinfo="none">hg 1.3565 + parents</command> command tells you what the parents of the 1.3566 + dirstate are.</para> 1.3567 + 1.3568 + <sect2> 1.3569 + <title>What happens when you commit</title> 1.3570 + 1.3571 + <para id="x_30b">The dirstate stores parent information for more than just 1.3572 + book-keeping purposes. Mercurial uses the parents of the 1.3573 + dirstate as <emphasis>the parents of a new 1.3574 + changeset</emphasis> when you perform a commit.</para> 1.3575 + 1.3576 + <figure id="fig:concepts:wdir" float="0"> 1.3577 + <title>The working directory can have two parents</title> 1.3578 + <mediaobject> 1.3579 + <imageobject><imagedata fileref="figs/wdir.png"/></imageobject> 1.3580 + <textobject><phrase>XXX add text</phrase></textobject> 1.3581 + </mediaobject> 1.3582 + </figure> 1.3583 + 1.3584 + <para id="x_30d"><xref linkend="fig:concepts:wdir"/> shows the 1.3585 + normal state of the working directory, where it has a single 1.3586 + changeset as parent. That changeset is the 1.3587 + <emphasis>tip</emphasis>, the newest changeset in the 1.3588 + repository that has no children.</para> 1.3589 + 1.3590 + <figure id="fig:concepts:wdir-after-commit" float="0"> 1.3591 + <title>The working directory gains new parents after a 1.3592 + commit</title> 1.3593 + <mediaobject> 1.3594 + <imageobject><imagedata fileref="figs/wdir-after-commit.png"/></imageobject> 1.3595 + <textobject><phrase>XXX add text</phrase></textobject> 1.3596 + </mediaobject> 1.3597 + </figure> 1.3598 + 1.3599 + <para id="x_30f">It's useful to think of the working directory as 1.3600 + <quote>the changeset I'm about to commit</quote>. Any files 1.3601 + that you tell Mercurial that you've added, removed, renamed, 1.3602 + or copied will be reflected in that changeset, as will 1.3603 + modifications to any files that Mercurial is already tracking; 1.3604 + the new changeset will have the parents of the working 1.3605 + directory as its parents.</para> 1.3606 + 1.3607 + <para id="x_310">After a commit, Mercurial will update the 1.3608 + parents of the working directory, so that the first parent is 1.3609 + the ID of the new changeset, and the second is the null ID. 1.3610 + This is shown in <xref linkend="fig:concepts:wdir-after-commit"/>. Mercurial 1.3611 + doesn't touch any of the files in the working directory when 1.3612 + you commit; it just modifies the dirstate to note its new 1.3613 + parents.</para> 1.3614 + 1.3615 + </sect2> 1.3616 + <sect2> 1.3617 + <title>Creating a new head</title> 1.3618 + 1.3619 + <para id="x_311">It's perfectly normal to update the working directory to a 1.3620 + changeset other than the current tip. For example, you might 1.3621 + want to know what your project looked like last Tuesday, or 1.3622 + you could be looking through changesets to see which one 1.3623 + introduced a bug. In cases like this, the natural thing to do 1.3624 + is update the working directory to the changeset you're 1.3625 + interested in, and then examine the files in the working 1.3626 + directory directly to see their contents as they were when you 1.3627 + committed that changeset. The effect of this is shown in 1.3628 + <xref linkend="fig:concepts:wdir-pre-branch"/>.</para> 1.3629 + 1.3630 + <figure id="fig:concepts:wdir-pre-branch" float="0"> 1.3631 + <title>The working directory, updated to an older 1.3632 + changeset</title> 1.3633 + <mediaobject> 1.3634 + <imageobject><imagedata fileref="figs/wdir-pre-branch.png"/></imageobject> 1.3635 + <textobject><phrase>XXX add text</phrase></textobject> 1.3636 + </mediaobject> 1.3637 + </figure> 1.3638 + 1.3639 + <para id="x_313">Having updated the working directory to an 1.3640 + older changeset, what happens if you make some changes, and 1.3641 + then commit? Mercurial behaves in the same way as I outlined 1.3642 + above. The parents of the working directory become the 1.3643 + parents of the new changeset. This new changeset has no 1.3644 + children, so it becomes the new tip. And the repository now 1.3645 + contains two changesets that have no children; we call these 1.3646 + <emphasis>heads</emphasis>. You can see the structure that 1.3647 + this creates in <xref linkend="fig:concepts:wdir-branch"/>.</para> 1.3648 + 1.3649 + <figure id="fig:concepts:wdir-branch" float="0"> 1.3650 + <title>After a commit made while synced to an older 1.3651 + changeset</title> 1.3652 + <mediaobject> 1.3653 + <imageobject><imagedata fileref="figs/wdir-branch.png"/></imageobject> 1.3654 + <textobject><phrase>XXX add text</phrase></textobject> 1.3655 + </mediaobject> 1.3656 + </figure> 1.3657 + 1.3658 + <note> 1.3659 + <para id="x_315">If you're new to Mercurial, you should keep 1.3660 + in mind a common <quote>error</quote>, which is to use the 1.3661 + <command role="hg-cmd" moreinfo="none">hg pull</command> command without any 1.3662 + options. By default, the <command role="hg-cmd" moreinfo="none">hg 1.3663 + pull</command> command <emphasis>does not</emphasis> 1.3664 + update the working directory, so you'll bring new changesets 1.3665 + into your repository, but the working directory will stay 1.3666 + synced at the same changeset as before the pull. If you 1.3667 + make some changes and commit afterwards, you'll thus create 1.3668 + a new head, because your working directory isn't synced to 1.3669 + whatever the current tip is. To combine the operation of a 1.3670 + pull, followed by an update, run <command moreinfo="none">hg pull 1.3671 + -u</command>.</para> 1.3672 + 1.3673 + <para id="x_316">I put the word <quote>error</quote> in quotes 1.3674 + because all that you need to do to rectify the situation 1.3675 + where you created a new head by accident is 1.3676 + <command role="hg-cmd" moreinfo="none">hg merge</command>, then <command role="hg-cmd" moreinfo="none">hg commit</command>. In other words, this 1.3677 + almost never has negative consequences; it's just something 1.3678 + of a surprise for newcomers. I'll discuss other ways to 1.3679 + avoid this behavior, and why Mercurial behaves in this 1.3680 + initially surprising way, later on.</para> 1.3681 + </note> 1.3682 + 1.3683 + </sect2> 1.3684 + <sect2> 1.3685 + <title>Merging changes</title> 1.3686 + 1.3687 + <para id="x_317">When you run the <command role="hg-cmd" moreinfo="none">hg 1.3688 + merge</command> command, Mercurial leaves the first parent 1.3689 + of the working directory unchanged, and sets the second parent 1.3690 + to the changeset you're merging with, as shown in <xref linkend="fig:concepts:wdir-merge"/>.</para> 1.3691 + 1.3692 + <figure id="fig:concepts:wdir-merge" float="0"> 1.3693 + <title>Merging two heads</title> 1.3694 + <mediaobject> 1.3695 + <imageobject> 1.3696 + <imagedata fileref="figs/wdir-merge.png"/> 1.3697 + </imageobject> 1.3698 + <textobject><phrase>XXX add text</phrase></textobject> 1.3699 + </mediaobject> 1.3700 + </figure> 1.3701 + 1.3702 + <para id="x_319">Mercurial also has to modify the working directory, to 1.3703 + merge the files managed in the two changesets. Simplified a 1.3704 + little, the merging process goes like this, for every file in 1.3705 + the manifests of both changesets.</para> 1.3706 + <itemizedlist> 1.3707 + <listitem><para id="x_31a">If neither changeset has modified a file, do 1.3708 + nothing with that file.</para> 1.3709 + </listitem> 1.3710 + <listitem><para id="x_31b">If one changeset has modified a file, and the 1.3711 + other hasn't, create the modified copy of the file in the 1.3712 + working directory.</para> 1.3713 + </listitem> 1.3714 + <listitem><para id="x_31c">If one changeset has removed a file, and the 1.3715 + other hasn't (or has also deleted it), delete the file 1.3716 + from the working directory.</para> 1.3717 + </listitem> 1.3718 + <listitem><para id="x_31d">If one changeset has removed a file, but the 1.3719 + other has modified the file, ask the user what to do: keep 1.3720 + the modified file, or remove it?</para> 1.3721 + </listitem> 1.3722 + <listitem><para id="x_31e">If both changesets have modified a file, 1.3723 + invoke an external merge program to choose the new 1.3724 + contents for the merged file. This may require input from 1.3725 + the user.</para> 1.3726 + </listitem> 1.3727 + <listitem><para id="x_31f">If one changeset has modified a file, and the 1.3728 + other has renamed or copied the file, make sure that the 1.3729 + changes follow the new name of the file.</para> 1.3730 + </listitem></itemizedlist> 1.3731 + <para id="x_320">There are more details—merging has plenty of corner 1.3732 + cases—but these are the most common choices that are 1.3733 + involved in a merge. As you can see, most cases are 1.3734 + completely automatic, and indeed most merges finish 1.3735 + automatically, without requiring your input to resolve any 1.3736 + conflicts.</para> 1.3737 + 1.3738 + <para id="x_321">When you're thinking about what happens when you commit 1.3739 + after a merge, once again the working directory is <quote>the 1.3740 + changeset I'm about to commit</quote>. After the <command role="hg-cmd" moreinfo="none">hg merge</command> command completes, the 1.3741 + working directory has two parents; these will become the 1.3742 + parents of the new changeset.</para> 1.3743 + 1.3744 + <para id="x_322">Mercurial lets you perform multiple merges, but 1.3745 + you must commit the results of each individual merge as you 1.3746 + go. This is necessary because Mercurial only tracks two 1.3747 + parents for both revisions and the working directory. While 1.3748 + it would be technically feasible to merge multiple changesets 1.3749 + at once, Mercurial avoids this for simplicity. With multi-way 1.3750 + merges, the risks of user confusion, nasty conflict 1.3751 + resolution, and making a terrible mess of a merge would grow 1.3752 + intolerable.</para> 1.3753 + 1.3754 + </sect2> 1.3755 + 1.3756 + <sect2> 1.3757 + <title>Merging and renames</title> 1.3758 + 1.3759 + <para id="x_69a">A surprising number of revision control systems pay little 1.3760 + or no attention to a file's <emphasis>name</emphasis> over 1.3761 + time. For instance, it used to be common that if a file got 1.3762 + renamed on one side of a merge, the changes from the other 1.3763 + side would be silently dropped.</para> 1.3764 + 1.3765 + <para id="x_69b">Mercurial records metadata when you tell it to perform a 1.3766 + rename or copy. It uses this metadata during a merge to do the 1.3767 + right thing in the case of a merge. For instance, if I rename 1.3768 + a file, and you edit it without renaming it, when we merge our 1.3769 + work the file will be renamed and have your edits 1.3770 + applied.</para> 1.3771 + </sect2> 1.3772 + </sect1> 1.3773 + 1.3774 + <sect1> 1.3775 + <title>Other interesting design features</title> 1.3776 + 1.3777 + <para id="x_323">In the sections above, I've tried to highlight some of the 1.3778 + most important aspects of Mercurial's design, to illustrate that 1.3779 + it pays careful attention to reliability and performance. 1.3780 + However, the attention to detail doesn't stop there. There are 1.3781 + a number of other aspects of Mercurial's construction that I 1.3782 + personally find interesting. I'll detail a few of them here, 1.3783 + separate from the <quote>big ticket</quote> items above, so that 1.3784 + if you're interested, you can gain a better idea of the amount 1.3785 + of thinking that goes into a well-designed system.</para> 1.3786 + 1.3787 + <sect2> 1.3788 + <title>Clever compression</title> 1.3789 + 1.3790 + <para id="x_324">When appropriate, Mercurial will store both snapshots and 1.3791 + deltas in compressed form. It does this by always 1.3792 + <emphasis>trying to</emphasis> compress a snapshot or delta, 1.3793 + but only storing the compressed version if it's smaller than 1.3794 + the uncompressed version.</para> 1.3795 + 1.3796 + <para id="x_325">This means that Mercurial does <quote>the right 1.3797 + thing</quote> when storing a file whose native form is 1.3798 + compressed, such as a <literal moreinfo="none">zip</literal> archive or a JPEG 1.3799 + image. When these types of files are compressed a second 1.3800 + time, the resulting file is usually bigger than the 1.3801 + once-compressed form, and so Mercurial will store the plain 1.3802 + <literal moreinfo="none">zip</literal> or JPEG.</para> 1.3803 + 1.3804 + <para id="x_326">Deltas between revisions of a compressed file are usually 1.3805 + larger than snapshots of the file, and Mercurial again does 1.3806 + <quote>the right thing</quote> in these cases. It finds that 1.3807 + such a delta exceeds the threshold at which it should store a 1.3808 + complete snapshot of the file, so it stores the snapshot, 1.3809 + again saving space compared to a naive delta-only 1.3810 + approach.</para> 1.3811 + 1.3812 + <sect3> 1.3813 + <title>Network recompression</title> 1.3814 + 1.3815 + <para id="x_327">When storing revisions on disk, Mercurial uses the 1.3816 + <quote>deflate</quote> compression algorithm (the same one 1.3817 + used by the popular <literal moreinfo="none">zip</literal> archive format), 1.3818 + which balances good speed with a respectable compression 1.3819 + ratio. However, when transmitting revision data over a 1.3820 + network connection, Mercurial uncompresses the compressed 1.3821 + revision data.</para> 1.3822 + 1.3823 + <para id="x_328">If the connection is over HTTP, Mercurial recompresses 1.3824 + the entire stream of data using a compression algorithm that 1.3825 + gives a better compression ratio (the Burrows-Wheeler 1.3826 + algorithm from the widely used <literal moreinfo="none">bzip2</literal> 1.3827 + compression package). This combination of algorithm and 1.3828 + compression of the entire stream (instead of a revision at a 1.3829 + time) substantially reduces the number of bytes to be 1.3830 + transferred, yielding better network performance over most 1.3831 + kinds of network.</para> 1.3832 + 1.3833 + <para id="x_329">If the connection is over 1.3834 + <command moreinfo="none">ssh</command>, Mercurial 1.3835 + <emphasis>doesn't</emphasis> recompress the stream, because 1.3836 + <command moreinfo="none">ssh</command> can already do this itself. You can 1.3837 + tell Mercurial to always use <command moreinfo="none">ssh</command>'s 1.3838 + compression feature by editing the 1.3839 + <filename moreinfo="none">.hgrc</filename> file in your home directory as 1.3840 + follows.</para> 1.3841 + 1.3842 + <programlisting format="linespecific">[ui] 1.3843 +ssh = ssh -C</programlisting> 1.3844 + 1.3845 + </sect3> 1.3846 + </sect2> 1.3847 + <sect2> 1.3848 + <title>Read/write ordering and atomicity</title> 1.3849 + 1.3850 + <para id="x_32a">Appending to files isn't the whole story when 1.3851 + it comes to guaranteeing that a reader won't see a partial 1.3852 + write. If you recall <xref linkend="fig:concepts:metadata"/>, 1.3853 + revisions in the changelog point to revisions in the manifest, 1.3854 + and revisions in the manifest point to revisions in filelogs. 1.3855 + This hierarchy is deliberate.</para> 1.3856 + 1.3857 + <para id="x_32b">A writer starts a transaction by writing filelog and 1.3858 + manifest data, and doesn't write any changelog data until 1.3859 + those are finished. A reader starts by reading changelog 1.3860 + data, then manifest data, followed by filelog data.</para> 1.3861 + 1.3862 + <para id="x_32c">Since the writer has always finished writing filelog and 1.3863 + manifest data before it writes to the changelog, a reader will 1.3864 + never read a pointer to a partially written manifest revision 1.3865 + from the changelog, and it will never read a pointer to a 1.3866 + partially written filelog revision from the manifest.</para> 1.3867 + 1.3868 + </sect2> 1.3869 + <sect2> 1.3870 + <title>Concurrent access</title> 1.3871 + 1.3872 + <para id="x_32d">The read/write ordering and atomicity guarantees mean that 1.3873 + Mercurial never needs to <emphasis>lock</emphasis> a 1.3874 + repository when it's reading data, even if the repository is 1.3875 + being written to while the read is occurring. This has a big 1.3876 + effect on scalability; you can have an arbitrary number of 1.3877 + Mercurial processes safely reading data from a repository 1.3878 + all at once, no matter whether it's being written to or 1.3879 + not.</para> 1.3880 + 1.3881 + <para id="x_32e">The lockless nature of reading means that if you're 1.3882 + sharing a repository on a multi-user system, you don't need to 1.3883 + grant other local users permission to 1.3884 + <emphasis>write</emphasis> to your repository in order for 1.3885 + them to be able to clone it or pull changes from it; they only 1.3886 + need <emphasis>read</emphasis> permission. (This is 1.3887 + <emphasis>not</emphasis> a common feature among revision 1.3888 + control systems, so don't take it for granted! Most require 1.3889 + readers to be able to lock a repository to access it safely, 1.3890 + and this requires write permission on at least one directory, 1.3891 + which of course makes for all kinds of nasty and annoying 1.3892 + security and administrative problems.)</para> 1.3893 + 1.3894 + <para id="x_32f">Mercurial uses locks to ensure that only one process can 1.3895 + write to a repository at a time (the locking mechanism is safe 1.3896 + even over filesystems that are notoriously hostile to locking, 1.3897 + such as NFS). If a repository is locked, a writer will wait 1.3898 + for a while to retry if the repository becomes unlocked, but 1.3899 + if the repository remains locked for too long, the process 1.3900 + attempting to write will time out after a while. This means 1.3901 + that your daily automated scripts won't get stuck forever and 1.3902 + pile up if a system crashes unnoticed, for example. (Yes, the 1.3903 + timeout is configurable, from zero to infinity.)</para> 1.3904 + 1.3905 + <sect3> 1.3906 + <title>Safe dirstate access</title> 1.3907 + 1.3908 + <para id="x_330">As with revision data, Mercurial doesn't take a lock to 1.3909 + read the dirstate file; it does acquire a lock to write it. 1.3910 + To avoid the possibility of reading a partially written copy 1.3911 + of the dirstate file, Mercurial writes to a file with a 1.3912 + unique name in the same directory as the dirstate file, then 1.3913 + renames the temporary file atomically to 1.3914 + <filename moreinfo="none">dirstate</filename>. The file named 1.3915 + <filename moreinfo="none">dirstate</filename> is thus guaranteed to be 1.3916 + complete, not partially written.</para> 1.3917 + 1.3918 + </sect3> 1.3919 + </sect2> 1.3920 + <sect2> 1.3921 + <title>Avoiding seeks</title> 1.3922 + 1.3923 + <para id="x_331">Critical to Mercurial's performance is the avoidance of 1.3924 + seeks of the disk head, since any seek is far more expensive 1.3925 + than even a comparatively large read operation.</para> 1.3926 + 1.3927 + <para id="x_332">This is why, for example, the dirstate is stored in a 1.3928 + single file. If there were a dirstate file per directory that 1.3929 + Mercurial tracked, the disk would seek once per directory. 1.3930 + Instead, Mercurial reads the entire single dirstate file in 1.3931 + one step.</para> 1.3932 + 1.3933 + <para id="x_333">Mercurial also uses a <quote>copy on write</quote> scheme 1.3934 + when cloning a repository on local storage. Instead of 1.3935 + copying every revlog file from the old repository into the new 1.3936 + repository, it makes a <quote>hard link</quote>, which is a 1.3937 + shorthand way to say <quote>these two names point to the same 1.3938 + file</quote>. When Mercurial is about to write to one of a 1.3939 + revlog's files, it checks to see if the number of names 1.3940 + pointing at the file is greater than one. If it is, more than 1.3941 + one repository is using the file, so Mercurial makes a new 1.3942 + copy of the file that is private to this repository.</para> 1.3943 + 1.3944 + <para id="x_334">A few revision control developers have pointed out that 1.3945 + this idea of making a complete private copy of a file is not 1.3946 + very efficient in its use of storage. While this is true, 1.3947 + storage is cheap, and this method gives the highest 1.3948 + performance while deferring most book-keeping to the operating 1.3949 + system. An alternative scheme would most likely reduce 1.3950 + performance and increase the complexity of the software, but 1.3951 + speed and simplicity are key to the <quote>feel</quote> of 1.3952 + day-to-day use.</para> 1.3953 + 1.3954 + </sect2> 1.3955 + <sect2> 1.3956 + <title>Other contents of the dirstate</title> 1.3957 + 1.3958 + <para id="x_335">Because Mercurial doesn't force you to tell it when you're 1.3959 + modifying a file, it uses the dirstate to store some extra 1.3960 + information so it can determine efficiently whether you have 1.3961 + modified a file. For each file in the working directory, it 1.3962 + stores the time that it last modified the file itself, and the 1.3963 + size of the file at that time.</para> 1.3964 + 1.3965 + <para id="x_336">When you explicitly <command role="hg-cmd" moreinfo="none">hg 1.3966 + add</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>, 1.3967 + <command role="hg-cmd" moreinfo="none">hg rename</command> or <command role="hg-cmd" moreinfo="none">hg copy</command> files, Mercurial updates the 1.3968 + dirstate so that it knows what to do with those files when you 1.3969 + commit.</para> 1.3970 + 1.3971 + <para id="x_337">The dirstate helps Mercurial to efficiently 1.3972 + check the status of files in a repository.</para> 1.3973 + 1.3974 + <itemizedlist> 1.3975 + <listitem> 1.3976 + <para id="x_726">When Mercurial checks the state of a file in the 1.3977 + working directory, it first checks a file's modification 1.3978 + time against the time in the dirstate that records when 1.3979 + Mercurial last wrote the file. If the last modified time 1.3980 + is the same as the time when Mercurial wrote the file, the 1.3981 + file must not have been modified, so Mercurial does not 1.3982 + need to check any further.</para> 1.3983 + </listitem> 1.3984 + <listitem> 1.3985 + <para id="x_727">If the file's size has changed, the file must have 1.3986 + been modified. If the modification time has changed, but 1.3987 + the size has not, only then does Mercurial need to 1.3988 + actually read the contents of the file to see if it has 1.3989 + changed.</para> 1.3990 + </listitem> 1.3991 + </itemizedlist> 1.3992 + 1.3993 + <para id="x_728">Storing the modification time and size dramatically 1.3994 + reduces the number of read operations that Mercurial needs to 1.3995 + perform when we run commands like <command moreinfo="none">hg status</command>. 1.3996 + This results in large performance improvements.</para> 1.3997 + </sect2> 1.3998 + </sect1> 1.3999 +</chapter> 1.4000 + 1.4001 +<!-- 1.4002 +local variables: 1.4003 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.4004 +end: 1.4005 +--> 1.4006 + 1.4007 + <!-- BEGIN ch05 --> 1.4008 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.4009 + 1.4010 +<chapter id="chap:daily"> 1.4011 + <?dbhtml filename="mercurial-in-daily-use.html"?> 1.4012 + <title>Mercurial pour une utilisation de tous les jours</title> 1.4013 + 1.4014 + <sect1> 1.4015 + <title>Informer Mercurial des fichier à suivre</title> 1.4016 + 1.4017 + <para id="x_1a3">Mercurial ne suit pas les fichiers de votre dépôt tant 1.4018 + 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 1.4019 + inconnus de Mercurial. Il utilise un 1.4020 + <quote><literal moreinfo="none">?</literal></quote> pour montrer ces fichiers.</para> 1.4021 + 1.4022 + <para id="x_1a4">Pour informer Mercurial de suivre un fichier, utilisez 1.4023 + la commande <command role="hg-cmd" moreinfo="none">hg add</command>. Une fois que vous 1.4024 + avez ajouté un fichier, la ligne correspondante à ce fichier dans la 1.4025 + sortie de <command role="hg-cmd" moreinfo="none">hg status</command> change de 1.4026 + <quote><literal moreinfo="none">?</literal></quote> à 1.4027 + <quote><literal moreinfo="none">A</literal></quote>.</para> 1.4028 + 1.4029 + <!-- BEGIN daily.files.add --> 1.4030 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init add-example</userinput> 1.4031 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd add-example</userinput> 1.4032 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > myfile.txt</userinput> 1.4033 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4034 +? myfile.txt 1.4035 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile.txt</userinput> 1.4036 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4037 +A myfile.txt 1.4038 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added one file'</userinput> 1.4039 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4040 +</screen> 1.4041 +<!-- END daily.files.add --> 1.4042 + 1.4043 + 1.4044 + <para id="x_1a5">Après avoir exécuté un <command role="hg-cmd" moreinfo="none">hg 1.4045 + commit</command>, les fichiers que vous avez ajoutés avant le commit 1.4046 + ne seront plus listés dans la sortie de <command role="hg-cmd" moreinfo="none">hg 1.4047 + 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 1.4048 + <quote>intéressants</quote> —ceux que vous avez (par exemple) 1.4049 + modifiés, supprimés ou renommés. Si vous aviez un dépôt qui contient un 1.4050 + millier de fichiers, vous ne voudriez certainement que rarement entendre 1.4051 + parler des fichiers que Mercurial suit, mais qui n'ont pas changés. 1.4052 + (Vous pouvez quand même avoir cette information, nous y reviendrons 1.4053 + plus tard.)</para> 1.4054 + 1.4055 + <para id="x_1a6">Une fois que vous ajoutez un fichier, Mercurial ne fait 1.4056 + rien du tout avec celui-ci immédiatement. Au lieu de ça, il va prendre 1.4057 + un "snapshot" de l'état du fichier la prochaine fois que vous 1.4058 + exécuterez un commit. Il continuera ensuite à suivre les changements 1.4059 + que vous avez fait au fichier chaque fois que vous committerez, et ce, 1.4060 + jusqu'à ce que vous supprimiez le fichier.</para> 1.4061 + 1.4062 + <sect2> 1.4063 + <title>Nommage des fichiers explicite versus implicite</title> 1.4064 + 1.4065 + <para id="x_1a7">Un comportement utile que Mercurial possède est que si 1.4066 + vous passez le nom d'un répertoire à une commande, toute commande 1.4067 + Mercurial la traitera comme : <quote>Je veux opérer sur chaque fichier 1.4068 + dans ce répertoire et ses sous-répertoires</quote>.</para> 1.4069 + 1.4070 + <!-- BEGIN daily.files.add-dir --> 1.4071 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput> 1.4072 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b/somefile.txt</userinput> 1.4073 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c > b/source.cpp</userinput> 1.4074 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b/d</userinput> 1.4075 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo d > b/d/test.h</userinput> 1.4076 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput> 1.4077 +adding b/d/test.h 1.4078 +adding b/somefile.txt 1.4079 +adding b/source.cpp 1.4080 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added all files in subdirectory'</userinput> 1.4081 +</screen> 1.4082 +<!-- END daily.files.add-dir --> 1.4083 + 1.4084 + 1.4085 + <para id="x_1a8">Remarquez que dans cet exemple, Mercurial affiche le 1.4086 + nom des fichiers qu'il a ajouté, alors qu'il ne l'a pas fait lorsque 1.4087 + nous avons ajouté le fichier nommé <filename moreinfo="none">myfile.txt</filename> 1.4088 + dans l'exemple précédent.</para> 1.4089 + 1.4090 + <para id="x_1a9">Ce qu'il se passe est que dans le premier cas, nous 1.4091 + avons nommé explicitement le fichier à ajouter sur la ligne de 1.4092 + commande. Ce que Mercurial suppose dans ce cas est que nous savons ce 1.4093 + que nous faisons, il n'affiche donc rien en sortie.</para> 1.4094 + 1.4095 + <para id="x_1aa">Cependant, lorsque nous avons 1.4096 + <emphasis>implicitement</emphasis> donné les fichiers à l'aide du nom 1.4097 + d'un répertoire, Mercurial prend l'initiative d'afficher le nom de 1.4098 + chaque fichier avec lequel il fait quelque chose. Ceci clarifie ce 1.4099 + qu'il se passe et réduit la probabilité d'une mauvaise surprise 1.4100 + restée silencieuse. Ce comportement est commun à la plupart des 1.4101 + commandes Mercurial.</para> 1.4102 + </sect2> 1.4103 + <sect2> 1.4104 + <title>Mercurial suit les fichiers, pas les répertoires</title> 1.4105 + 1.4106 + <para id="x_1ab">Mercurial ne suit pas les informations sur les 1.4107 + répertoires. En contrepartie, il suit le chemin vers un fichier. Avant 1.4108 + de créer un fichier, il crée au préalable les répertoires manquants 1.4109 + dans le chemin. Après avoir supprimé un fichier, il supprime chaque 1.4110 + répertoire vide qui apparaît dans le chemin du fichier. Ceci apparaît 1.4111 + comme une distinction triviale, cependant, cela a une conséquence 1.4112 + pratique mineure : il n'est pas possible de représenter un répertoire 1.4113 + totalement vide dans Mercurial.</para> 1.4114 + 1.4115 + <para id="x_1ac">Les répertoires vides sont rarement utiles. Il existe 1.4116 + cependant des solutions alternatives et non intrusives que vous 1.4117 + pouvez utiliser pour obtenir l'effet approprié. Les développeurs de 1.4118 + Mercurial ont ainsi pensé que la complexité requise pour gérer les 1.4119 + répertoires n'était pas aussi importante que le bénéfice que cette 1.4120 + fonctionnalité apporterait.</para> 1.4121 + 1.4122 + <para id="x_1ad">Si vous avez besoin d'un répertoire vide dans votre 1.4123 + dépôt, il existe quelques façons d'y arriver. L'une d'elles est de 1.4124 + créer un répertoire et ensuite, de faire un <command role="hg-cmd" moreinfo="none">hg 1.4125 + add</command> sur un fichier <quote>caché</quote> dans ce 1.4126 + répertoire. Sur les systèmes de type Unix, tout fichier dont le nom 1.4127 + commence avec un point (<quote><literal moreinfo="none">.</literal></quote>) est 1.4128 + considéré comme caché par la plupart des commandes et outils 1.4129 + graphiques. Cette approche est illustrée ci-après.</para> 1.4130 + 1.4131 + <!-- BEGIN daily.files.hidden --> 1.4132 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hidden-example</userinput> 1.4133 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hidden-example</userinput> 1.4134 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir empty</userinput> 1.4135 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">touch empty/.hidden</userinput> 1.4136 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add empty/.hidden</userinput> 1.4137 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Manage an empty-looking directory'</userinput> 1.4138 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls empty</userinput> 1.4139 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.4140 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hidden-example tmp</userinput> 1.4141 +updating working directory 1.4142 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4143 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp</userinput> 1.4144 +empty 1.4145 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp/empty</userinput> 1.4146 +</screen> 1.4147 +<!-- END daily.files.hidden --> 1.4148 + 1.4149 + 1.4150 + <para id="x_1ae">Une autre façon de s'attaquer au besoin d'un 1.4151 + répertoire vide est de simplement d'en créer un dans vos scripts 1.4152 + de construction avant qu'ils n'en aient le besoin.</para> 1.4153 + </sect2> 1.4154 + </sect1> 1.4155 + 1.4156 + <sect1> 1.4157 + <title>Comment arrêter de suivre un fichier</title> 1.4158 + 1.4159 + <para id="x_1af">Une fois que vous décidez qu'un fichier n'appartient 1.4160 + plus à votre dépôt, utilisez la commande <command role="hg-cmd" moreinfo="none">hg 1.4161 + remove</command>. Ceci supprime le fichier et informe Mercurial 1.4162 + d'arrêter de le suivre (ce qui prendra effet lors du prochain commit). 1.4163 + Un fichier supprimé est représenté dans la sortie de la commande 1.4164 + <command role="hg-cmd" moreinfo="none">hg status</command> par un 1.4165 + <quote><literal moreinfo="none">R</literal></quote>.</para> 1.4166 + 1.4167 + <!-- BEGIN daily.files.remove --> 1.4168 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init remove-example</userinput> 1.4169 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd remove-example</userinput> 1.4170 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.4171 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput> 1.4172 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b/b</userinput> 1.4173 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a b</userinput> 1.4174 +adding b/b 1.4175 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Small example for file removal'</userinput> 1.4176 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove a</userinput> 1.4177 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4178 +R a 1.4179 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove b</userinput> 1.4180 +removing b/b 1.4181 +</screen> 1.4182 +<!-- END daily.files.remove --> 1.4183 + 1.4184 + 1.4185 + <para id="x_1b0">Après avoir fait un <command role="hg-cmd" moreinfo="none">hg 1.4186 + remove</command> sur un fichier, Mercurial ne suivra plus aucun 1.4187 + changement sur ce fichier, même si vous recréez un fichier avec le même 1.4188 + nom dans votre répertoire de travail. Si vous recréez un fichier avec le 1.4189 + même nom et que vous désirez que Mercurial suive ce dernier, faite 1.4190 + simplement un <command role="hg-cmd" moreinfo="none">hg add</command> sur celui-ci. 1.4191 + Mercurial saura alors que le nouveau fichier ne fait pas référence à 1.4192 + l'ancien fichier qui portait le même nom.</para> 1.4193 + 1.4194 + <sect2> 1.4195 + <title>Supprimer un fichier n'affecte pas son historique</title> 1.4196 + 1.4197 + <para id="x_1b1">Il est important de comprendre que supprimer un fichier 1.4198 + n'a que deux effets.</para> 1.4199 + 1.4200 + <itemizedlist> 1.4201 + <listitem><para id="x_1b2">Il supprime la version actuelle de ce 1.4202 + fichier du répertoire de travail.</para> 1.4203 + </listitem> 1.4204 + <listitem><para id="x_1b3">Il arrête, à partir du prochain commit, le 1.4205 + suivi de Mercurial sur les changements qui ont lieu sur ce 1.4206 + fichier.</para> 1.4207 + </listitem></itemizedlist> 1.4208 + 1.4209 + <para id="x_1b4">Supprimer un fichier <emphasis>n'</emphasis>affecte en 1.4210 + <emphasis>aucun</emphasis> cas l'<emphasis>historique</emphasis> du 1.4211 + fichier.</para> 1.4212 + 1.4213 + <para id="x_1b5">Si vous mettez à jour le répertoire de travail à un 1.4214 + changeset qui a été committé alors que le fichier que vous venez de 1.4215 + supprimer était encore suivi, ce fichier réapparaîtra dans le 1.4216 + répertoire de travail, avec le contenu qu'il avait lorsque vous aviez 1.4217 + committé ce changeset. Si vous mettez à jour (update) le répertoire de 1.4218 + travail à un changeset ultérieur dans lequel le fichier a été 1.4219 + supprimé, Mercurial supprimera une nouvelle fois le fichier du 1.4220 + répertoire de travail.</para> 1.4221 + </sect2> 1.4222 + 1.4223 + <sect2> 1.4224 + <title>Fichiers manquants</title> 1.4225 + 1.4226 + <para id="x_1b6">Mercurial considère qu'un fichier que vous avez 1.4227 + supprimé sans utiliser<command role="hg-cmd" moreinfo="none">hg remove</command> 1.4228 + comme étant <emphasis>manquant</emphasis>. Un fichier manquant est 1.4229 + représenté avec un <quote><literal moreinfo="none">!</literal></quote> en sortie de 1.4230 + <command role="hg-cmd" moreinfo="none">hg status</command>. 1.4231 + Les commandes Mercurial ne feront rien avec les fichiers 1.4232 + manquants.</para> 1.4233 + 1.4234 + <!-- BEGIN daily.files.missing --> 1.4235 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init missing-example</userinput> 1.4236 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd missing-example</userinput> 1.4237 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.4238 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> 1.4239 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'File about to be missing'</userinput> 1.4240 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm a</userinput> 1.4241 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4242 +! a 1.4243 +</screen> 1.4244 +<!-- END daily.files.missing --> 1.4245 + 1.4246 + 1.4247 + <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 1.4248 + vous voulez que ce fichier reste supprimé, vous pouvez exécuter 1.4249 + <command role="hg-cmd" moreinfo="none">hg remove <option role="hg-opt-remove">--after</option></command> à tout moment 1.4250 + pour dire à Mercurial que vous aviez bien voulu supprimer ce 1.4251 + fichier.</para> 1.4252 + 1.4253 + <!-- BEGIN daily.files.remove-after --> 1.4254 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove --after a</userinput> 1.4255 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4256 +R a 1.4257 +</screen> 1.4258 +<!-- END daily.files.remove-after --> 1.4259 + 1.4260 + 1.4261 + <para id="x_1b8">D'un autre coté, si vous avez supprimé le fichier 1.4262 + manquant par accident, donnez à la commande <command role="hg-cmd" moreinfo="none">hg 1.4263 + revert</command> le nom du fichier à retrouver. Il réapparaitra dans 1.4264 + sa forme non modifiée.</para> 1.4265 + 1.4266 + <!-- BEGIN daily.files.recover-missing --> 1.4267 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert a</userinput> 1.4268 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat a</userinput> 1.4269 +a 1.4270 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4271 +</screen> 1.4272 +<!-- END daily.files.recover-missing --> 1.4273 + 1.4274 + 1.4275 + </sect2> 1.4276 + 1.4277 + <sect2> 1.4278 + <title>Entre nous : Pourquoi dire explicitement à Mercurial de supprimer un 1.4279 + fichier ?</title> 1.4280 + 1.4281 + <para id="x_1b9">Vous pourriez vous demander pourquoi il est nécessaire 1.4282 + de dire explicitement à Mercurial que vous souhaitez supprimer un 1.4283 + fichier. Au début du développement de Mercurial, celui ci vous 1.4284 + laissait pourtant supprimer un fichier sans soucis ; Mercurial vous 1.4285 + aurait automatiquement informé de l'absence du fichier lorsque vous 1.4286 + auriez lancé un <command role="hg-cmd" moreinfo="none">hg commit</command> et arrêté 1.4287 + de le suivre. En pratique, ceci a montré qu'il était trop facile de 1.4288 + supprimer accidentellement un fichier sans le remarquer.</para> 1.4289 + </sect2> 1.4290 + 1.4291 + <sect2> 1.4292 + <title>Raccourci utile—ajouter et supprimer des fichiers en une 1.4293 + seule étape.</title> 1.4294 + 1.4295 + <para id="x_1ba">Mercurial offre une commande combinée, <command role="hg-cmd" moreinfo="none">hg addremove</command>, qui ajoute les fichiers non 1.4296 + suivis et marque les fichiers manquants comme supprimés.</para> 1.4297 + 1.4298 + <!-- BEGIN daily.files.addremove --> 1.4299 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init addremove-example</userinput> 1.4300 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd addremove-example</userinput> 1.4301 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.4302 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b</userinput> 1.4303 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg addremove</userinput> 1.4304 +adding a 1.4305 +adding b 1.4306 +</screen> 1.4307 +<!-- END daily.files.addremove --> 1.4308 + 1.4309 + 1.4310 + <para id="x_1bb">La commande <command role="hg-cmd" moreinfo="none">hg commit</command> 1.4311 + fournit aussi une option <option role="hg-opt-commit">-A</option> qui 1.4312 + exécute le même ajouter-et-supprimer, immédiatement suivi d'un 1.4313 + commit.</para> 1.4314 + 1.4315 + <!-- BEGIN daily.files.commit-addremove --> 1.4316 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c > c</userinput> 1.4317 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Commit with addremove'</userinput> 1.4318 +adding c 1.4319 +</screen> 1.4320 +<!-- END daily.files.commit-addremove --> 1.4321 + 1.4322 + 1.4323 + </sect2> 1.4324 + </sect1> 1.4325 + 1.4326 + <sect1 id="chap:daily.copy"> 1.4327 + <title>Copier des fichiers</title> 1.4328 + 1.4329 + <para id="x_1bc">Mercurial fournit une commande <command role="hg-cmd" moreinfo="none">hg 1.4330 + copy</command> qui vous permet de faire une nouvelle copie d'un 1.4331 + fichier. Lorsque vous copiez un fichier en utilisant cette commande, 1.4332 + Mercurial crée un enregistrement du fait que ce nouveau fichier est une 1.4333 + copie du fichier originel. Il traite ces fichiers copiés spécialement 1.4334 + lorsque vous fusionnez (merge) votre travail avec quelqu'un 1.4335 + d'autre.</para> 1.4336 + 1.4337 + <sect2> 1.4338 + <title>Les résultats d'une copie durant une fusion (merge)</title> 1.4339 + 1.4340 + <para id="x_1bd">Ce qu'il se passe durant une fusion (merge) est que 1.4341 + les changements <quote>suivent</quote> une copie. Pour illustrer ce 1.4342 + que cela veut dire de la meilleure façon, créons un exemple. Nous 1.4343 + allons commencer avec le mini dépôt usuel qui contient un simple 1.4344 + fichier.</para> 1.4345 + 1.4346 + <!-- BEGIN daily.copy.init --> 1.4347 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init my-copy</userinput> 1.4348 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput> 1.4349 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo line > file</userinput> 1.4350 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file</userinput> 1.4351 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added a file'</userinput> 1.4352 +</screen> 1.4353 +<!-- END daily.copy.init --> 1.4354 + 1.4355 + 1.4356 + <para id="x_1be">Nous devons faire du travail en parallèle, ainsi, 1.4357 + nous aurons quelque chose à fusionner (merge). Donc clonons notre 1.4358 + dépôt.</para> 1.4359 + 1.4360 + <!-- BEGIN daily.copy.clone --> 1.4361 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.4362 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone my-copy your-copy</userinput> 1.4363 +updating working directory 1.4364 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4365 +</screen> 1.4366 +<!-- END daily.copy.clone --> 1.4367 + 1.4368 + 1.4369 + <para id="x_1bf">De retour dans notre dépôt initial, utilisons la 1.4370 + commande <command role="hg-cmd" moreinfo="none">hg copy</command> pour faire une 1.4371 + copie du premier fichier que nous avons créé.</para> 1.4372 + 1.4373 + <!-- BEGIN daily.copy.copy --> 1.4374 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput> 1.4375 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput> 1.4376 +</screen> 1.4377 +<!-- END daily.copy.copy --> 1.4378 + 1.4379 + 1.4380 + <para id="x_1c0">Si nous regardons ensuite à la sortie de la commande 1.4381 + <command role="hg-cmd" moreinfo="none">hg status</command>, les fichiers copiés 1.4382 + ont l'air de fichiers normalement ajoutés.</para> 1.4383 + 1.4384 + <!-- BEGIN daily.copy.status --> 1.4385 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4386 +A new-file 1.4387 +</screen> 1.4388 +<!-- END daily.copy.status --> 1.4389 + 1.4390 + 1.4391 + <para id="x_1c1">Mais si nous passons l'option <option role="hg-opt-status">-C</option> à <command role="hg-cmd" moreinfo="none">hg 1.4392 + status</command>, il affiche une autre ligne de sortie : il s'agit 1.4393 + du fichier <emphasis>source</emphasis> pour notre copie.</para> 1.4394 + 1.4395 + <!-- BEGIN daily.copy.status-copy --> 1.4396 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput> 1.4397 +A new-file 1.4398 + file 1.4399 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Copied file'</userinput> 1.4400 +</screen> 1.4401 +<!-- END daily.copy.status-copy --> 1.4402 + 1.4403 + 1.4404 + <para id="x_1c2">Maintenant, de retour dans le dépôt que nous avons 1.4405 + cloné, créons un changement en parallèle. Nous allons ajouter une 1.4406 + ligne de contenu au fichier original qui a été créé.</para> 1.4407 + 1.4408 + <!-- BEGIN daily.copy.other --> 1.4409 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../your-copy</userinput> 1.4410 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'new contents' >> file</userinput> 1.4411 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Changed file'</userinput> 1.4412 +</screen> 1.4413 +<!-- END daily.copy.other --> 1.4414 + 1.4415 + 1.4416 + <para id="x_1c3">Nous avons alors un fichier <filename moreinfo="none">file</filename> 1.4417 + modifié dans ce dépôt. Lorsque nous récupérons (pull) les changements 1.4418 + depuis le premier répertoire et fusionnons (merge) les deux "heads", 1.4419 + Mercurial propagera les changements que nous avons faits localement 1.4420 + au fichier <filename moreinfo="none">file</filename> dans sa copie 1.4421 + <filename moreinfo="none">new-file</filename>.</para> 1.4422 + 1.4423 + <!-- BEGIN daily.copy.merge --> 1.4424 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-copy</userinput> 1.4425 +pulling from ../my-copy 1.4426 +searching for changes 1.4427 +adding changesets 1.4428 +adding manifests 1.4429 +adding file changes 1.4430 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.4431 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.4432 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.4433 +merging file and new-file to new-file 1.4434 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved 1.4435 +(branch merge, don't forget to commit) 1.4436 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat new-file</userinput> 1.4437 +line 1.4438 +new contents 1.4439 +</screen> 1.4440 +<!-- END daily.copy.merge --> 1.4441 + 1.4442 + 1.4443 + </sect2> 1.4444 + <sect2 id="sec:daily:why-copy"> 1.4445 + <title>Pourquoi est-ce que les changements devraient suivre les copies 1.4446 + ?</title> 1.4447 + 1.4448 + <para id="x_1c4">Ce comportement—des changements d'un fichiers 1.4449 + qui se propagent aux copies de ce fichier—peut sembler 1.4450 + ésotérique, mais, dans la plupart des cas, c'est hautement 1.4451 + désirable.</para> 1.4452 + 1.4453 + <para id="x_1c5">Pour commencer, souvenez vous que cette propagation 1.4454 + a lieue <emphasis>seulement</emphasis> lors des fusions (merge). 1.4455 + Donc, si vous faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur 1.4456 + un fichier, et par la suite modifiez le fichier original durant le 1.4457 + cours normal de votre travail, rien n'a lieu.</para> 1.4458 + 1.4459 + <para id="x_1c6">La deuxième chose à savoir c'est que les modifications 1.4460 + ne se propageront à travers une copie que si le changeset à partir 1.4461 + duquel vous faites une fusion (merge) <emphasis>n'a pas encore 1.4462 + vu</emphasis> la copie.</para> 1.4463 + 1.4464 + <para id="x_1c7">La raison pour laquelle Mercurial fait ainsi est une 1.4465 + règle. Imaginons que je corrige un important bug dans un fichier source 1.4466 + et que je commit mes changements. Pendant ce temps, vous avez décidé de 1.4467 + faire un <command role="hg-cmd" moreinfo="none">hg copy</command> du fichier dans 1.4468 + votre dépôt, sans rien savoir au sujet du bug ou à propos de la 1.4469 + correction. Vous avez alors commencé à "hacker" sur votre copie du 1.4470 + fichier.</para> 1.4471 + 1.4472 + <para id="x_1c8">Si vous aviez récupéré (pull) et fusionné (merge) mes 1.4473 + changements, et que Mercurial <emphasis>n'avait pas</emphasis> 1.4474 + propagé les changements à travers les copies, votre nouveau fichier 1.4475 + source contiendrait maintenant le bug, et à moins que vous ne sachiez 1.4476 + qu'il faille propager la correction du bug à la main, le bug aurait 1.4477 + <emphasis>subsisté</emphasis> dans votre copie du fichier.</para> 1.4478 + 1.4479 + <para id="x_1c9">En propageant automatiquement les changements qui 1.4480 + fixent les bugs à partir du fichier original vers les copies, 1.4481 + Mercurial prévient ce type de problèmes. A ma connaissance, Mercurial 1.4482 + est le <emphasis>seul</emphasis> système de gestion de révisions qui 1.4483 + propage les changements à travers les copies comme ceci.</para> 1.4484 + 1.4485 + <para id="x_1ca">Une fois que votre historique des changements a un 1.4486 + enregistrement concernant une copie et qu'une fusion postérieure a 1.4487 + eu lieue, il n'y a d'habitude pas d'autre besoin de propager les 1.4488 + changements du fichier originel vers le fichier copié. C'est pourquoi 1.4489 + Mercurial ne propage les changements à travers les copies qu'à la 1.4490 + première fusion, et pas d'avantage.</para> 1.4491 + </sect2> 1.4492 + 1.4493 + <sect2> 1.4494 + <title>Comment faire des changements qui <emphasis>ne</emphasis> 1.4495 + suivent <emphasis>pas</emphasis> une copie</title> 1.4496 + 1.4497 + <para id="x_1cb">Si pour une raison ou une autre, vous décidez que 1.4498 + cette fonctionnalité de propager automatiquement les changements à 1.4499 + travers les copies n'est pas pour vous, utilisez simplement la 1.4500 + commande normale de copie de votre système (sur les systèmes de type 1.4501 + Unix, il s'agit de <command moreinfo="none">cp</command>) pour faire une copie d'un 1.4502 + fichier. Utilisez ensuite <command role="hg-cmd" moreinfo="none">hg add</command> 1.4503 + pour ajouter les nouveaux fichiers à la main. Cependant, avant d'en 1.4504 + faire ainsi, relisez <xref linkend="sec:daily:why-copy"/>, et faites 1.4505 + un choix en connaissance de cause comme quoi cette fonctionnalité 1.4506 + n'est pas appropriée à votre cas spécifique.</para> 1.4507 + 1.4508 + </sect2> 1.4509 + <sect2> 1.4510 + <title>Comportement de la commande <command role="hg-cmd" moreinfo="none">hg copy</command></title> 1.4511 + 1.4512 + <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 1.4513 + fichier source tel qu'il est actuellement dans le répertoire de 1.4514 + travail. Cela signifie que si vous effectuez des modifications sur un 1.4515 + fichier, puis faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur 1.4516 + celui-ci sans avoir au préalable committé ces changements, la nouvelle 1.4517 + copie contiendra aussi les modifications que vous avez fait jusqu'à 1.4518 + ce point. (Je trouve ce comportement quelque peu contre intuitif, 1.4519 + c'est pourquoi j'en fais mention ici.)</para> 1.4520 + <!-- Vérifier que je n'ai pas fait de contre sens en relisant la 1.4521 + version anglaise, ce que je comprend ici me paraît un peu bizarre --> 1.4522 + 1.4523 + <para id="x_1cd">La commande <command role="hg-cmd" moreinfo="none">hg copy</command> 1.4524 + agit comme la commande Unix <command moreinfo="none">cp</command> (vous pouvez 1.4525 + utilisez l'alias <command role="hg-cmd" moreinfo="none">hg cp</command> si vous 1.4526 + préférez). Nous devons lui donner deux ou plus arguments où le 1.4527 + dernier est considéré comme la <emphasis>destination</emphasis>, et 1.4528 + les autres comme les <emphasis>sources</emphasis>.</para> 1.4529 + 1.4530 + <para id="x_685">Si vous passez à <command role="hg-cmd" moreinfo="none">hg 1.4531 + copy</command> un seul fichier source, et que la destination 1.4532 + n'existe pas, ceci créera un nouveau fichier avec ce nom.</para> 1.4533 + 1.4534 + <!-- BEGIN daily.copy.simple --> 1.4535 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir k</userinput> 1.4536 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a k</userinput> 1.4537 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls k</userinput> 1.4538 +a 1.4539 +</screen> 1.4540 +<!-- END daily.copy.simple --> 1.4541 + 1.4542 + 1.4543 + <para id="x_1ce">Si la destination est un répertoire, Mercurial copie 1.4544 + les sources dans ce répertoire.</para> 1.4545 + 1.4546 + <!-- BEGIN daily.copy.dir-dest --> 1.4547 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir d</userinput> 1.4548 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a b d</userinput> 1.4549 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls d</userinput> 1.4550 +a b 1.4551 +</screen> 1.4552 +<!-- END daily.copy.dir-dest --> 1.4553 + 1.4554 + 1.4555 + <para id="x_1cf">La copie de répertoire est récursive et préserve la 1.4556 + structure du répertoire source.</para> 1.4557 + 1.4558 + <!-- BEGIN daily.copy.dir-src --> 1.4559 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z e</userinput> 1.4560 +copying z/a/c to e/a/c 1.4561 +</screen> 1.4562 +<!-- END daily.copy.dir-src --> 1.4563 + 1.4564 + 1.4565 + <para id="x_1d0">Si la source et la destination sont tous deux des 1.4566 + répertoires, l'arborescence de la source est recréée dans le 1.4567 + répertoire destination.</para> 1.4568 + 1.4569 + <!-- BEGIN daily.copy.dir-src-dest --> 1.4570 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z d</userinput> 1.4571 +copying z/a/c to d/z/a/c 1.4572 +</screen> 1.4573 +<!-- END daily.copy.dir-src-dest --> 1.4574 + 1.4575 + 1.4576 + <para id="x_1d1">Comme avec la commande <command role="hg-cmd" moreinfo="none">hg 1.4577 + remove</command>, si vous copiez un fichier manuellement et voulez 1.4578 + que Mercurial sache qu'il s'agit d'une copie, utilisez simplement 1.4579 + l'option <option role="hg-opt-copy">--after</option> avec <command role="hg-cmd" moreinfo="none">hg copy</command>.</para> 1.4580 + 1.4581 + <!-- BEGIN daily.copy.after --> 1.4582 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp a n</userinput> 1.4583 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy --after a n</userinput> 1.4584 +</screen> 1.4585 +<!-- END daily.copy.after --> 1.4586 + 1.4587 + </sect2> 1.4588 + </sect1> 1.4589 + 1.4590 + <sect1> 1.4591 + <title>Renommer les fichiers</title> 1.4592 + 1.4593 + <para id="x_1d2">Il est plus commun d'avoir besoin de renommer un 1.4594 + fichier que d'en faire une copie. La raison pour laquelle j'ai discuté 1.4595 + de la commande <command role="hg-cmd" moreinfo="none">hg copy</command> avant de parler 1.4596 + de renommage des fichiers est que Mercurial traite les renommages 1.4597 + essentiellement comme une copie. Ainsi, savoir comment Mercurial traite 1.4598 + les copies de fichiers vous informe sur ce que vous êtes en droit 1.4599 + d'attendre lorsque vous renommez un fichier.</para> 1.4600 + 1.4601 + <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 1.4602 + les fichiers sources, les supprime et marque ces fichiers comme étant 1.4603 + supprimés.</para> 1.4604 + 1.4605 + <!-- BEGIN daily.rename.rename --> 1.4606 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput> 1.4607 +</screen> 1.4608 +<!-- END daily.rename.rename --> 1.4609 + 1.4610 + 1.4611 + <para id="x_1d4">La commande <command role="hg-cmd" moreinfo="none">hg status</command> 1.4612 + montre les nouveaux fichiers comme ajoutés et les fichiers originaux 1.4613 + comme supprimés.</para> 1.4614 + 1.4615 + <!-- BEGIN daily.rename.status --> 1.4616 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.4617 +A b 1.4618 +R a 1.4619 +</screen> 1.4620 +<!-- END daily.rename.status --> 1.4621 + 1.4622 + 1.4623 + <para id="x_1d5">A cause du <command role="hg-cmd" moreinfo="none">hg copy</command>, 1.4624 + nous devons utiliser l'option <option role="hg-opt-status">-C</option> 1.4625 + pour la commande <command role="hg-cmd" moreinfo="none">hg status</command> afin 1.4626 + d'observer que le fichier ajouté est bien suivi par Mercurial comme 1.4627 + étant une copie de l'original maintenant supprimé.</para> 1.4628 + 1.4629 + <!-- BEGIN daily.rename.status-copy --> 1.4630 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput> 1.4631 +A b 1.4632 + a 1.4633 +R a 1.4634 +</screen> 1.4635 +<!-- END daily.rename.status-copy --> 1.4636 + 1.4637 + 1.4638 + <para id="x_1d6">Comme avec <command role="hg-cmd" moreinfo="none">hg remove</command> et 1.4639 + <command role="hg-cmd" moreinfo="none">hg copy</command>, vous pouvez informer 1.4640 + Mercurial au sujet d'un renommage après coup en utilisant l'option 1.4641 + <option role="hg-opt-rename">--after</option>. Dans le plus grand 1.4642 + respect, le comportement de la commande <command role="hg-cmd" moreinfo="none">hg 1.4643 + rename</command>, et les options qu'il accepte sont similaires à la 1.4644 + commande <command role="hg-cmd" moreinfo="none">hg copy</command>.</para> 1.4645 + 1.4646 + <para id="x_686">Si vous êtes familier avec la ligne de commande Unix, 1.4647 + 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> 1.4648 + 1.4649 + <sect2> 1.4650 + <title>Renommer les fichiers et fusionner (merge) les changements</title> 1.4651 + 1.4652 + <para id="x_1d7">Puise que le "rename" de Mercurial est implanté comme un 1.4653 + "copy-and-remove", la même propagation des changements a lieue après 1.4654 + un "rename" qu'après un "copy" lorsque vous fusionnez (merge).</para> 1.4655 + 1.4656 + <para id="x_1d8">Si je modifie un fichier et que vous le renommez, si 1.4657 + ensuite nous fusionnons nos changements respectifs, mes modifications 1.4658 + sur le fichier sous son nom originel seront propagés vers le même 1.4659 + fichier sous son nouveau nom. (C'est quelque chose que vous pourriez 1.4660 + espérer voir <quote>fonctionner simplement</quote>, mais tous les 1.4661 + systèmes de gestion de version ne le font pas.)</para> 1.4662 + 1.4663 + <para id="x_1d9">Tandis qu'avoir des changements qui suivent une copie 1.4664 + est une fonctionnalité où vous hocheriez sûrement la tête en disant 1.4665 + <quote>oui, cela pourrait être utile</quote>, il est clair que les 1.4666 + voir suivre un renommage est définitivement important. Sans cette 1.4667 + aptitude, il serait vraiment trop facile d'avoir des changements 1.4668 + qui deviennent orphelins lorsque des fichiers sont renommés.</para> 1.4669 + </sect2> 1.4670 + 1.4671 + <sect2> 1.4672 + <title>Renommages divergeants et fusion (merge)</title> 1.4673 + 1.4674 + <para id="x_1da">Le cas de noms divergeants a lieu lorsque deux 1.4675 + développeurs commencent avec un fichier—appelons le 1.4676 + <filename moreinfo="none">foo</filename>—dans leurs dépôts respectifs.</para> 1.4677 + 1.4678 + <!-- BEGIN rename.divergent.clone --> 1.4679 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig anne</userinput> 1.4680 +updating working directory 1.4681 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4682 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig bob</userinput> 1.4683 +updating working directory 1.4684 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4685 +</screen> 1.4686 +<!-- END rename.divergent.clone --> 1.4687 + 1.4688 + 1.4689 + <para id="x_1db">Anne renomme le fichier en 1.4690 + <filename moreinfo="none">bar</filename>.</para> 1.4691 + 1.4692 + <!-- BEGIN rename.divergent.rename.anne --> 1.4693 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd anne</userinput> 1.4694 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename foo bar</userinput> 1.4695 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to bar'</userinput> 1.4696 +</screen> 1.4697 +<!-- END rename.divergent.rename.anne --> 1.4698 + 1.4699 + 1.4700 + <para id="x_1dc">Pendant ce temps, Bob le renomme en 1.4701 + <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> 1.4702 + 1.4703 + <!-- BEGIN rename.divergent.rename.bob --> 1.4704 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../bob</userinput> 1.4705 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg mv foo quux</userinput> 1.4706 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to quux'</userinput> 1.4707 +</screen> 1.4708 +<!-- END rename.divergent.rename.bob --> 1.4709 + 1.4710 + 1.4711 + <para id="x_1dd">J'aime à penser qu'il s'agit d'un conflit puisque 1.4712 + chaque développeur a exprimé différentes intentions au sujet de ce 1.4713 + que le nom de ce fichier aurait du être.</para> 1.4714 + 1.4715 + <para id="x_1de">Que pensez vous qu'il devrait se produire lorsqu'ils 1.4716 + fusionnent (merge) leurs travaux ? Le comportement actuel de 1.4717 + Mercurial est qu'il préserve toujours les <emphasis>deux</emphasis> 1.4718 + noms lorsqu'il fusionne (merge) des changesets qui contiennent des 1.4719 + renommages divergeants.</para> 1.4720 + 1.4721 + <!-- BEGIN rename.divergent.merge --> 1.4722 +<screen format="linespecific"># See http://www.selenic.com/mercurial/bts/issue455 1.4723 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../orig</userinput> 1.4724 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../anne</userinput> 1.4725 +pulling from ../anne 1.4726 +searching for changes 1.4727 +adding changesets 1.4728 +adding manifests 1.4729 +adding file changes 1.4730 +added 1 changesets with 1 changes to 1 files 1.4731 +1 files updated, 0 files merged, 1 files removed, 0 files unresolved 1.4732 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../bob</userinput> 1.4733 +pulling from ../bob 1.4734 +searching for changes 1.4735 +adding changesets 1.4736 +adding manifests 1.4737 +adding file changes 1.4738 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.4739 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.4740 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.4741 +warning: detected divergent renames of foo to: 1.4742 + bar 1.4743 + quux 1.4744 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4745 +(branch merge, don't forget to commit) 1.4746 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput> 1.4747 +bar quux 1.4748 +</screen> 1.4749 +<!-- END rename.divergent.merge --> 1.4750 + 1.4751 + 1.4752 + <para id="x_1df">Remarquez que bien que Mercurial vous avertisse au 1.4753 + sujet de la divergeance des renommages, il vous laisse faire quelque 1.4754 + chose au sujet de la divergeance après la fusion (merge).</para> 1.4755 + </sect2> 1.4756 + 1.4757 + <sect2> 1.4758 + <title>Renommages et fusion convergeants</title> 1.4759 + 1.4760 + <para id="x_1e0">Un autre type de conflit de renommage intervient 1.4761 + lorsque deux personne choisissent de renommer différents fichiers 1.4762 + <emphasis>source</emphasis> vers la même 1.4763 + <emphasis>destination</emphasis>. Dans ce cas, Mercurial exécute la 1.4764 + machinerie normale de fusion (merge) et vous guide vers une 1.4765 + solution convenable.</para> 1.4766 + </sect2> 1.4767 + 1.4768 + <sect2> 1.4769 + <title>Autres cas anguleux relatifs aux noms</title> 1.4770 + 1.4771 + <para id="x_1e1">Mercurial possède un bug de longue date dans lequel il 1.4772 + échoue à traiter une fusion (merge) où un coté a un fichier avec un 1.4773 + nom donné, alors que l'autre coté possède un répertoire avec le même nom. 1.4774 + Ceci est documenté dans l'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue29">issue 1.4775 + 29</ulink>.</para> 1.4776 + 1.4777 + <!-- BEGIN issue29.go --> 1.4778 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init issue29</userinput> 1.4779 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd issue29</userinput> 1.4780 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.4781 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Ama</userinput> 1.4782 +adding a 1.4783 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b</userinput> 1.4784 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amb</userinput> 1.4785 +adding b 1.4786 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg up 0</userinput> 1.4787 +0 files updated, 0 files merged, 1 files removed, 0 files unresolved 1.4788 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput> 1.4789 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b/b</userinput> 1.4790 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amc</userinput> 1.4791 +adding b/b 1.4792 +created new head 1.4793 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.4794 +abort: Is a directory: /tmp/issue29vhrzWD/issue29/b 1.4795 +</screen> 1.4796 +<!-- END issue29.go --> 1.4797 + 1.4798 + 1.4799 + </sect2> 1.4800 + </sect1> 1.4801 + 1.4802 + <sect1> 1.4803 + <title>Récupération d'erreurs</title> 1.4804 + 1.4805 + <para id="x_1e2">Mercurial possède certaines commandes utiles qui vont 1.4806 + vous aider à récupérer de certaines erreurs communes.</para> 1.4807 + 1.4808 + <para id="x_1e3">La commande <command role="hg-cmd" moreinfo="none">hg revert</command> 1.4809 + vous permet d'annuler les changements que vous avez faits dans votre 1.4810 + 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 1.4811 + juste <command role="hg-cmd" moreinfo="none">hg revert</command> avec le nom du fichier 1.4812 + que vous avez ajouté et tandis que le fichier ne sera touché d'une 1.4813 + quelconque manière, il ne sera plus suivi comme ajouté par Mercurial. 1.4814 + Vous pouvez aussi utiliser la commande <command role="hg-cmd" moreinfo="none">hg 1.4815 + revert</command> pour vous débarrasser de modifications erronés 1.4816 + apportées à un fichier.</para> 1.4817 + 1.4818 + <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 1.4819 + qui n'ont pas encore été committées. Une fois que vous avez committé un 1.4820 + changement, si vous décidez qu'il s'agissait d'une erreur, vous pouvez 1.4821 + toujours faire quelque chose à ce sujet, bien que vos options soient 1.4822 + un peu plus limitées.</para> 1.4823 + 1.4824 + <para id="x_1e5">Pour plus d'informations au sujet de la commande 1.4825 + <command role="hg-cmd" moreinfo="none">hg revert</command>, et des détails sur comment 1.4826 + traiter les modifications que vous avez déjà committées, référez vous à 1.4827 + <xref linkend="chap:undo"/>.</para> 1.4828 + </sect1> 1.4829 + 1.4830 + <sect1> 1.4831 + <title>Traiter avec les fusions (merge) malicieuses</title> 1.4832 + 1.4833 + <para id="x_687">Dans des projets compliqués ou conséquents, il n'est pas 1.4834 + rare qu'une fusion (merge) de deux changesets finisse par une migraine. 1.4835 + Supposez qu'il y ait un gros fichier source qui ait été largement édité de 1.4836 + chaque coté de la fusion (merge) : ceci va inévitablement résulter en 1.4837 + conflits, dont certains peuvent prendre plusieurs essais pour s'en 1.4838 + sortir.</para> 1.4839 + 1.4840 + <para id="x_688">Développons en un cas simple pour voir comment le gérer. 1.4841 + Nous allons commencer avec un dépôt contenant un fichier, et le 1.4842 + cloner deux fois.</para> 1.4843 + 1.4844 + <!-- BEGIN ch04/resolve.init --> 1.4845 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init conflict</userinput> 1.4846 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd conflict</userinput> 1.4847 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first > myfile.txt</userinput> 1.4848 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -A -m first</userinput> 1.4849 +adding myfile.txt 1.4850 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.4851 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict left</userinput> 1.4852 +updating working directory 1.4853 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4854 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict right</userinput> 1.4855 +updating working directory 1.4856 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4857 +</screen> 1.4858 +<!-- END ch04/resolve.init --> 1.4859 + 1.4860 + 1.4861 + <para id="x_689">Dans un des clones, nous allons modifier le fichier 1.4862 + d'une façon.</para> 1.4863 + 1.4864 + <!-- BEGIN ch04/resolve.left --> 1.4865 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd left</userinput> 1.4866 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo left >> myfile.txt</userinput> 1.4867 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m left</userinput> 1.4868 +</screen> 1.4869 +<!-- END ch04/resolve.left --> 1.4870 + 1.4871 + 1.4872 + <para id="x_68a">Dans un autre, nous allons modifier le fichier 1.4873 + différemment.</para> 1.4874 + 1.4875 + <!-- BEGIN ch04/resolve.right --> 1.4876 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../right</userinput> 1.4877 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo right >> myfile.txt</userinput> 1.4878 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m right</userinput> 1.4879 +</screen> 1.4880 +<!-- END ch04/resolve.right --> 1.4881 + 1.4882 + 1.4883 + <para id="x_68b">Ensuite, nous allons récupérer (pull) chaque ensemble de 1.4884 + changement dans notre dépôt original.</para> 1.4885 + 1.4886 + <!-- BEGIN ch04/resolve.pull --> 1.4887 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../conflict</userinput> 1.4888 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../left</userinput> 1.4889 +pulling from ../left 1.4890 +searching for changes 1.4891 +adding changesets 1.4892 +adding manifests 1.4893 +adding file changes 1.4894 +added 1 changesets with 1 changes to 1 files 1.4895 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.4896 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../right</userinput> 1.4897 +pulling from ../right 1.4898 +searching for changes 1.4899 +adding changesets 1.4900 +adding manifests 1.4901 +adding file changes 1.4902 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.4903 +not updating, since new heads added 1.4904 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.4905 +</screen> 1.4906 +<!-- END ch04/resolve.pull --> 1.4907 + 1.4908 + 1.4909 + <para id="x_68c">Nous nous attendons à ce que notre dépôt contienne deux 1.4910 + "heads".</para> 1.4911 + 1.4912 + <!-- BEGIN ch04/resolve.heads --> 1.4913 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> 1.4914 +changeset: 2:85f1afc84c33 1.4915 +tag: tip 1.4916 +parent: 0:14a820f81f48 1.4917 +user: Bryan O'Sullivan <bos@serpentine.com> 1.4918 +date: Sun Aug 16 14:04:51 2009 +0000 1.4919 +summary: right 1.4920 + 1.4921 +changeset: 1:085ebbf44348 1.4922 +user: Bryan O'Sullivan <bos@serpentine.com> 1.4923 +date: Sun Aug 16 14:04:51 2009 +0000 1.4924 +summary: left 1.4925 + 1.4926 +</screen> 1.4927 +<!-- END ch04/resolve.heads --> 1.4928 + 1.4929 + 1.4930 + <para id="x_68d">Normalement, si nous lançons <command role="hg-cmd" moreinfo="none">hg 1.4931 + merge</command> à ce point, il nous renverra vers une interface 1.4932 + utilisateur qui nous permettra de résoudre manuellement les éditions 1.4933 + conflictuelles sur le fichier <filename moreinfo="none">myfile.txt</filename>. 1.4934 + Cependant, pour simplifier ici les choses dans la présentation, nous 1.4935 + aimerions plutôt que la fusion (merge) échoue immédiatement. Voici une 1.4936 + façon de le faire.</para> 1.4937 + 1.4938 + <!-- BEGIN ch04/resolve.export --> 1.4939 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=false</userinput> 1.4940 +</screen> 1.4941 +<!-- END ch04/resolve.export --> 1.4942 + 1.4943 + 1.4944 + <para id="x_68e">Nous avons dit au processus de fusion de Mercurial 1.4945 + d'exécuter la commande <command moreinfo="none">false</command> (qui échoue 1.4946 + immédiatement, à la demande) s'il détecte une fusion (merge) qu'il ne 1.4947 + peut pas arranger automatiquement.</para> 1.4948 + 1.4949 + <para id="x_68f">Si nous appelons maintenant <command role="hg-cmd" moreinfo="none">hg 1.4950 + merge</command>, il devrait échouer et reporter une erreur.</para> 1.4951 + 1.4952 + <!-- BEGIN ch04/resolve.merge --> 1.4953 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.4954 +merging myfile.txt 1.4955 +merging myfile.txt failed! 1.4956 +0 files updated, 0 files merged, 0 files removed, 1 files unresolved 1.4957 +use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon 1.4958 +</screen> 1.4959 +<!-- END ch04/resolve.merge --> 1.4960 + 1.4961 + 1.4962 + <para id="x_690">Même si nous ne remarquons pas qu'une fusion (merge) a 1.4963 + échoué, Mercurial nous empêchera de committer le résultat d'une fusion 1.4964 + ratée.</para> 1.4965 + 1.4966 + <!-- BEGIN ch04/resolve.cifail --> 1.4967 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Attempt to commit a failed merge'</userinput> 1.4968 +abort: unresolved merge conflicts (see hg resolve) 1.4969 +</screen> 1.4970 +<!-- END ch04/resolve.cifail --> 1.4971 + 1.4972 + 1.4973 + <para id="x_691">Lorsque <command role="hg-cmd" moreinfo="none">hg commit</command> 1.4974 + échoue dans ce cas, il suggère que nous utilisons la commande peu 1.4975 + connue <command role="hg-cmd" moreinfo="none">hg resolve</command>. Comme d'habitude, 1.4976 + <command role="hg-cmd" moreinfo="none">hg help resolve</command> affichera une aide 1.4977 + sommaire.</para> 1.4978 + 1.4979 + <sect2> 1.4980 + <title>États de résolution des fichiers</title> 1.4981 + <!-- TODO Vérifier traduction : File resolution states --> 1.4982 + 1.4983 + <para id="x_692">Lorsqu'une fusion intervient, la plupart des fichiers 1.4984 + vont, la plupart du temps, rester sans modification. Pour chaque 1.4985 + fichier sur lequel Mercurial doit faire quelque chose, il suit l'état 1.4986 + de celui-ci.</para> 1.4987 + 1.4988 + <itemizedlist> 1.4989 + <listitem><para id="x_693">Un fichier 1.4990 + <quote><emphasis>resolved</emphasis></quote> a été fusionné 1.4991 + (merge) avec succès, que ce soit automatiquement par Mercurial ou 1.4992 + manuellement par une intervention humaine.</para></listitem> 1.4993 + <listitem><para id="x_694">Un fichier 1.4994 + <quote><emphasis>unresolved</emphasis></quote> n'a pas été 1.4995 + fusionné (merge) correctement et a besoin de plus 1.4996 + d'attention.</para> 1.4997 + </listitem> 1.4998 + </itemizedlist> 1.4999 + 1.5000 + <para id="x_695">Si Mercurial voit un fichier 1.5001 + <emphasis>quelconque</emphasis> dans un état 1.5002 + <quote>unresolved</quote> après une fusion (merge), il considère que 1.5003 + la fusion (merge) a échoué. Heureusement, nous n'avons pas à 1.5004 + recommencer la procédure à partir du début.</para> 1.5005 + 1.5006 + <para id="x_696">L'option <option role="hg-opt-resolve">--list</option> 1.5007 + 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 1.5008 + fusionné (merge).</para> 1.5009 + 1.5010 + <!-- BEGIN ch04/resolve.list --> 1.5011 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -l</userinput> 1.5012 +U myfile.txt 1.5013 +</screen> 1.5014 +<!-- END ch04/resolve.list --> 1.5015 + 1.5016 + 1.5017 + <para id="x_697">En sortie de <command role="hg-cmd" moreinfo="none">hg 1.5018 + resolve</command>, un fichier "resolved" est marqué avec un 1.5019 + <literal moreinfo="none">R</literal>, alors qu'un fichier "unresolved" est marqué 1.5020 + d'un <literal moreinfo="none">U</literal>. S'il existe un fichier listé avec un 1.5021 + <literal moreinfo="none">U</literal>, nous savons qu'essayer de committer le résultat 1.5022 + de la fusion (merge) échouera.</para> 1.5023 + </sect2> 1.5024 + 1.5025 + <sect2> 1.5026 + <title>Résoudre une fusion de fichier</title> 1.5027 + 1.5028 + <para id="x_698">Nous avons plusieurs options pour changer l'état d'un 1.5029 + fichier de "unresolved" à "resolved". Le plus commun est de relancer 1.5030 + <command role="hg-cmd" moreinfo="none">hg resolve</command>. Si nous passons les noms 1.5031 + des fichiers individuels ou des répertoires, ceci retentera la fusion 1.5032 + de tous les fichiers présents à cet endroit. Nous pouvons aussi 1.5033 + passer l'option <option role="hg-opt-resolve">--all</option> ou 1.5034 + <option role="hg-opt-resolve">-a</option> qui tentera de fusionner 1.5035 + <emphasis>tous</emphasis> les fichiers "unresolved".</para> 1.5036 + 1.5037 + <para id="x_699">Mercurial nous laisse aussi modifier la résolution 1.5038 + d'un fichier directement. Nous pouvons marquer un fichier "resolved" 1.5039 + en utilisant l'option <option role="hg-opt-resolve">--mark</option>, 1.5040 + ou "unresolved" en utilisant l'option <option role="hg-opt-resolve">--unmark</option>. Ceci nous autorise à 1.5041 + nettoyer une fusion particulièrement compliquée à la main, et de 1.5042 + garder un suivi de nos progrès avec chaque fichier pendant que nous 1.5043 + procédons.</para> 1.5044 + </sect2> 1.5045 + </sect1> 1.5046 + 1.5047 + <sect1> 1.5048 + <title>Des "diffs" plus utiles</title> 1.5049 + 1.5050 + <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 1.5051 + la commande régulière <command moreinfo="none">diff</command>, mais ceci a quelques 1.5052 + inconvénients.</para> 1.5053 + 1.5054 + <para id="x_6c8">Considérez le cas où nous utilisons <command role="hg-cmd" moreinfo="none">hg 1.5055 + rename</command> pour renommer un fichier.</para> 1.5056 + 1.5057 + <!-- BEGIN ch04/diff.rename.basic --> 1.5058 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput> 1.5059 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> 1.5060 +diff -r f5deb7868663 a 1.5061 +--- a/a Sun Aug 16 14:04:49 2009 +0000 1.5062 ++++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.5063 +@@ -1,1 +0,0 @@ 1.5064 +-a 1.5065 +diff -r f5deb7868663 b 1.5066 +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.5067 ++++ b/b Sun Aug 16 14:04:49 2009 +0000 1.5068 +@@ -0,0 +1,1 @@ 1.5069 ++a 1.5070 +</screen> 1.5071 +<!-- END ch04/diff.rename.basic --> 1.5072 + 1.5073 + 1.5074 + <para id="x_6c9">La sortie de <command role="hg-cmd" moreinfo="none">hg diff</command> 1.5075 + ci-dessus cache le fait que nous avons simplement renommé un fichier. 1.5076 + La commande <command role="hg-cmd" moreinfo="none">hg diff</command> accepte l'option 1.5077 + <option>--git</option> ou <option>-g</option> pour utiliser un nouveau 1.5078 + format de diff qui montre ces informations sous une forme plus 1.5079 + expressive.</para> 1.5080 + 1.5081 + <!-- BEGIN ch04/diff.rename.git --> 1.5082 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput> 1.5083 +diff --git a/a b/b 1.5084 +rename from a 1.5085 +rename to b 1.5086 +</screen> 1.5087 +<!-- END ch04/diff.rename.git --> 1.5088 + 1.5089 + 1.5090 + <para id="x_6ca">Cette option peut aussi aider avec le cas autrement 1.5091 + confus : un fichier qui apparaît comme étant modifié en accord avec 1.5092 + <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 1.5093 + survenir si nous changeons les permissions d'exécution du 1.5094 + fichier.</para> 1.5095 + 1.5096 + <!-- BEGIN ch04/diff.chmod --> 1.5097 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x a</userinput> 1.5098 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg st</userinput> 1.5099 +M a 1.5100 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> 1.5101 +</screen> 1.5102 +<!-- END ch04/diff.chmod --> 1.5103 + 1.5104 + 1.5105 + <para id="x_6cb">La commande normale <command moreinfo="none">diff</command> ne fait pas 1.5106 + attention aux permissions des fichiers, ce qui explique pourquoi 1.5107 + <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien du tout par 1.5108 + défaut. Si nous lui passons l'option <option>-g</option>, ceci nous 1.5109 + informe de ce qu'il s'est vraiment passé.</para> 1.5110 + 1.5111 + <!-- BEGIN ch04/diff.chmod.git --> 1.5112 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput> 1.5113 +diff --git a/a b/a 1.5114 +old mode 100644 1.5115 +new mode 100755 1.5116 +</screen> 1.5117 +<!-- END ch04/diff.chmod.git --> 1.5118 + 1.5119 + </sect1> 1.5120 + 1.5121 + <sect1> 1.5122 + <title>Quels fichiers suivre et lesquels éviter</title> 1.5123 + 1.5124 + <para id="x_6cc">Les systèmes de gestion de révisions sont en général 1.5125 + meilleurs pour gérer les fichiers textes qui sont écrits par les 1.5126 + humains, comme le code source, où les fichiers ne changent pas 1.5127 + énormément d'une révision à l'autre. Certains systèmes de gestion de 1.5128 + révisions centralisés peuvent aussi traiter très convenablement les 1.5129 + fichiers binaires, tels que les images bitmap.</para> 1.5130 + 1.5131 + <para id="x_6cd">Par exemple, une équipe de développement de jeux va 1.5132 + probablement gérer les deux types : ses codes source et tous ses binaires 1.5133 + (ex. données géométriques, textures, schémas de cartes) dans un système 1.5134 + de contrôle de révisions.</para> 1.5135 + <!-- Vérifier la traduction de map layouts que j'ai traduit par schémas 1.5136 + de cartes --> 1.5137 + 1.5138 + <para id="x_6ce">Puisqu'il est d'habitude impossible de fusionner (merge) 1.5139 + deux modifications conflictuelles sur un fichier binaire, les systèmes 1.5140 + de version centralisés offrent souvent un mécanisme de verrou (lock) qui 1.5141 + permet à un utilisateur de dire <quote>Je suis la seule personne qui 1.5142 + peut éditer ce fichier</quote>.</para> 1.5143 + 1.5144 + <para id="x_6cf">En comparaison avec un système centralisé, un système 1.5145 + décentralisé de gestion de révision change certains facteurs qui 1.5146 + guident les décisions sur quels fichiers gérer et comment.</para> 1.5147 + 1.5148 + <para id="x_6d0">Par exemple, un système distribué de gestion de révisions 1.5149 + ne peut pas, par sa nature, offrir un système de véroux (lock) sur les 1.5150 + fichiers. Il n'y a donc pas de mécanisme inclus pour empêcher deux 1.5151 + personnes de faire des modifications conflictuelles sur un fichier 1.5152 + binaire. Si vous avez une équipe où plusieurs personnes peuvent souvent 1.5153 + éditer un fichier binaire, cela ne serait pas une très bonne idée 1.5154 + d'utiliser Mercurial —ou tout autre système distribué de gestion 1.5155 + de révisions—pour gérer ces fichiers.</para> 1.5156 + 1.5157 + <para id="x_6d1">Lorsque vous sauvegardez les modifications sur un 1.5158 + fichier, Mercurial ne sauvegarde d'habitude que les différences entre 1.5159 + la version précédente et la version actuelle d'un fichier. Pour la 1.5160 + plupart des fichiers texte, ceci est très efficace. Cependant, certains 1.5161 + fichiers (en particulier les fichiers binaires) sont construits d'une 1.5162 + façon que même un petit changement sur un contenu logique résulte sur 1.5163 + un changement de la plupart des octets du fichier. Par exemple, les 1.5164 + fichiers compressés sont particulièrement sujets à ce comportement. Si 1.5165 + les différences entre deux versions successives d'un fichier sont 1.5166 + toujours très grandes, Mercurial ne sera pas capable de sauvegarder 1.5167 + l'historique des révisions sur le fichier très efficacement. Ceci peut 1.5168 + affecter aussi bien les besoins pour la sauvegarde locale que le temps 1.5169 + nécessaire à cloner le dépôt.</para> 1.5170 + 1.5171 + <para id="x_6d2">Pour avoir une idée de comment ceci pourrait vous 1.5172 + affecter en pratique, supposez que nous voulions que Mercurial gère des 1.5173 + documents OpenOffice. OpenOffice sauvegarde les documents sur le disque 1.5174 + comme des fichiers compressés zip. Même le fait d'éditer ces fichiers 1.5175 + d'une seule lettre, changera les bits de la quasi totalité du fichier 1.5176 + lorsque vous le sauvegarderez. Maintenant, supposez que ce fichier 1.5177 + fasse une taille de 2Mo. Puisque la plupart du fichier change à chaque 1.5178 + fois que vous sauvegardez, Mercurial aura à sauvegarder tous les 2Mo du 1.5179 + fichier à chaque commit, alors que de votre point de vue, il n'y a 1.5180 + que peu de mots qui changent à chaque fois. Un seul fichier 1.5181 + souvent édité qui n'est pas bien traité par les hypothèses que Mercurial 1.5182 + fait sur les sauvegardes peut facilement avoir un effet colossal sur la 1.5183 + taille du dépôt.</para> 1.5184 + 1.5185 + <para id="x_6d3">Même pire, si vous et quelqu'un d'autre éditez le même 1.5186 + document OpenOffice sur lequel vous travaillez, il n'y a pas de façon 1.5187 + utile pour fusionner votre travail. En fait, il n'y a pas de moyen 1.5188 + utile de montrer que les différences sont faites à partir de votre 1.5189 + vision des modifications.</para> 1.5190 + 1.5191 + <para id="x_6d4">Il y a ainsi quelques recommandations claires sur les 1.5192 + types de fichiers spécifiques avec lesquels faire très 1.5193 + attention.</para> 1.5194 + 1.5195 + <itemizedlist> 1.5196 + <listitem><para id="x_6d5">Les fichier qui sont très gros et 1.5197 + incompressibles, comme les images ISO de CD-ROM, sont, par 1.5198 + construction très gros et les cloner à travers un réseau sera très 1.5199 + long.</para></listitem> 1.5200 + <!-- TODO : Trouver une meilleure traduction pour : ISO CD-ROM images, will by 1.5201 + virtue of sheer size make clones over a network very slow. --> 1.5202 + <listitem><para id="x_6d6">Les fichiers qui changent beaucoup d'une 1.5203 + révision à l'autre peuvent être très chers à sauvegarder si vous 1.5204 + les éditez fréquemment, de même que les conflits entre deux éditions 1.5205 + concurrentes peuvent être difficiles à résoudre.</para> 1.5206 + </listitem> 1.5207 + </itemizedlist> 1.5208 + </sect1> 1.5209 + 1.5210 + <sect1> 1.5211 + <title>Sauvegardes et miroirs</title> 1.5212 + 1.5213 + <para id="x_6d7">Puisque Mercurial maintient une copie complète de 1.5214 + l'historique de chaque clone, toute personne qui utilise Mercurial pour 1.5215 + collaborer à un projet peut potentiellement agir comme une source de 1.5216 + sauvegarde si une catastrophe survenait. Si un dépôt central devient 1.5217 + indisponible, vous pouvez construire un remplaçant en clonant une copie 1.5218 + du dépôt à partir d'un des contributeurs en récupérant (pull) tous les 1.5219 + changements qui n'auraient pas été vus par les autres.</para> 1.5220 + 1.5221 + <para id="x_6d8">Il est simple d'utiliser Mercurial pour construire des 1.5222 + serveurs hors site de sauvegarde et des miroirs distants. Initiez une 1.5223 + tâche périodique (ex. via la commande <command moreinfo="none">cron</command>) sur un 1.5224 + serveur distant pour récupérer (pull) les changements de votre dépôt 1.5225 + distant chaque heure. Ceci sera difficile seulement dans le cas 1.5226 + improbable où le nombre des dépôts maîtres que vous maintenez change 1.5227 + souvent, auquel cas vous aurez besoin de faire un peu de scripting pour 1.5228 + rafraichir la liste des dépôt à sauvegarder.</para> 1.5229 + 1.5230 + <para id="x_6d9">Si vous exécutez des sauvegardes traditionnelles de 1.5231 + votre dépôt maître sur bande ou disque, et que vous voulez sauvegarder 1.5232 + un dépôt nommé <filename moreinfo="none">myrepo</filename>, utilisez la commande 1.5233 + <command moreinfo="none">hg clone -U myrepo myrepo.bak</command> pour créer un clone de 1.5234 + <filename moreinfo="none">myrepo</filename> avant de commencer vos backups. 1.5235 + L'option <option>-U</option> ne crée pas de répertoire de travail après 1.5236 + que le clone soit accompli, puisque ceci serait superflu et ferait que 1.5237 + la sauvegarde prenne plus de temps.</para> 1.5238 + 1.5239 + <para id="x_6da">Si vous voulez ensuite sauvegarder 1.5240 + <filename moreinfo="none">myrepo.bak</filename> au lieu de <filename moreinfo="none">myrepo</filename>, 1.5241 + vous aurez la garantie d'avoir une image (snapshot) consistante de 1.5242 + votre dépôt sur lequel un développeur insomniaque n'enverra (push) pas de 1.5243 + changements en milieu de sauvegarde.</para> 1.5244 + </sect1> 1.5245 +</chapter> 1.5246 + 1.5247 +<!-- 1.5248 +local variables: 1.5249 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.5250 +end: 1.5251 +--> 1.5252 + 1.5253 + <!-- BEGIN ch06 --> 1.5254 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.5255 + 1.5256 +<chapter id="cha:collab"> 1.5257 + <?dbhtml filename="collaborating-with-other-people.html"?> 1.5258 + <title>Collaborating with other people</title> 1.5259 + 1.5260 + <para id="x_44a">As a completely decentralised tool, Mercurial doesn't impose 1.5261 + any policy on how people ought to work with each other. However, 1.5262 + if you're new to distributed revision control, it helps to have 1.5263 + some tools and examples in mind when you're thinking about 1.5264 + possible workflow models.</para> 1.5265 + 1.5266 + <sect1> 1.5267 + <title>Mercurial's web interface</title> 1.5268 + 1.5269 + <para id="x_44b">Mercurial has a powerful web interface that provides several 1.5270 + useful capabilities.</para> 1.5271 + 1.5272 + <para id="x_44c">For interactive use, the web interface lets you browse a 1.5273 + single repository or a collection of repositories. You can view 1.5274 + the history of a repository, examine each change (comments and 1.5275 + diffs), and view the contents of each directory and file. You 1.5276 + can even get a view of history that gives a graphical view of 1.5277 + the relationships between individual changes and merges.</para> 1.5278 + 1.5279 + <para id="x_44d">Also for human consumption, the web interface provides 1.5280 + Atom and RSS feeds of the changes in a repository. This lets you 1.5281 + <quote>subscribe</quote> to a repository using your favorite 1.5282 + feed reader, and be automatically notified of activity in that 1.5283 + repository as soon as it happens. I find this capability much 1.5284 + more convenient than the model of subscribing to a mailing list 1.5285 + to which notifications are sent, as it requires no additional 1.5286 + configuration on the part of whoever is serving the 1.5287 + repository.</para> 1.5288 + 1.5289 + <para id="x_44e">The web interface also lets remote users clone a repository, 1.5290 + pull changes from it, and (when the server is configured to 1.5291 + permit it) push changes back to it. Mercurial's HTTP tunneling 1.5292 + protocol aggressively compresses data, so that it works 1.5293 + efficiently even over low-bandwidth network connections.</para> 1.5294 + 1.5295 + <para id="x_44f">The easiest way to get started with the web interface is to 1.5296 + use your web browser to visit an existing repository, such as 1.5297 + the master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg">http://www.selenic.com/repo/hg</ulink>.</para> 1.5298 + 1.5299 + <para id="x_450">If you're interested in providing a web interface 1.5300 + to your own repositories, there are several good ways to do 1.5301 + this.</para> 1.5302 + 1.5303 + <para id="x_69d">The easiest and fastest way to get started in an informal 1.5304 + environment is to use the <command role="hg-cmd" moreinfo="none">hg 1.5305 + serve</command> command, which is best suited to short-term 1.5306 + <quote>lightweight</quote> serving. See <xref linkend="sec:collab:serve"/> below for details of how to use 1.5307 + this command.</para> 1.5308 + 1.5309 + <para id="x_69e">For longer-lived repositories that you'd like to 1.5310 + have permanently available, there are several public hosting 1.5311 + services available. Some are free to open source projects, 1.5312 + while others offer paid commercial hosting. An up-to-date list 1.5313 + 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> 1.5314 + 1.5315 + <para id="x_6a0">If you would prefer to host your own repositories, Mercurial 1.5316 + has built-in support for several popular hosting technologies, 1.5317 + most notably CGI (Common Gateway Interface), and WSGI (Web 1.5318 + Services Gateway Interface). See <xref linkend="sec:collab:cgi"/> for details of CGI and WSGI 1.5319 + configuration.</para> 1.5320 + </sect1> 1.5321 + 1.5322 + <sect1> 1.5323 + <title>Collaboration models</title> 1.5324 + 1.5325 + <para id="x_451">With a suitably flexible tool, making decisions about 1.5326 + workflow is much more of a social engineering challenge than a 1.5327 + technical one. Mercurial imposes few limitations on how you can 1.5328 + structure the flow of work in a project, so it's up to you and 1.5329 + your group to set up and live with a model that matches your own 1.5330 + particular needs.</para> 1.5331 + 1.5332 + <sect2> 1.5333 + <title>Factors to keep in mind</title> 1.5334 + 1.5335 + <para id="x_452">The most important aspect of any model that you must keep 1.5336 + in mind is how well it matches the needs and capabilities of 1.5337 + the people who will be using it. This might seem 1.5338 + self-evident; even so, you still can't afford to forget it for 1.5339 + a moment.</para> 1.5340 + 1.5341 + <para id="x_453">I once put together a workflow model that seemed to make 1.5342 + perfect sense to me, but that caused a considerable amount of 1.5343 + consternation and strife within my development team. In spite 1.5344 + of my attempts to explain why we needed a complex set of 1.5345 + branches, and how changes ought to flow between them, a few 1.5346 + team members revolted. Even though they were smart people, 1.5347 + they didn't want to pay attention to the constraints we were 1.5348 + operating under, or face the consequences of those constraints 1.5349 + in the details of the model that I was advocating.</para> 1.5350 + 1.5351 + <para id="x_454">Don't sweep foreseeable social or technical problems under 1.5352 + the rug. Whatever scheme you put into effect, you should plan 1.5353 + for mistakes and problem scenarios. Consider adding automated 1.5354 + machinery to prevent, or quickly recover from, trouble that 1.5355 + you can anticipate. As an example, if you intend to have a 1.5356 + branch with not-for-release changes in it, you'd do well to 1.5357 + think early about the possibility that someone might 1.5358 + accidentally merge those changes into a release branch. You 1.5359 + could avoid this particular problem by writing a hook that 1.5360 + prevents changes from being merged from an inappropriate 1.5361 + branch.</para> 1.5362 + </sect2> 1.5363 + 1.5364 + <sect2> 1.5365 + <title>Informal anarchy</title> 1.5366 + 1.5367 + <para id="x_455">I wouldn't suggest an <quote>anything goes</quote> 1.5368 + approach as something sustainable, but it's a model that's 1.5369 + easy to grasp, and it works perfectly well in a few unusual 1.5370 + situations.</para> 1.5371 + 1.5372 + <para id="x_456">As one example, many projects have a loose-knit group of 1.5373 + collaborators who rarely physically meet each other. Some 1.5374 + groups like to overcome the isolation of working at a distance 1.5375 + by organizing occasional <quote>sprints</quote>. In a sprint, 1.5376 + a number of people get together in a single location (a 1.5377 + company's conference room, a hotel meeting room, that kind of 1.5378 + place) and spend several days more or less locked in there, 1.5379 + hacking intensely on a handful of projects.</para> 1.5380 + 1.5381 + <para id="x_457">A sprint or a hacking session in a coffee shop are the perfect places to use the 1.5382 + <command role="hg-cmd" moreinfo="none">hg serve</command> command, since 1.5383 + <command role="hg-cmd" moreinfo="none">hg serve</command> does not require any 1.5384 + fancy server infrastructure. You can get started with 1.5385 + <command role="hg-cmd" moreinfo="none">hg serve</command> in moments, by 1.5386 + reading <xref linkend="sec:collab:serve"/> below. Then simply 1.5387 + tell the person next to you that you're running a server, send 1.5388 + the URL to them in an instant message, and you immediately 1.5389 + have a quick-turnaround way to work together. They can type 1.5390 + your URL into their web browser and quickly review your 1.5391 + changes; or they can pull a bugfix from you and verify it; or 1.5392 + they can clone a branch containing a new feature and try it 1.5393 + out.</para> 1.5394 + 1.5395 + <para id="x_458">The charm, and the problem, with doing things 1.5396 + in an ad hoc fashion like this is that only people who know 1.5397 + about your changes, and where they are, can see them. Such an 1.5398 + informal approach simply doesn't scale beyond a handful 1.5399 + people, because each individual needs to know about 1.5400 + <emphasis>n</emphasis> different repositories to pull 1.5401 + from.</para> 1.5402 + </sect2> 1.5403 + 1.5404 + <sect2> 1.5405 + <title>A single central repository</title> 1.5406 + 1.5407 + <para id="x_459">For smaller projects migrating from a centralised revision 1.5408 + control tool, perhaps the easiest way to get started is to 1.5409 + have changes flow through a single shared central repository. 1.5410 + This is also the most common <quote>building block</quote> for 1.5411 + more ambitious workflow schemes.</para> 1.5412 + 1.5413 + <para id="x_45a">Contributors start by cloning a copy of this repository. 1.5414 + They can pull changes from it whenever they need to, and some 1.5415 + (perhaps all) developers have permission to push a change back 1.5416 + when they're ready for other people to see it.</para> 1.5417 + 1.5418 + <para id="x_45b">Under this model, it can still often make sense for people 1.5419 + to pull changes directly from each other, without going 1.5420 + through the central repository. Consider a case in which I 1.5421 + have a tentative bug fix, but I am worried that if I were to 1.5422 + publish it to the central repository, it might subsequently 1.5423 + break everyone else's trees as they pull it. To reduce the 1.5424 + potential for damage, I can ask you to clone my repository 1.5425 + into a temporary repository of your own and test it. This 1.5426 + lets us put off publishing the potentially unsafe change until 1.5427 + it has had a little testing.</para> 1.5428 + 1.5429 + <para id="x_45c">If a team is hosting its own repository in this 1.5430 + kind of scenario, people will usually use the 1.5431 + <command moreinfo="none">ssh</command> protocol to securely push changes to 1.5432 + the central repository, as documented in <xref linkend="sec:collab:ssh"/>. It's also usual to publish a 1.5433 + read-only copy of the repository over HTTP, as in 1.5434 + <xref linkend="sec:collab:cgi"/>. Publishing over HTTP 1.5435 + satisfies the needs of people who don't have push access, and 1.5436 + those who want to use web browsers to browse the repository's 1.5437 + history.</para> 1.5438 + </sect2> 1.5439 + 1.5440 + <sect2> 1.5441 + <title>A hosted central repository</title> 1.5442 + 1.5443 + <para id="x_6a1">A wonderful thing about public hosting services like 1.5444 + <ulink url="http://bitbucket.org/">Bitbucket</ulink> is that 1.5445 + not only do they handle the fiddly server configuration 1.5446 + details, such as user accounts, authentication, and secure 1.5447 + wire protocols, they provide additional infrastructure to make 1.5448 + this model work well.</para> 1.5449 + 1.5450 + <para id="x_6a2">For instance, a well-engineered hosting service will let 1.5451 + people clone their own copies of a repository with a single 1.5452 + click. This lets people work in separate spaces and share 1.5453 + their changes when they're ready.</para> 1.5454 + 1.5455 + <para id="x_6a3">In addition, a good hosting service will let people 1.5456 + communicate with each other, for instance to say <quote>there 1.5457 + are changes ready for you to review in this 1.5458 + tree</quote>.</para> 1.5459 + </sect2> 1.5460 + 1.5461 + <sect2> 1.5462 + <title>Working with multiple branches</title> 1.5463 + 1.5464 + <para id="x_45d">Projects of any significant size naturally tend to make 1.5465 + progress on several fronts simultaneously. In the case of 1.5466 + software, it's common for a project to go through periodic 1.5467 + official releases. A release might then go into 1.5468 + <quote>maintenance mode</quote> for a while after its first 1.5469 + publication; maintenance releases tend to contain only bug 1.5470 + fixes, not new features. In parallel with these maintenance 1.5471 + releases, one or more future releases may be under 1.5472 + development. People normally use the word 1.5473 + <quote>branch</quote> to refer to one of these many slightly 1.5474 + different directions in which development is 1.5475 + proceeding.</para> 1.5476 + 1.5477 + <para id="x_45e">Mercurial is particularly well suited to managing a number 1.5478 + of simultaneous, but not identical, branches. Each 1.5479 + <quote>development direction</quote> can live in its own 1.5480 + central repository, and you can merge changes from one to 1.5481 + another as the need arises. Because repositories are 1.5482 + independent of each other, unstable changes in a development 1.5483 + branch will never affect a stable branch unless someone 1.5484 + explicitly merges those changes into the stable branch.</para> 1.5485 + 1.5486 + <para id="x_45f">Here's an example of how this can work in practice. Let's 1.5487 + say you have one <quote>main branch</quote> on a central 1.5488 + server.</para> 1.5489 + 1.5490 + <!-- BEGIN branching.init --> 1.5491 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init main</userinput> 1.5492 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main</userinput> 1.5493 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a boring feature.' > myfile</userinput> 1.5494 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'We have reached an important milestone!'</userinput> 1.5495 +adding myfile 1.5496 +</screen> 1.5497 +<!-- END branching.init --> 1.5498 + 1.5499 + 1.5500 + <para id="x_460">People clone it, make changes locally, test them, and push 1.5501 + them back.</para> 1.5502 + 1.5503 + <para id="x_461">Once the main branch reaches a release milestone, you can 1.5504 + use the <command role="hg-cmd" moreinfo="none">hg tag</command> command to 1.5505 + give a permanent name to the milestone revision.</para> 1.5506 + 1.5507 + <!-- BEGIN branching.tag --> 1.5508 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput> 1.5509 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.5510 +changeset: 1:5e447fdaf941 1.5511 +tag: tip 1.5512 +user: Bryan O'Sullivan <bos@serpentine.com> 1.5513 +date: Sun Aug 16 14:04:47 2009 +0000 1.5514 +summary: Added tag v1.0 for changeset 6412b791fd06 1.5515 + 1.5516 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> 1.5517 +tip 1:5e447fdaf941 1.5518 +v1.0 0:6412b791fd06 1.5519 +</screen> 1.5520 +<!-- END branching.tag --> 1.5521 + 1.5522 + 1.5523 + <para id="x_462">Let's say some ongoing 1.5524 + development occurs on the main branch.</para> 1.5525 + 1.5526 + <!-- BEGIN branching.main --> 1.5527 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput> 1.5528 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is exciting and new!' >> myfile</userinput> 1.5529 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add a new feature'</userinput> 1.5530 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.5531 +This is a boring feature. 1.5532 +This is exciting and new! 1.5533 +</screen> 1.5534 +<!-- END branching.main --> 1.5535 + 1.5536 + 1.5537 + <para id="x_463">Using the tag that was recorded at the milestone, people 1.5538 + who clone that repository at any time in the future can use 1.5539 + <command role="hg-cmd" moreinfo="none">hg update</command> to get a copy of 1.5540 + the working directory exactly as it was when that tagged 1.5541 + revision was committed.</para> 1.5542 + 1.5543 + <!-- BEGIN branching.update --> 1.5544 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.5545 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -U main main-old</userinput> 1.5546 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main-old</userinput> 1.5547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update v1.0</userinput> 1.5548 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.5549 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.5550 +This is a boring feature. 1.5551 +</screen> 1.5552 +<!-- END branching.update --> 1.5553 + 1.5554 + 1.5555 + <para id="x_464">In addition, immediately after the main branch is tagged, 1.5556 + we can then clone the main branch on the server to a new 1.5557 + <quote>stable</quote> branch, also on the server.</para> 1.5558 + 1.5559 + <!-- BEGIN branching.clone --> 1.5560 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.5561 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -rv1.0 main stable</userinput> 1.5562 +requesting all changes 1.5563 +adding changesets 1.5564 +adding manifests 1.5565 +adding file changes 1.5566 +added 1 changesets with 1 changes to 1 files 1.5567 +updating working directory 1.5568 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.5569 +</screen> 1.5570 +<!-- END branching.clone --> 1.5571 + 1.5572 + 1.5573 + <para id="x_465">If we need to make a change to the stable 1.5574 + branch, we can then clone <emphasis>that</emphasis> 1.5575 + repository, make our changes, commit, and push our changes 1.5576 + back there.</para> 1.5577 + 1.5578 + <!-- BEGIN branching.stable --> 1.5579 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone stable stable-fix</userinput> 1.5580 +updating working directory 1.5581 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.5582 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd stable-fix</userinput> 1.5583 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a fix to a boring feature.' > myfile</userinput> 1.5584 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Fix a bug'</userinput> 1.5585 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> 1.5586 +pushing to /tmp/branchingPsTziR/stable 1.5587 +searching for changes 1.5588 +adding changesets 1.5589 +adding manifests 1.5590 +adding file changes 1.5591 +added 1 changesets with 1 changes to 1 files 1.5592 +</screen> 1.5593 +<!-- END branching.stable --> 1.5594 + 1.5595 + 1.5596 + <para id="x_466">Because Mercurial repositories are independent, and 1.5597 + Mercurial doesn't move changes around automatically, the 1.5598 + stable and main branches are <emphasis>isolated</emphasis> 1.5599 + from each other. The changes that we made on the main branch 1.5600 + don't <quote>leak</quote> to the stable branch, and vice 1.5601 + versa.</para> 1.5602 + 1.5603 + <para id="x_467">We'll often want all of our bugfixes on the stable 1.5604 + branch to show up on the main branch, too. Rather than 1.5605 + rewrite a bugfix on the main branch, we can simply pull and 1.5606 + merge changes from the stable to the main branch, and 1.5607 + Mercurial will bring those bugfixes in for us.</para> 1.5608 + 1.5609 + <!-- BEGIN branching.merge --> 1.5610 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput> 1.5611 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../stable</userinput> 1.5612 +pulling from ../stable 1.5613 +searching for changes 1.5614 +adding changesets 1.5615 +adding manifests 1.5616 +adding file changes 1.5617 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.5618 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.5619 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.5620 +merging myfile 1.5621 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved 1.5622 +(branch merge, don't forget to commit) 1.5623 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Bring in bugfix from stable branch'</userinput> 1.5624 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.5625 +This is a fix to a boring feature. 1.5626 +This is exciting and new! 1.5627 +</screen> 1.5628 +<!-- END branching.merge --> 1.5629 + 1.5630 + 1.5631 + <para id="x_468">The main branch will still contain changes that 1.5632 + are not on the stable branch, but it will also contain all of 1.5633 + the bugfixes from the stable branch. The stable branch 1.5634 + remains unaffected by these changes, since changes are only 1.5635 + flowing from the stable to the main branch, and not the other 1.5636 + way.</para> 1.5637 + </sect2> 1.5638 + 1.5639 + <sect2> 1.5640 + <title>Feature branches</title> 1.5641 + 1.5642 + <para id="x_469">For larger projects, an effective way to manage change is 1.5643 + to break up a team into smaller groups. Each group has a 1.5644 + shared branch of its own, cloned from a single 1.5645 + <quote>master</quote> branch used by the entire project. 1.5646 + People working on an individual branch are typically quite 1.5647 + isolated from developments on other branches.</para> 1.5648 + 1.5649 + <figure id="fig:collab:feature-branches" float="0"> 1.5650 + <title>Feature branches</title> 1.5651 + <mediaobject> 1.5652 + <imageobject><imagedata width="100%" fileref="figs/feature-branches.png"/></imageobject> 1.5653 + <textobject><phrase>XXX add text</phrase></textobject> 1.5654 + </mediaobject> 1.5655 + </figure> 1.5656 + 1.5657 + <para id="x_46b">When a particular feature is deemed to be in suitable 1.5658 + shape, someone on that feature team pulls and merges from the 1.5659 + master branch into the feature branch, then pushes back up to 1.5660 + the master branch.</para> 1.5661 + </sect2> 1.5662 + 1.5663 + <sect2> 1.5664 + <title>The release train</title> 1.5665 + 1.5666 + <para id="x_46c">Some projects are organized on a <quote>train</quote> 1.5667 + basis: a release is scheduled to happen every few months, and 1.5668 + whatever features are ready when the <quote>train</quote> is 1.5669 + ready to leave are allowed in.</para> 1.5670 + 1.5671 + <para id="x_46d">This model resembles working with feature branches. The 1.5672 + difference is that when a feature branch misses a train, 1.5673 + someone on the feature team pulls and merges the changes that 1.5674 + went out on that train release into the feature branch, and 1.5675 + the team continues its work on top of that release so that 1.5676 + their feature can make the next release.</para> 1.5677 + </sect2> 1.5678 + 1.5679 + <sect2> 1.5680 + <title>The Linux kernel model</title> 1.5681 + 1.5682 + <para id="x_46e">The development of the Linux kernel has a shallow 1.5683 + hierarchical structure, surrounded by a cloud of apparent 1.5684 + chaos. Because most Linux developers use 1.5685 + <command moreinfo="none">git</command>, a distributed revision control tool 1.5686 + with capabilities similar to Mercurial, it's useful to 1.5687 + describe the way work flows in that environment; if you like 1.5688 + the ideas, the approach translates well across tools.</para> 1.5689 + 1.5690 + <para id="x_46f">At the center of the community sits Linus Torvalds, the 1.5691 + creator of Linux. He publishes a single source repository 1.5692 + that is considered the <quote>authoritative</quote> current 1.5693 + tree by the entire developer community. Anyone can clone 1.5694 + Linus's tree, but he is very choosy about whose trees he pulls 1.5695 + from.</para> 1.5696 + 1.5697 + <para id="x_470">Linus has a number of <quote>trusted lieutenants</quote>. 1.5698 + As a general rule, he pulls whatever changes they publish, in 1.5699 + most cases without even reviewing those changes. Some of 1.5700 + those lieutenants are generally agreed to be 1.5701 + <quote>maintainers</quote>, responsible for specific 1.5702 + subsystems within the kernel. If a random kernel hacker wants 1.5703 + to make a change to a subsystem that they want to end up in 1.5704 + Linus's tree, they must find out who the subsystem's 1.5705 + maintainer is, and ask that maintainer to take their change. 1.5706 + If the maintainer reviews their changes and agrees to take 1.5707 + them, they'll pass them along to Linus in due course.</para> 1.5708 + 1.5709 + <para id="x_471">Individual lieutenants have their own approaches to 1.5710 + reviewing, accepting, and publishing changes; and for deciding 1.5711 + when to feed them to Linus. In addition, there are several 1.5712 + well known branches that people use for different purposes. 1.5713 + For example, a few people maintain <quote>stable</quote> 1.5714 + repositories of older versions of the kernel, to which they 1.5715 + apply critical fixes as needed. Some maintainers publish 1.5716 + multiple trees: one for experimental changes; one for changes 1.5717 + that they are about to feed upstream; and so on. Others just 1.5718 + publish a single tree.</para> 1.5719 + 1.5720 + <para id="x_472">This model has two notable features. The first is that 1.5721 + it's <quote>pull only</quote>. You have to ask, convince, or 1.5722 + beg another developer to take a change from you, because there 1.5723 + are almost no trees to which more than one person can push, 1.5724 + and there's no way to push changes into a tree that someone 1.5725 + else controls.</para> 1.5726 + 1.5727 + <para id="x_473">The second is that it's based on reputation and acclaim. 1.5728 + If you're an unknown, Linus will probably ignore changes from 1.5729 + you without even responding. But a subsystem maintainer will 1.5730 + probably review them, and will likely take them if they pass 1.5731 + their criteria for suitability. The more <quote>good</quote> 1.5732 + changes you contribute to a maintainer, the more likely they 1.5733 + are to trust your judgment and accept your changes. If you're 1.5734 + well-known and maintain a long-lived branch for something 1.5735 + Linus hasn't yet accepted, people with similar interests may 1.5736 + pull your changes regularly to keep up with your work.</para> 1.5737 + 1.5738 + <para id="x_474">Reputation and acclaim don't necessarily cross subsystem 1.5739 + or <quote>people</quote> boundaries. If you're a respected 1.5740 + but specialised storage hacker, and you try to fix a 1.5741 + networking bug, that change will receive a level of scrutiny 1.5742 + from a network maintainer comparable to a change from a 1.5743 + complete stranger.</para> 1.5744 + 1.5745 + <para id="x_475">To people who come from more orderly project backgrounds, 1.5746 + the comparatively chaotic Linux kernel development process 1.5747 + often seems completely insane. It's subject to the whims of 1.5748 + individuals; people make sweeping changes whenever they deem 1.5749 + it appropriate; and the pace of development is astounding. 1.5750 + And yet Linux is a highly successful, well-regarded piece of 1.5751 + software.</para> 1.5752 + </sect2> 1.5753 + 1.5754 + <sect2> 1.5755 + <title>Pull-only versus shared-push collaboration</title> 1.5756 + 1.5757 + <para id="x_476">A perpetual source of heat in the open source community is 1.5758 + whether a development model in which people only ever pull 1.5759 + changes from others is <quote>better than</quote> one in which 1.5760 + multiple people can push changes to a shared 1.5761 + repository.</para> 1.5762 + 1.5763 + <para id="x_477">Typically, the backers of the shared-push model use tools 1.5764 + that actively enforce this approach. If you're using a 1.5765 + centralised revision control tool such as Subversion, there's 1.5766 + no way to make a choice over which model you'll use: the tool 1.5767 + gives you shared-push, and if you want to do anything else, 1.5768 + you'll have to roll your own approach on top (such as applying 1.5769 + a patch by hand).</para> 1.5770 + 1.5771 + <para id="x_478">A good distributed revision control tool will 1.5772 + support both models. You and your collaborators can then 1.5773 + structure how you work together based on your own needs and 1.5774 + preferences, not on what contortions your tools force you 1.5775 + into.</para> 1.5776 + </sect2> 1.5777 + <sect2> 1.5778 + <title>Where collaboration meets branch management</title> 1.5779 + 1.5780 + <para id="x_479">Once you and your team set up some shared 1.5781 + repositories and start propagating changes back and forth 1.5782 + between local and shared repos, you begin to face a related, 1.5783 + but slightly different challenge: that of managing the 1.5784 + multiple directions in which your team may be moving at once. 1.5785 + Even though this subject is intimately related to how your 1.5786 + team collaborates, it's dense enough to merit treatment of its 1.5787 + own, in <xref linkend="chap:branch"/>.</para> 1.5788 + </sect2> 1.5789 + </sect1> 1.5790 + 1.5791 + <sect1> 1.5792 + <title>The technical side of sharing</title> 1.5793 + 1.5794 + <para id="x_47a">The remainder of this chapter is devoted to the question of 1.5795 + sharing changes with your collaborators.</para> 1.5796 + </sect1> 1.5797 + 1.5798 + <sect1 id="sec:collab:serve"> 1.5799 + <title>Informal sharing with <command role="hg-cmd" moreinfo="none">hg 1.5800 + serve</command></title> 1.5801 + 1.5802 + <para id="x_47b">Mercurial's <command role="hg-cmd" moreinfo="none">hg serve</command> 1.5803 + command is wonderfully suited to small, tight-knit, and 1.5804 + fast-paced group environments. It also provides a great way to 1.5805 + get a feel for using Mercurial commands over a network.</para> 1.5806 + 1.5807 + <para id="x_47c">Run <command role="hg-cmd" moreinfo="none">hg serve</command> inside a 1.5808 + repository, and in under a second it will bring up a specialised 1.5809 + HTTP server; this will accept connections from any client, and 1.5810 + serve up data for that repository until you terminate it. 1.5811 + Anyone who knows the URL of the server you just started, and can 1.5812 + talk to your computer over the network, can then use a web 1.5813 + browser or Mercurial to read data from that repository. A URL 1.5814 + for a <command role="hg-cmd" moreinfo="none">hg serve</command> instance running 1.5815 + on a laptop is likely to look something like 1.5816 + <literal moreinfo="none">http://my-laptop.local:8000/</literal>.</para> 1.5817 + 1.5818 + <para id="x_47d">The <command role="hg-cmd" moreinfo="none">hg serve</command> command is 1.5819 + <emphasis>not</emphasis> a general-purpose web server. It can do 1.5820 + only two things:</para> 1.5821 + <itemizedlist> 1.5822 + <listitem><para id="x_47e">Allow people to browse the history of the 1.5823 + repository it's serving, from their normal web 1.5824 + browsers.</para> 1.5825 + </listitem> 1.5826 + <listitem><para id="x_47f">Speak Mercurial's wire protocol, so that people 1.5827 + can <command role="hg-cmd" moreinfo="none">hg clone</command> or <command role="hg-cmd" moreinfo="none">hg pull</command> changes from that 1.5828 + repository.</para> 1.5829 + </listitem></itemizedlist> 1.5830 + <para id="x_480">In particular, <command role="hg-cmd" moreinfo="none">hg serve</command> 1.5831 + won't allow remote users to <emphasis>modify</emphasis> your 1.5832 + repository. It's intended for read-only use.</para> 1.5833 + 1.5834 + <para id="x_481">If you're getting started with Mercurial, there's nothing to 1.5835 + prevent you from using <command role="hg-cmd" moreinfo="none">hg serve</command> 1.5836 + to serve up a repository on your own computer, then use commands 1.5837 + 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 1.5838 + server as if the repository was hosted remotely. This can help 1.5839 + you to quickly get acquainted with using commands on 1.5840 + network-hosted repositories.</para> 1.5841 + 1.5842 + <sect2> 1.5843 + <title>A few things to keep in mind</title> 1.5844 + 1.5845 + <para id="x_482">Because it provides unauthenticated read access to all 1.5846 + clients, you should only use <command role="hg-cmd" moreinfo="none">hg 1.5847 + serve</command> in an environment where you either don't 1.5848 + care, or have complete control over, who can access your 1.5849 + network and pull data from your repository.</para> 1.5850 + 1.5851 + <para id="x_483">The <command role="hg-cmd" moreinfo="none">hg serve</command> command 1.5852 + knows nothing about any firewall software you might have 1.5853 + installed on your system or network. It cannot detect or 1.5854 + control your firewall software. If other people are unable to 1.5855 + talk to a running <command role="hg-cmd" moreinfo="none">hg serve</command> 1.5856 + instance, the second thing you should do 1.5857 + (<emphasis>after</emphasis> you make sure that they're using 1.5858 + the correct URL) is check your firewall configuration.</para> 1.5859 + 1.5860 + <para id="x_484">By default, <command role="hg-cmd" moreinfo="none">hg serve</command> 1.5861 + listens for incoming connections on port 8000. If another 1.5862 + process is already listening on the port you want to use, you 1.5863 + can specify a different port to listen on using the <option role="hg-opt-serve">-p</option> option.</para> 1.5864 + 1.5865 + <para id="x_485">Normally, when <command role="hg-cmd" moreinfo="none">hg serve</command> 1.5866 + starts, it prints no output, which can be a bit unnerving. If 1.5867 + you'd like to confirm that it is indeed running correctly, and 1.5868 + find out what URL you should send to your collaborators, start 1.5869 + it with the <option role="hg-opt-global">-v</option> 1.5870 + option.</para> 1.5871 + </sect2> 1.5872 + </sect1> 1.5873 + 1.5874 + <sect1 id="sec:collab:ssh"> 1.5875 + <title>Using the Secure Shell (ssh) protocol</title> 1.5876 + 1.5877 + <para id="x_486">You can pull and push changes securely over a network 1.5878 + connection using the Secure Shell (<literal moreinfo="none">ssh</literal>) 1.5879 + protocol. To use this successfully, you may have to do a little 1.5880 + bit of configuration on the client or server sides.</para> 1.5881 + 1.5882 + <para id="x_487">If you're not familiar with ssh, it's the name of 1.5883 + both a command and a network protocol that let you securely 1.5884 + communicate with another computer. To use it with Mercurial, 1.5885 + you'll be setting up one or more user accounts on a server so 1.5886 + that remote users can log in and execute commands.</para> 1.5887 + 1.5888 + <para id="x_488">(If you <emphasis>are</emphasis> familiar with ssh, you'll 1.5889 + probably find some of the material that follows to be elementary 1.5890 + in nature.)</para> 1.5891 + 1.5892 + <sect2> 1.5893 + <title>How to read and write ssh URLs</title> 1.5894 + 1.5895 + <para id="x_489">An ssh URL tends to look like this:</para> 1.5896 + <programlisting format="linespecific">ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting> 1.5897 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.5898 + <listitem><para id="x_48a">The <quote><literal moreinfo="none">ssh://</literal></quote> 1.5899 + part tells Mercurial to use the ssh protocol.</para> 1.5900 + </listitem> 1.5901 + <listitem><para id="x_48b">The <quote><literal moreinfo="none">bos@</literal></quote> 1.5902 + component indicates what username to log into the server 1.5903 + as. You can leave this out if the remote username is the 1.5904 + same as your local username.</para> 1.5905 + </listitem> 1.5906 + <listitem><para id="x_48c">The 1.5907 + <quote><literal moreinfo="none">hg.serpentine.com</literal></quote> gives 1.5908 + the hostname of the server to log into.</para> 1.5909 + </listitem> 1.5910 + <listitem><para id="x_48d">The <quote>:22</quote> identifies the port 1.5911 + number to connect to the server on. The default port is 1.5912 + 22, so you only need to specify a colon and port number if 1.5913 + you're <emphasis>not</emphasis> using port 22.</para> 1.5914 + </listitem> 1.5915 + <listitem><para id="x_48e">The remainder of the URL is the local path to 1.5916 + the repository on the server.</para> 1.5917 + </listitem></orderedlist> 1.5918 + 1.5919 + <para id="x_48f">There's plenty of scope for confusion with the path 1.5920 + component of ssh URLs, as there is no standard way for tools 1.5921 + to interpret it. Some programs behave differently than others 1.5922 + when dealing with these paths. This isn't an ideal situation, 1.5923 + but it's unlikely to change. Please read the following 1.5924 + paragraphs carefully.</para> 1.5925 + 1.5926 + <para id="x_490">Mercurial treats the path to a repository on the server as 1.5927 + relative to the remote user's home directory. For example, if 1.5928 + user <literal moreinfo="none">foo</literal> on the server has a home directory 1.5929 + of <filename class="directory" moreinfo="none">/home/foo</filename>, then an 1.5930 + ssh URL that contains a path component of <filename class="directory" moreinfo="none">bar</filename> <emphasis>really</emphasis> 1.5931 + refers to the directory <filename class="directory" moreinfo="none">/home/foo/bar</filename>.</para> 1.5932 + 1.5933 + <para id="x_491">If you want to specify a path relative to another user's 1.5934 + home directory, you can use a path that starts with a tilde 1.5935 + character followed by the user's name (let's call them 1.5936 + <literal moreinfo="none">otheruser</literal>), like this.</para> 1.5937 + <programlisting format="linespecific">ssh://server/~otheruser/hg/repo</programlisting> 1.5938 + 1.5939 + <para id="x_492">And if you really want to specify an 1.5940 + <emphasis>absolute</emphasis> path on the server, begin the 1.5941 + path component with two slashes, as in this example.</para> 1.5942 + <programlisting format="linespecific">ssh://server//absolute/path</programlisting> 1.5943 + </sect2> 1.5944 + 1.5945 + <sect2> 1.5946 + <title>Finding an ssh client for your system</title> 1.5947 + 1.5948 + <para id="x_493">Almost every Unix-like system comes with OpenSSH 1.5949 + preinstalled. If you're using such a system, run 1.5950 + <literal moreinfo="none">which ssh</literal> to find out if the 1.5951 + <command moreinfo="none">ssh</command> command is installed (it's usually in 1.5952 + <filename class="directory" moreinfo="none">/usr/bin</filename>). In the 1.5953 + unlikely event that it isn't present, take a look at your 1.5954 + system documentation to figure out how to install it.</para> 1.5955 + 1.5956 + <para id="x_494">On Windows, the TortoiseHg package is bundled 1.5957 + with a version of Simon Tatham's excellent 1.5958 + <command moreinfo="none">plink</command> command, and you should not need to 1.5959 + do any further configuration.</para> 1.5960 + </sect2> 1.5961 + 1.5962 + <sect2> 1.5963 + <title>Generating a key pair</title> 1.5964 + 1.5965 + <para id="x_499">To avoid the need to repetitively type a 1.5966 + password every time you need to use your ssh client, I 1.5967 + recommend generating a key pair.</para> 1.5968 + 1.5969 + <tip> 1.5970 + <title>Key pairs are not mandatory</title> 1.5971 + 1.5972 + <para id="x_6a4">Mercurial knows nothing about ssh authentication or key 1.5973 + pairs. You can, if you like, safely ignore this section and 1.5974 + the one that follows until you grow tired of repeatedly 1.5975 + typing ssh passwords.</para> 1.5976 + </tip> 1.5977 + 1.5978 + <itemizedlist> 1.5979 + <listitem> 1.5980 + <para id="x_6a5">On a Unix-like system, the 1.5981 + <command moreinfo="none">ssh-keygen</command> command will do the 1.5982 + trick.</para> 1.5983 + <para id="x_6a6">On Windows, if you're using TortoiseHg, you may need 1.5984 + to download a command named <command moreinfo="none">puttygen</command> 1.5985 + from <ulink url="http://www.chiark.greenend.org.uk/~sgtatham/putty">the 1.5986 + PuTTY web site</ulink> to generate a key pair. See 1.5987 + <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen">the 1.5988 + <command moreinfo="none">puttygen</command> documentation</ulink> for 1.5989 + details of how use the command.</para> 1.5990 + </listitem> 1.5991 + </itemizedlist> 1.5992 + 1.5993 + <para id="x_49a">When you generate a key pair, it's usually 1.5994 + <emphasis>highly</emphasis> advisable to protect it with a 1.5995 + passphrase. (The only time that you might not want to do this 1.5996 + is when you're using the ssh protocol for automated tasks on a 1.5997 + secure network.)</para> 1.5998 + 1.5999 + <para id="x_49b">Simply generating a key pair isn't enough, however. 1.6000 + You'll need to add the public key to the set of authorised 1.6001 + keys for whatever user you're logging in remotely as. For 1.6002 + servers using OpenSSH (the vast majority), this will mean 1.6003 + 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> 1.6004 + directory.</para> 1.6005 + 1.6006 + <para id="x_49c">On a Unix-like system, your public key will have a 1.6007 + <filename moreinfo="none">.pub</filename> extension. If you're using 1.6008 + <command moreinfo="none">puttygen</command> on Windows, you can save the 1.6009 + public key to a file of your choosing, or paste it from the 1.6010 + window it's displayed in straight into the <filename role="special" moreinfo="none">authorized_keys</filename> file.</para> 1.6011 + </sect2> 1.6012 + <sect2> 1.6013 + <title>Using an authentication agent</title> 1.6014 + 1.6015 + <para id="x_49d">An authentication agent is a daemon that stores 1.6016 + passphrases in memory (so it will forget passphrases if you 1.6017 + log out and log back in again). An ssh client will notice if 1.6018 + it's running, and query it for a passphrase. If there's no 1.6019 + authentication agent running, or the agent doesn't store the 1.6020 + necessary passphrase, you'll have to type your passphrase 1.6021 + every time Mercurial tries to communicate with a server on 1.6022 + your behalf (e.g. whenever you pull or push changes).</para> 1.6023 + 1.6024 + <para id="x_49e">The downside of storing passphrases in an agent is that 1.6025 + it's possible for a well-prepared attacker to recover the 1.6026 + plain text of your passphrases, in some cases even if your 1.6027 + system has been power-cycled. You should make your own 1.6028 + judgment as to whether this is an acceptable risk. It 1.6029 + certainly saves a lot of repeated typing.</para> 1.6030 + 1.6031 + <itemizedlist> 1.6032 + <listitem> 1.6033 + <para id="x_49f">On Unix-like systems, the agent is called 1.6034 + <command moreinfo="none">ssh-agent</command>, and it's often run 1.6035 + automatically for you when you log in. You'll need to use 1.6036 + the <command moreinfo="none">ssh-add</command> command to add passphrases 1.6037 + to the agent's store.</para> 1.6038 + </listitem> 1.6039 + <listitem> 1.6040 + <para id="x_6a7">On Windows, if you're using TortoiseHg, the 1.6041 + <command moreinfo="none">pageant</command> command acts as the agent. As 1.6042 + with <command moreinfo="none">puttygen</command>, you'll need to <ulink url="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html">download 1.6043 + <command moreinfo="none">pageant</command></ulink> from the PuTTY web 1.6044 + site and read <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">its 1.6045 + documentation</ulink>. The <command moreinfo="none">pageant</command> 1.6046 + command adds an icon to your system tray that will let you 1.6047 + manage stored passphrases.</para> 1.6048 + </listitem> 1.6049 + </itemizedlist> 1.6050 + </sect2> 1.6051 + 1.6052 + <sect2> 1.6053 + <title>Configuring the server side properly</title> 1.6054 + 1.6055 + <para id="x_4a0">Because ssh can be fiddly to set up if you're new to it, 1.6056 + a variety of things can go wrong. Add Mercurial 1.6057 + on top, and there's plenty more scope for head-scratching. 1.6058 + Most of these potential problems occur on the server side, not 1.6059 + the client side. The good news is that once you've gotten a 1.6060 + configuration working, it will usually continue to work 1.6061 + indefinitely.</para> 1.6062 + 1.6063 + <para id="x_4a1">Before you try using Mercurial to talk to an ssh server, 1.6064 + it's best to make sure that you can use the normal 1.6065 + <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command> command to 1.6066 + talk to the server first. If you run into problems with using 1.6067 + these commands directly, Mercurial surely won't work. Worse, 1.6068 + it will obscure the underlying problem. Any time you want to 1.6069 + debug ssh-related Mercurial problems, you should drop back to 1.6070 + making sure that plain ssh client commands work first, 1.6071 + <emphasis>before</emphasis> you worry about whether there's a 1.6072 + problem with Mercurial.</para> 1.6073 + 1.6074 + <para id="x_4a2">The first thing to be sure of on the server side is that 1.6075 + you can actually log in from another machine at all. If you 1.6076 + can't use <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command> 1.6077 + to log in, the error message you get may give you a few hints 1.6078 + as to what's wrong. The most common problems are as 1.6079 + follows.</para> 1.6080 + <itemizedlist> 1.6081 + <listitem><para id="x_4a3">If you get a <quote>connection refused</quote> 1.6082 + error, either there isn't an SSH daemon running on the 1.6083 + server at all, or it's inaccessible due to firewall 1.6084 + configuration.</para> 1.6085 + </listitem> 1.6086 + <listitem><para id="x_4a4">If you get a <quote>no route to host</quote> 1.6087 + error, you either have an incorrect address for the server 1.6088 + or a seriously locked down firewall that won't admit its 1.6089 + existence at all.</para> 1.6090 + </listitem> 1.6091 + <listitem><para id="x_4a5">If you get a <quote>permission denied</quote> 1.6092 + error, you may have mistyped the username on the server, 1.6093 + or you could have mistyped your key's passphrase or the 1.6094 + remote user's password.</para> 1.6095 + </listitem></itemizedlist> 1.6096 + <para id="x_4a6">In summary, if you're having trouble talking to the 1.6097 + server's ssh daemon, first make sure that one is running at 1.6098 + all. On many systems it will be installed, but disabled, by 1.6099 + default. Once you're done with this step, you should then 1.6100 + check that the server's firewall is configured to allow 1.6101 + incoming connections on the port the ssh daemon is listening 1.6102 + on (usually 22). Don't worry about more exotic possibilities 1.6103 + for misconfiguration until you've checked these two 1.6104 + first.</para> 1.6105 + 1.6106 + <para id="x_4a7">If you're using an authentication agent on the client side 1.6107 + to store passphrases for your keys, you ought to be able to 1.6108 + log into the server without being prompted for a passphrase or 1.6109 + a password. If you're prompted for a passphrase, there are a 1.6110 + few possible culprits.</para> 1.6111 + <itemizedlist> 1.6112 + <listitem><para id="x_4a8">You might have forgotten to use 1.6113 + <command moreinfo="none">ssh-add</command> or <command moreinfo="none">pageant</command> 1.6114 + to store the passphrase.</para> 1.6115 + </listitem> 1.6116 + <listitem><para id="x_4a9">You might have stored the passphrase for the 1.6117 + wrong key.</para> 1.6118 + </listitem></itemizedlist> 1.6119 + <para id="x_4aa">If you're being prompted for the remote user's password, 1.6120 + there are another few possible problems to check.</para> 1.6121 + <itemizedlist> 1.6122 + <listitem><para id="x_4ab">Either the user's home directory or their 1.6123 + <filename role="special" class="directory" moreinfo="none">.ssh</filename> 1.6124 + directory might have excessively liberal permissions. As 1.6125 + a result, the ssh daemon will not trust or read their 1.6126 + <filename role="special" moreinfo="none">authorized_keys</filename> file. 1.6127 + For example, a group-writable home or <filename role="special" class="directory" moreinfo="none">.ssh</filename> 1.6128 + directory will often cause this symptom.</para> 1.6129 + </listitem> 1.6130 + <listitem><para id="x_4ac">The user's <filename role="special" moreinfo="none">authorized_keys</filename> file may have 1.6131 + a problem. If anyone other than the user owns or can write 1.6132 + to that file, the ssh daemon will not trust or read 1.6133 + it.</para> 1.6134 + </listitem></itemizedlist> 1.6135 + 1.6136 + <para id="x_4ad">In the ideal world, you should be able to run the 1.6137 + following command successfully, and it should print exactly 1.6138 + one line of output, the current date and time.</para> 1.6139 + <programlisting format="linespecific">ssh myserver date</programlisting> 1.6140 + 1.6141 + <para id="x_4ae">If, on your server, you have login scripts that print 1.6142 + banners or other junk even when running non-interactive 1.6143 + commands like this, you should fix them before you continue, 1.6144 + so that they only print output if they're run interactively. 1.6145 + Otherwise these banners will at least clutter up Mercurial's 1.6146 + output. Worse, they could potentially cause problems with 1.6147 + running Mercurial commands remotely. Mercurial tries to 1.6148 + detect and ignore banners in non-interactive 1.6149 + <command moreinfo="none">ssh</command> sessions, but it is not foolproof. (If 1.6150 + you're editing your login scripts on your server, the usual 1.6151 + way to see if a login script is running in an interactive 1.6152 + shell is to check the return code from the command 1.6153 + <literal moreinfo="none">tty -s</literal>.)</para> 1.6154 + 1.6155 + <para id="x_4af">Once you've verified that plain old ssh is working with 1.6156 + your server, the next step is to ensure that Mercurial runs on 1.6157 + the server. The following command should run 1.6158 + successfully:</para> 1.6159 + 1.6160 + <programlisting format="linespecific">ssh myserver hg version</programlisting> 1.6161 + 1.6162 + <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 1.6163 + because you haven't installed Mercurial to <filename class="directory" moreinfo="none">/usr/bin</filename>. Don't worry if this 1.6164 + is the case; you don't need to do that. But you should check 1.6165 + for a few possible problems.</para> 1.6166 + <itemizedlist> 1.6167 + <listitem><para id="x_4b1">Is Mercurial really installed on the server at 1.6168 + all? I know this sounds trivial, but it's worth 1.6169 + checking!</para> 1.6170 + </listitem> 1.6171 + <listitem><para id="x_4b2">Maybe your shell's search path (usually set 1.6172 + via the <envar>PATH</envar> environment variable) is 1.6173 + simply misconfigured.</para> 1.6174 + </listitem> 1.6175 + <listitem><para id="x_4b3">Perhaps your <envar>PATH</envar> environment 1.6176 + variable is only being set to point to the location of the 1.6177 + <command moreinfo="none">hg</command> executable if the login session is 1.6178 + interactive. This can happen if you're setting the path 1.6179 + in the wrong shell login script. See your shell's 1.6180 + documentation for details.</para> 1.6181 + </listitem> 1.6182 + <listitem><para id="x_4b4">The <envar>PYTHONPATH</envar> environment 1.6183 + variable may need to contain the path to the Mercurial 1.6184 + Python modules. It might not be set at all; it could be 1.6185 + incorrect; or it may be set only if the login is 1.6186 + interactive.</para> 1.6187 + </listitem></itemizedlist> 1.6188 + 1.6189 + <para id="x_4b5">If you can run <command role="hg-cmd" moreinfo="none">hg version</command> 1.6190 + over an ssh connection, well done! You've got the server and 1.6191 + client sorted out. You should now be able to use Mercurial to 1.6192 + access repositories hosted by that username on that server. 1.6193 + If you run into problems with Mercurial and ssh at this point, 1.6194 + try using the <option role="hg-opt-global">--debug</option> 1.6195 + option to get a clearer picture of what's going on.</para> 1.6196 + </sect2> 1.6197 + <sect2> 1.6198 + <title>Using compression with ssh</title> 1.6199 + 1.6200 + <para id="x_4b6">Mercurial does not compress data when it uses the ssh 1.6201 + protocol, because the ssh protocol can transparently compress 1.6202 + data. However, the default behavior of ssh clients is 1.6203 + <emphasis>not</emphasis> to request compression.</para> 1.6204 + 1.6205 + <para id="x_4b7">Over any network other than a fast LAN (even a wireless 1.6206 + network), using compression is likely to significantly speed 1.6207 + up Mercurial's network operations. For example, over a WAN, 1.6208 + someone measured compression as reducing the amount of time 1.6209 + required to clone a particularly large repository from 51 1.6210 + minutes to 17 minutes.</para> 1.6211 + 1.6212 + <para id="x_4b8">Both <command moreinfo="none">ssh</command> and <command moreinfo="none">plink</command> 1.6213 + accept a <option role="cmd-opt-ssh">-C</option> option which 1.6214 + turns on compression. You can easily edit your <filename role="special" moreinfo="none">~/.hgrc</filename> to enable compression for 1.6215 + all of Mercurial's uses of the ssh protocol. Here is how to 1.6216 + do so for regular <command moreinfo="none">ssh</command> on Unix-like systems, 1.6217 + for example.</para> 1.6218 + <programlisting format="linespecific">[ui] 1.6219 +ssh = ssh -C</programlisting> 1.6220 + 1.6221 + <para id="x_4b9">If you use <command moreinfo="none">ssh</command> on a 1.6222 + Unix-like system, you can configure it to always use 1.6223 + compression when talking to your server. To do this, edit 1.6224 + your <filename role="special" moreinfo="none">.ssh/config</filename> file 1.6225 + (which may not yet exist), as follows.</para> 1.6226 + 1.6227 + <programlisting format="linespecific">Host hg 1.6228 + Compression yes 1.6229 + HostName hg.example.com</programlisting> 1.6230 + 1.6231 + <para id="x_4ba">This defines a hostname alias, 1.6232 + <literal moreinfo="none">hg</literal>. When you use that hostname on the 1.6233 + <command moreinfo="none">ssh</command> command line or in a Mercurial 1.6234 + <literal moreinfo="none">ssh</literal>-protocol URL, it will cause 1.6235 + <command moreinfo="none">ssh</command> to connect to 1.6236 + <literal moreinfo="none">hg.example.com</literal> and use compression. This 1.6237 + gives you both a shorter name to type and compression, each of 1.6238 + which is a good thing in its own right.</para> 1.6239 + </sect2> 1.6240 + </sect1> 1.6241 + 1.6242 + <sect1 id="sec:collab:cgi"> 1.6243 + <title>Serving over HTTP using CGI</title> 1.6244 + 1.6245 + <para id="x_6a8">The simplest way to host one or more repositories in a 1.6246 + permanent way is to use a web server and Mercurial's CGI 1.6247 + support.</para> 1.6248 + 1.6249 + <para id="x_4bb">Depending on how ambitious you are, configuring Mercurial's 1.6250 + CGI interface can take anything from a few moments to several 1.6251 + hours.</para> 1.6252 + 1.6253 + <para id="x_4bc">We'll begin with the simplest of examples, and work our way 1.6254 + towards a more complex configuration. Even for the most basic 1.6255 + case, you're almost certainly going to need to read and modify 1.6256 + your web server's configuration.</para> 1.6257 + 1.6258 + <note> 1.6259 + <title>High pain tolerance required</title> 1.6260 + 1.6261 + <para id="x_4bd">Configuring a web server is a complex, fiddly, 1.6262 + and highly system-dependent activity. I can't possibly give 1.6263 + you instructions that will cover anything like all of the 1.6264 + cases you will encounter. Please use your discretion and 1.6265 + judgment in following the sections below. Be prepared to make 1.6266 + plenty of mistakes, and to spend a lot of time reading your 1.6267 + server's error logs.</para> 1.6268 + 1.6269 + <para id="x_6a9">If you don't have a strong stomach for tweaking 1.6270 + configurations over and over, or a compelling need to host 1.6271 + your own services, you might want to try one of the public 1.6272 + hosting services that I mentioned earlier.</para> 1.6273 + </note> 1.6274 + 1.6275 + <sect2> 1.6276 + <title>Web server configuration checklist</title> 1.6277 + 1.6278 + <para id="x_4be">Before you continue, do take a few moments to check a few 1.6279 + aspects of your system's setup.</para> 1.6280 + 1.6281 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.6282 + <listitem><para id="x_4bf">Do you have a web server installed 1.6283 + at all? Mac OS X and some Linux distributions ship with 1.6284 + Apache, but many other systems may not have a web server 1.6285 + installed.</para> 1.6286 + </listitem> 1.6287 + <listitem><para id="x_4c0">If you have a web server installed, is it 1.6288 + actually running? On most systems, even if one is 1.6289 + present, it will be disabled by default.</para> 1.6290 + </listitem> 1.6291 + <listitem><para id="x_4c1">Is your server configured to allow you to run 1.6292 + CGI programs in the directory where you plan to do so? 1.6293 + Most servers default to explicitly disabling the ability 1.6294 + to run CGI programs.</para> 1.6295 + </listitem></orderedlist> 1.6296 + 1.6297 + <para id="x_4c2">If you don't have a web server installed, and don't have 1.6298 + substantial experience configuring Apache, you should consider 1.6299 + using the <literal moreinfo="none">lighttpd</literal> web server instead of 1.6300 + Apache. Apache has a well-deserved reputation for baroque and 1.6301 + confusing configuration. While <literal moreinfo="none">lighttpd</literal> is 1.6302 + less capable in some ways than Apache, most of these 1.6303 + capabilities are not relevant to serving Mercurial 1.6304 + repositories. And <literal moreinfo="none">lighttpd</literal> is undeniably 1.6305 + <emphasis>much</emphasis> easier to get started with than 1.6306 + Apache.</para> 1.6307 + </sect2> 1.6308 + 1.6309 + <sect2> 1.6310 + <title>Basic CGI configuration</title> 1.6311 + 1.6312 + <para id="x_4c3">On Unix-like systems, it's common for users to have a 1.6313 + subdirectory named something like <filename class="directory" moreinfo="none">public_html</filename> in their home 1.6314 + directory, from which they can serve up web pages. A file 1.6315 + named <filename moreinfo="none">foo</filename> in this directory will be 1.6316 + accessible at a URL of the form 1.6317 + <literal moreinfo="none">http://www.example.com/username/foo</literal>.</para> 1.6318 + 1.6319 + <para id="x_4c4">To get started, find the <filename role="special" moreinfo="none">hgweb.cgi</filename> script that should be 1.6320 + present in your Mercurial installation. If you can't quickly 1.6321 + find a local copy on your system, simply download one from the 1.6322 + 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> 1.6323 + 1.6324 + <para id="x_4c5">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and 1.6325 + ensure that it's executable.</para> 1.6326 + <programlisting format="linespecific">cp .../hgweb.cgi ~/public_html 1.6327 +chmod 755 ~/public_html/hgweb.cgi</programlisting> 1.6328 + <para id="x_4c6">The <literal moreinfo="none">755</literal> argument to 1.6329 + <command moreinfo="none">chmod</command> is a little more general than just 1.6330 + making the script executable: it ensures that the script is 1.6331 + executable by anyone, and that <quote>group</quote> and 1.6332 + <quote>other</quote> write permissions are 1.6333 + <emphasis>not</emphasis> set. If you were to leave those 1.6334 + write permissions enabled, Apache's <literal moreinfo="none">suexec</literal> 1.6335 + subsystem would likely refuse to execute the script. In fact, 1.6336 + <literal moreinfo="none">suexec</literal> also insists that the 1.6337 + <emphasis>directory</emphasis> in which the script resides 1.6338 + must not be writable by others.</para> 1.6339 + <programlisting format="linespecific">chmod 755 ~/public_html</programlisting> 1.6340 + 1.6341 + <sect3 id="sec:collab:wtf"> 1.6342 + <title>What could <emphasis>possibly</emphasis> go 1.6343 + wrong?</title> 1.6344 + 1.6345 + <para id="x_4c7">Once you've copied the CGI script into place, 1.6346 + go into a web browser, and try to open the URL 1.6347 + <literal moreinfo="none">http://myhostname/~myuser/hgweb.cgi</literal>, 1.6348 + <emphasis>but</emphasis> brace yourself for instant failure. 1.6349 + There's a high probability that trying to visit this URL 1.6350 + will fail, and there are many possible reasons for this. In 1.6351 + fact, you're likely to stumble over almost every one of the 1.6352 + possible errors below, so please read carefully. The 1.6353 + following are all of the problems I ran into on a system 1.6354 + running Fedora 7, with a fresh installation of Apache, and a 1.6355 + user account that I created specially to perform this 1.6356 + exercise.</para> 1.6357 + 1.6358 + <para id="x_4c8">Your web server may have per-user directories disabled. 1.6359 + If you're using Apache, search your config file for a 1.6360 + <literal moreinfo="none">UserDir</literal> directive. If there's none 1.6361 + present, per-user directories will be disabled. If one 1.6362 + exists, but its value is <literal moreinfo="none">disabled</literal>, then 1.6363 + per-user directories will be disabled. Otherwise, the 1.6364 + string after <literal moreinfo="none">UserDir</literal> gives the name of 1.6365 + the subdirectory that Apache will look in under your home 1.6366 + directory, for example <filename class="directory" moreinfo="none">public_html</filename>.</para> 1.6367 + 1.6368 + <para id="x_4c9">Your file access permissions may be too restrictive. 1.6369 + The web server must be able to traverse your home directory 1.6370 + and directories under your <filename class="directory" moreinfo="none">public_html</filename> directory, and 1.6371 + read files under the latter too. Here's a quick recipe to 1.6372 + help you to make your permissions more appropriate.</para> 1.6373 + <programlisting format="linespecific">chmod 755 ~ 1.6374 +find ~/public_html -type d -print0 | xargs -0r chmod 755 1.6375 +find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting> 1.6376 + 1.6377 + <para id="x_4ca">The other possibility with permissions is that you might 1.6378 + get a completely empty window when you try to load the 1.6379 + script. In this case, it's likely that your access 1.6380 + permissions are <emphasis>too permissive</emphasis>. Apache's 1.6381 + <literal moreinfo="none">suexec</literal> subsystem won't execute a script 1.6382 + that's group- or world-writable, for example.</para> 1.6383 + 1.6384 + <para id="x_4cb">Your web server may be configured to disallow execution 1.6385 + of CGI programs in your per-user web directory. Here's 1.6386 + Apache's default per-user configuration from my Fedora 1.6387 + system.</para> 1.6388 + 1.6389 + <!-- BEGIN ch06/apache-config.lst --> 1.6390 +<programlisting format="linespecific"><Directory /home/*/public_html> 1.6391 + AllowOverride FileInfo AuthConfig Limit 1.6392 + Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec 1.6393 + <Limit GET POST OPTIONS> 1.6394 + Order allow,deny 1.6395 + Allow from all 1.6396 + </Limit> 1.6397 + <LimitExcept GET POST OPTIONS> 1.6398 + Order deny,allow Deny from all 1.6399 + </LimitExcept> 1.6400 +</Directory></programlisting> 1.6401 +<!-- END ch06/apache-config.lst --> 1.6402 + 1.6403 + 1.6404 + <para id="x_4cc">If you find a similar-looking 1.6405 + <literal moreinfo="none">Directory</literal> group in your Apache 1.6406 + configuration, the directive to look at inside it is 1.6407 + <literal moreinfo="none">Options</literal>. Add <literal moreinfo="none">ExecCGI</literal> 1.6408 + to the end of this list if it's missing, and restart the web 1.6409 + server.</para> 1.6410 + 1.6411 + <para id="x_4cd">If you find that Apache serves you the text of the CGI 1.6412 + script instead of executing it, you may need to either 1.6413 + uncomment (if already present) or add a directive like 1.6414 + this.</para> 1.6415 + <programlisting format="linespecific">AddHandler cgi-script .cgi</programlisting> 1.6416 + 1.6417 + <para id="x_4ce">The next possibility is that you might be served with a 1.6418 + colourful Python backtrace claiming that it can't import a 1.6419 + <literal moreinfo="none">mercurial</literal>-related module. This is 1.6420 + actually progress! The server is now capable of executing 1.6421 + your CGI script. This error is only likely to occur if 1.6422 + you're running a private installation of Mercurial, instead 1.6423 + of a system-wide version. Remember that the web server runs 1.6424 + the CGI program without any of the environment variables 1.6425 + that you take for granted in an interactive session. If 1.6426 + this error happens to you, edit your copy of <filename role="special" moreinfo="none">hgweb.cgi</filename> and follow the 1.6427 + directions inside it to correctly set your 1.6428 + <envar>PYTHONPATH</envar> environment variable.</para> 1.6429 + 1.6430 + <para id="x_4cf">Finally, you are <emphasis>certain</emphasis> to be 1.6431 + served with another colourful Python backtrace: this one 1.6432 + will complain that it can't find <filename class="directory" moreinfo="none">/path/to/repository</filename>. Edit 1.6433 + your <filename role="special" moreinfo="none">hgweb.cgi</filename> script 1.6434 + and replace the <filename class="directory" moreinfo="none">/path/to/repository</filename> string 1.6435 + with the complete path to the repository you want to serve 1.6436 + up.</para> 1.6437 + 1.6438 + <para id="x_4d0">At this point, when you try to reload the page, you 1.6439 + should be presented with a nice HTML view of your 1.6440 + repository's history. Whew!</para> 1.6441 + </sect3> 1.6442 + 1.6443 + <sect3> 1.6444 + <title>Configuring lighttpd</title> 1.6445 + 1.6446 + <para id="x_4d1">To be exhaustive in my experiments, I tried configuring 1.6447 + the increasingly popular <literal moreinfo="none">lighttpd</literal> web 1.6448 + server to serve the same repository as I described with 1.6449 + Apache above. I had already overcome all of the problems I 1.6450 + outlined with Apache, many of which are not server-specific. 1.6451 + As a result, I was fairly sure that my file and directory 1.6452 + permissions were good, and that my <filename role="special" moreinfo="none">hgweb.cgi</filename> script was properly 1.6453 + edited.</para> 1.6454 + 1.6455 + <para id="x_4d2">Once I had Apache running, getting 1.6456 + <literal moreinfo="none">lighttpd</literal> to serve the repository was a 1.6457 + snap (in other words, even if you're trying to use 1.6458 + <literal moreinfo="none">lighttpd</literal>, you should read the Apache 1.6459 + section). I first had to edit the 1.6460 + <literal moreinfo="none">mod_access</literal> section of its config file to 1.6461 + enable <literal moreinfo="none">mod_cgi</literal> and 1.6462 + <literal moreinfo="none">mod_userdir</literal>, both of which were disabled 1.6463 + by default on my system. I then added a few lines to the 1.6464 + end of the config file, to configure these modules.</para> 1.6465 + <programlisting format="linespecific">userdir.path = "public_html" 1.6466 +cgi.assign = (".cgi" => "" )</programlisting> 1.6467 + <para id="x_4d3">With this done, <literal moreinfo="none">lighttpd</literal> ran 1.6468 + immediately for me. If I had configured 1.6469 + <literal moreinfo="none">lighttpd</literal> before Apache, I'd almost 1.6470 + certainly have run into many of the same system-level 1.6471 + configuration problems as I did with Apache. However, I 1.6472 + found <literal moreinfo="none">lighttpd</literal> to be noticeably easier to 1.6473 + configure than Apache, even though I've used Apache for over 1.6474 + a decade, and this was my first exposure to 1.6475 + <literal moreinfo="none">lighttpd</literal>.</para> 1.6476 + </sect3> 1.6477 + </sect2> 1.6478 + 1.6479 + <sect2> 1.6480 + <title>Sharing multiple repositories with one CGI script</title> 1.6481 + 1.6482 + <para id="x_4d4">The <filename role="special" moreinfo="none">hgweb.cgi</filename> script 1.6483 + only lets you publish a single repository, which is an 1.6484 + annoying restriction. If you want to publish more than one 1.6485 + without wracking yourself with multiple copies of the same 1.6486 + script, each with different names, a better choice is to use 1.6487 + the <filename role="special" moreinfo="none">hgwebdir.cgi</filename> 1.6488 + script.</para> 1.6489 + 1.6490 + <para id="x_4d5">The procedure to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is only a little more 1.6491 + involved than for <filename role="special" moreinfo="none">hgweb.cgi</filename>. First, you must obtain 1.6492 + a copy of the script. If you don't have one handy, you can 1.6493 + 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> 1.6494 + 1.6495 + <para id="x_4d6">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and 1.6496 + ensure that it's executable.</para> 1.6497 + 1.6498 + <programlisting format="linespecific">cp .../hgwebdir.cgi ~/public_html 1.6499 +chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting> 1.6500 + 1.6501 + <para id="x_4d7">With basic configuration out of the way, try to 1.6502 + visit <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal> 1.6503 + in your browser. It should 1.6504 + display an empty list of repositories. If you get a blank 1.6505 + window or error message, try walking through the list of 1.6506 + potential problems in <xref linkend="sec:collab:wtf"/>.</para> 1.6507 + 1.6508 + <para id="x_4d8">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename> 1.6509 + script relies on an external configuration file. By default, 1.6510 + it searches for a file named <filename role="special" moreinfo="none">hgweb.config</filename> in the same directory 1.6511 + as itself. You'll need to create this file, and make it 1.6512 + world-readable. The format of the file is similar to a 1.6513 + Windows <quote>ini</quote> file, as understood by Python's 1.6514 + <literal moreinfo="none">ConfigParser</literal> 1.6515 + <citation>web:configparser</citation> module.</para> 1.6516 + 1.6517 + <para id="x_4d9">The easiest way to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is with a section 1.6518 + named <literal moreinfo="none">collections</literal>. This will automatically 1.6519 + publish <emphasis>every</emphasis> repository under the 1.6520 + directories you name. The section should look like 1.6521 + this:</para> 1.6522 + <programlisting format="linespecific">[collections] 1.6523 +/my/root = /my/root</programlisting> 1.6524 + <para id="x_4da">Mercurial interprets this by looking at the directory name 1.6525 + on the <emphasis>right</emphasis> hand side of the 1.6526 + <quote><literal moreinfo="none">=</literal></quote> sign; finding repositories 1.6527 + in that directory hierarchy; and using the text on the 1.6528 + <emphasis>left</emphasis> to strip off matching text from the 1.6529 + names it will actually list in the web interface. The 1.6530 + remaining component of a path after this stripping has 1.6531 + occurred is called a <quote>virtual path</quote>.</para> 1.6532 + 1.6533 + <para id="x_4db">Given the example above, if we have a 1.6534 + repository whose local path is <filename class="directory" moreinfo="none">/my/root/this/repo</filename>, the CGI 1.6535 + script will strip the leading <filename class="directory" moreinfo="none">/my/root</filename> from the name, and 1.6536 + publish the repository with a virtual path of <filename class="directory" moreinfo="none">this/repo</filename>. If the base URL for 1.6537 + our CGI script is 1.6538 + <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal>, the 1.6539 + complete URL for that repository will be 1.6540 + <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi/this/repo</literal>.</para> 1.6541 + 1.6542 + <para id="x_4dc">If we replace <filename class="directory" moreinfo="none">/my/root</filename> on the left hand side 1.6543 + of this example with <filename class="directory" moreinfo="none">/my</filename>, then <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will only strip off 1.6544 + <filename class="directory" moreinfo="none">/my</filename> from the repository 1.6545 + name, and will give us a virtual path of <filename class="directory" moreinfo="none">root/this/repo</filename> instead of 1.6546 + <filename class="directory" moreinfo="none">this/repo</filename>.</para> 1.6547 + 1.6548 + <para id="x_4dd">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename> 1.6549 + script will recursively search each directory listed in the 1.6550 + <literal moreinfo="none">collections</literal> section of its configuration 1.6551 + file, but it will <literal moreinfo="none">not</literal> recurse into the 1.6552 + repositories it finds.</para> 1.6553 + 1.6554 + <para id="x_4de">The <literal moreinfo="none">collections</literal> mechanism makes it easy 1.6555 + to publish many repositories in a <quote>fire and 1.6556 + forget</quote> manner. You only need to set up the CGI 1.6557 + script and configuration file one time. Afterwards, you can 1.6558 + publish or unpublish a repository at any time by simply moving 1.6559 + it into, or out of, the directory hierarchy in which you've 1.6560 + configured <filename role="special" moreinfo="none">hgwebdir.cgi</filename> to 1.6561 + look.</para> 1.6562 + 1.6563 + <sect3> 1.6564 + <title>Explicitly specifying which repositories to 1.6565 + publish</title> 1.6566 + 1.6567 + <para id="x_4df">In addition to the <literal moreinfo="none">collections</literal> 1.6568 + mechanism, the <filename role="special" moreinfo="none">hgwebdir.cgi</filename> script allows you 1.6569 + to publish a specific list of repositories. To do so, 1.6570 + create a <literal moreinfo="none">paths</literal> section, with contents of 1.6571 + the following form.</para> 1.6572 + <programlisting format="linespecific">[paths] 1.6573 +repo1 = /my/path/to/some/repo 1.6574 +repo2 = /some/path/to/another</programlisting> 1.6575 + <para id="x_4e0">In this case, the virtual path (the component that will 1.6576 + appear in a URL) is on the left hand side of each 1.6577 + definition, while the path to the repository is on the 1.6578 + right. Notice that there does not need to be any 1.6579 + relationship between the virtual path you choose and the 1.6580 + location of a repository in your filesystem.</para> 1.6581 + 1.6582 + <para id="x_4e1">If you wish, you can use both the 1.6583 + <literal moreinfo="none">collections</literal> and <literal moreinfo="none">paths</literal> 1.6584 + mechanisms simultaneously in a single configuration 1.6585 + file.</para> 1.6586 + 1.6587 + <note> 1.6588 + <title>Beware duplicate virtual paths</title> 1.6589 + 1.6590 + <para id="x_4e2"> If several repositories have the same 1.6591 + virtual path, <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will not report 1.6592 + an error. Instead, it will behave unpredictably.</para> 1.6593 + </note> 1.6594 + </sect3> 1.6595 + </sect2> 1.6596 + 1.6597 + <sect2> 1.6598 + <title>Downloading source archives</title> 1.6599 + 1.6600 + <para id="x_4e3">Mercurial's web interface lets users download an archive 1.6601 + of any revision. This archive will contain a snapshot of the 1.6602 + working directory as of that revision, but it will not contain 1.6603 + a copy of the repository data.</para> 1.6604 + 1.6605 + <para id="x_4e4">By default, this feature is not enabled. To enable it, 1.6606 + you'll need to add an <envar role="rc-item-web">allow_archive</envar> item to the 1.6607 + <literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>; see below for details.</para> 1.6608 + </sect2> 1.6609 + <sect2> 1.6610 + <title>Web configuration options</title> 1.6611 + 1.6612 + <para id="x_4e5">Mercurial's web interfaces (the <command role="hg-cmd" moreinfo="none">hg 1.6613 + 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 1.6614 + number of configuration options that you can set. These 1.6615 + belong in a section named <literal role="rc-web" moreinfo="none">web</literal>.</para> 1.6616 + <itemizedlist> 1.6617 + <listitem><para id="x_4e6"><envar role="rc-item-web">allow_archive</envar>: Determines 1.6618 + which (if any) archive download mechanisms Mercurial 1.6619 + supports. If you enable this feature, users of the web 1.6620 + interface will be able to download an archive of whatever 1.6621 + revision of a repository they are viewing. To enable the 1.6622 + archive feature, this item must take the form of a 1.6623 + sequence of words drawn from the list below.</para> 1.6624 + <itemizedlist> 1.6625 + <listitem><para id="x_4e7"><literal moreinfo="none">bz2</literal>: A 1.6626 + <command moreinfo="none">tar</command> archive, compressed using 1.6627 + <literal moreinfo="none">bzip2</literal> compression. This has the 1.6628 + best compression ratio, but uses the most CPU time on 1.6629 + the server.</para> 1.6630 + </listitem> 1.6631 + <listitem><para id="x_4e8"><literal moreinfo="none">gz</literal>: A 1.6632 + <command moreinfo="none">tar</command> archive, compressed using 1.6633 + <literal moreinfo="none">gzip</literal> compression.</para> 1.6634 + </listitem> 1.6635 + <listitem><para id="x_4e9"><literal moreinfo="none">zip</literal>: A 1.6636 + <command moreinfo="none">zip</command> archive, compressed using LZW 1.6637 + compression. This format has the worst compression 1.6638 + ratio, but is widely used in the Windows world.</para> 1.6639 + </listitem> 1.6640 + </itemizedlist> 1.6641 + <para id="x_4ea"> If you provide an empty list, or don't have an 1.6642 + <envar role="rc-item-web">allow_archive</envar> entry at 1.6643 + all, this feature will be disabled. Here is an example of 1.6644 + how to enable all three supported formats.</para> 1.6645 + <programlisting format="linespecific">[web] 1.6646 +allow_archive = bz2 gz zip</programlisting> 1.6647 + </listitem> 1.6648 + <listitem><para id="x_4eb"><envar role="rc-item-web">allowpull</envar>: 1.6649 + Boolean. Determines whether the web interface allows 1.6650 + remote users to <command role="hg-cmd" moreinfo="none">hg pull</command> 1.6651 + and <command role="hg-cmd" moreinfo="none">hg clone</command> this 1.6652 + repository over HTTP. If set to <literal moreinfo="none">no</literal> or 1.6653 + <literal moreinfo="none">false</literal>, only the 1.6654 + <quote>human-oriented</quote> portion of the web interface 1.6655 + is available.</para> 1.6656 + </listitem> 1.6657 + <listitem><para id="x_4ec"><envar role="rc-item-web">contact</envar>: 1.6658 + String. A free-form (but preferably brief) string 1.6659 + identifying the person or group in charge of the 1.6660 + repository. This often contains the name and email 1.6661 + address of a person or mailing list. It often makes sense 1.6662 + to place this entry in a repository's own <filename role="special" moreinfo="none">.hg/hgrc</filename> file, but it can make 1.6663 + sense to use in a global <filename role="special" moreinfo="none">~/.hgrc</filename> if every repository 1.6664 + has a single maintainer.</para> 1.6665 + </listitem> 1.6666 + <listitem><para id="x_4ed"><envar role="rc-item-web">maxchanges</envar>: 1.6667 + Integer. The default maximum number of changesets to 1.6668 + display in a single page of output.</para> 1.6669 + </listitem> 1.6670 + <listitem><para id="x_4ee"><envar role="rc-item-web">maxfiles</envar>: 1.6671 + Integer. The default maximum number of modified files to 1.6672 + display in a single page of output.</para> 1.6673 + </listitem> 1.6674 + <listitem><para id="x_4ef"><envar role="rc-item-web">stripes</envar>: 1.6675 + Integer. If the web interface displays alternating 1.6676 + <quote>stripes</quote> to make it easier to visually align 1.6677 + rows when you are looking at a table, this number controls 1.6678 + the number of rows in each stripe.</para> 1.6679 + </listitem> 1.6680 + <listitem><para id="x_4f0"><envar role="rc-item-web">style</envar>: Controls the template 1.6681 + Mercurial uses to display the web interface. Mercurial 1.6682 + ships with several web templates.</para> 1.6683 + <itemizedlist> 1.6684 + <listitem> 1.6685 + <para id="x_6aa"><literal moreinfo="none">coal</literal> is monochromatic.</para> 1.6686 + </listitem> 1.6687 + <listitem> 1.6688 + <para id="x_6ab"><literal moreinfo="none">gitweb</literal> emulates the visual 1.6689 + style of git's web interface.</para> 1.6690 + </listitem> 1.6691 + <listitem> 1.6692 + <para id="x_6ac"><literal moreinfo="none">monoblue</literal> uses solid blues and 1.6693 + greys.</para> 1.6694 + </listitem> 1.6695 + <listitem> 1.6696 + <para id="x_6ad"><literal moreinfo="none">paper</literal> is the default.</para> 1.6697 + </listitem> 1.6698 + <listitem> 1.6699 + <para id="x_6ae"><literal moreinfo="none">spartan</literal> was the default for a 1.6700 + long time.</para> 1.6701 + </listitem> 1.6702 + </itemizedlist> 1.6703 + <para id="x_6af">You can 1.6704 + also specify a custom template of your own; see 1.6705 + <xref linkend="chap:template"/> for details. Here, you can 1.6706 + see how to enable the <literal moreinfo="none">gitweb</literal> 1.6707 + style.</para> 1.6708 + <programlisting format="linespecific">[web] 1.6709 +style = gitweb</programlisting> 1.6710 + </listitem> 1.6711 + <listitem><para id="x_4f1"><envar role="rc-item-web">templates</envar>: 1.6712 + Path. The directory in which to search for template 1.6713 + files. By default, Mercurial searches in the directory in 1.6714 + which it was installed.</para> 1.6715 + </listitem></itemizedlist> 1.6716 + <para id="x_4f2">If you are using <filename role="special" moreinfo="none">hgwebdir.cgi</filename>, you can place a few 1.6717 + configuration items in a <literal role="rc-web" moreinfo="none">web</literal> 1.6718 + section of the <filename role="special" moreinfo="none">hgweb.config</filename> file instead of a 1.6719 + <filename role="special" moreinfo="none">~/.hgrc</filename> file, for 1.6720 + convenience. These items are <envar role="rc-item-web">motd</envar> and <envar role="rc-item-web">style</envar>.</para> 1.6721 + 1.6722 + <sect3> 1.6723 + <title>Options specific to an individual repository</title> 1.6724 + 1.6725 + <para id="x_4f3">A few <literal role="rc-web" moreinfo="none">web</literal> configuration 1.6726 + items ought to be placed in a repository's local <filename role="special" moreinfo="none">.hg/hgrc</filename>, rather than a user's 1.6727 + or global <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> 1.6728 + <itemizedlist> 1.6729 + <listitem><para id="x_4f4"><envar role="rc-item-web">description</envar>: String. A 1.6730 + free-form (but preferably brief) string that describes 1.6731 + the contents or purpose of the repository.</para> 1.6732 + </listitem> 1.6733 + <listitem><para id="x_4f5"><envar role="rc-item-web">name</envar>: 1.6734 + String. The name to use for the repository in the web 1.6735 + interface. This overrides the default name, which is 1.6736 + the last component of the repository's path.</para> 1.6737 + </listitem></itemizedlist> 1.6738 + </sect3> 1.6739 + 1.6740 + <sect3> 1.6741 + <title>Options specific to the <command role="hg-cmd" moreinfo="none">hg 1.6742 + serve</command> command</title> 1.6743 + 1.6744 + <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 1.6745 + with the <command role="hg-cmd" moreinfo="none">hg serve</command> 1.6746 + command.</para> 1.6747 + <itemizedlist> 1.6748 + <listitem><para id="x_4f7"><envar role="rc-item-web">accesslog</envar>: 1.6749 + Path. The name of a file into which to write an access 1.6750 + log. By default, the <command role="hg-cmd" moreinfo="none">hg 1.6751 + serve</command> command writes this information to 1.6752 + standard output, not to a file. Log entries are written 1.6753 + in the standard <quote>combined</quote> file format used 1.6754 + by almost all web servers.</para> 1.6755 + </listitem> 1.6756 + <listitem><para id="x_4f8"><envar role="rc-item-web">address</envar>: 1.6757 + String. The local address on which the server should 1.6758 + listen for incoming connections. By default, the server 1.6759 + listens on all addresses.</para> 1.6760 + </listitem> 1.6761 + <listitem><para id="x_4f9"><envar role="rc-item-web">errorlog</envar>: 1.6762 + Path. The name of a file into which to write an error 1.6763 + log. By default, the <command role="hg-cmd" moreinfo="none">hg 1.6764 + serve</command> command writes this information to 1.6765 + standard error, not to a file.</para> 1.6766 + </listitem> 1.6767 + <listitem><para id="x_4fa"><envar role="rc-item-web">ipv6</envar>: 1.6768 + Boolean. Whether to use the IPv6 protocol. By default, 1.6769 + IPv6 is not used.</para> 1.6770 + </listitem> 1.6771 + <listitem><para id="x_4fb"><envar role="rc-item-web">port</envar>: 1.6772 + Integer. The TCP port number on which the server should 1.6773 + listen. The default port number used is 8000.</para> 1.6774 + </listitem></itemizedlist> 1.6775 + </sect3> 1.6776 + 1.6777 + <sect3> 1.6778 + <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> 1.6779 + 1.6780 + <para id="x_4fc">It is important to remember that a web server like 1.6781 + Apache or <literal moreinfo="none">lighttpd</literal> will run under a user 1.6782 + ID that is different to yours. CGI scripts run by your 1.6783 + server, such as <filename role="special" moreinfo="none">hgweb.cgi</filename>, will usually also run 1.6784 + under that user ID.</para> 1.6785 + 1.6786 + <para id="x_4fd">If you add <literal role="rc-web" moreinfo="none">web</literal> items to 1.6787 + your own personal <filename role="special" moreinfo="none">~/.hgrc</filename> file, CGI scripts won't read that 1.6788 + <filename role="special" moreinfo="none">~/.hgrc</filename> file. Those 1.6789 + settings will thus only affect the behavior of the <command role="hg-cmd" moreinfo="none">hg serve</command> command when you run it. 1.6790 + To cause CGI scripts to see your settings, either create a 1.6791 + <filename role="special" moreinfo="none">~/.hgrc</filename> file in the 1.6792 + home directory of the user ID that runs your web server, or 1.6793 + add those settings to a system-wide <filename role="special" moreinfo="none">hgrc</filename> file.</para> 1.6794 + </sect3> 1.6795 + </sect2> 1.6796 + </sect1> 1.6797 + 1.6798 + <sect1> 1.6799 + <title>System-wide configuration</title> 1.6800 + 1.6801 + <para id="x_6b0">On Unix-like systems shared by multiple users (such as a 1.6802 + server to which people publish changes), it often makes sense to 1.6803 + set up some global default behaviors, such as what theme to use 1.6804 + in web interfaces.</para> 1.6805 + 1.6806 + <para id="x_6b1">If a file named <filename moreinfo="none">/etc/mercurial/hgrc</filename> 1.6807 + exists, Mercurial will read it at startup time and apply any 1.6808 + configuration settings it finds in that file. It will also look 1.6809 + for files ending in a <literal moreinfo="none">.rc</literal> extension in a 1.6810 + directory named <filename moreinfo="none">/etc/mercurial/hgrc.d</filename>, and 1.6811 + apply any configuration settings it finds in each of those 1.6812 + files.</para> 1.6813 + 1.6814 + <sect2> 1.6815 + <title>Making Mercurial more trusting</title> 1.6816 + 1.6817 + <para id="x_6b2">One situation in which a global <filename moreinfo="none">hgrc</filename> 1.6818 + can be useful is if users are pulling changes owned by other 1.6819 + users. By default, Mercurial will not trust most of the 1.6820 + configuration items in a <filename moreinfo="none">.hg/hgrc</filename> file 1.6821 + inside a repository that is owned by a different user. If we 1.6822 + clone or pull changes from such a repository, Mercurial will 1.6823 + print a warning stating that it does not trust their 1.6824 + <filename moreinfo="none">.hg/hgrc</filename>.</para> 1.6825 + 1.6826 + <para id="x_6b3">If everyone in a particular Unix group is on the same team 1.6827 + and <emphasis>should</emphasis> trust each other's 1.6828 + configuration settings, or we want to trust particular users, 1.6829 + we can override Mercurial's skeptical defaults by creating a 1.6830 + system-wide <filename moreinfo="none">hgrc</filename> file such as the 1.6831 + following:</para> 1.6832 + 1.6833 + <programlisting format="linespecific"># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc 1.6834 +[trusted] 1.6835 +# Trust all entries in any hgrc file owned by the "editors" or 1.6836 +# "www-data" groups. 1.6837 +groups = editors, www-data 1.6838 + 1.6839 +# Trust entries in hgrc files owned by the following users. 1.6840 +users = apache, bobo 1.6841 +</programlisting> 1.6842 + </sect2> 1.6843 + </sect1> 1.6844 +</chapter> 1.6845 + 1.6846 +<!-- 1.6847 +local variables: 1.6848 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.6849 +end: 1.6850 +--> 1.6851 + 1.6852 + <!-- BEGIN ch07 --> 1.6853 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.6854 + 1.6855 +<chapter id="chap:names"> 1.6856 + <?dbhtml filename="file-names-and-pattern-matching.html"?> 1.6857 + <title>File names and pattern matching</title> 1.6858 + 1.6859 + <para id="x_543">Mercurial provides mechanisms that let you work with file 1.6860 + names in a consistent and expressive way.</para> 1.6861 + 1.6862 + <sect1> 1.6863 + <title>Simple file naming</title> 1.6864 + 1.6865 + <para id="x_544">Mercurial uses a unified piece of machinery <quote>under the 1.6866 + hood</quote> to handle file names. Every command behaves 1.6867 + uniformly with respect to file names. The way in which commands 1.6868 + work with file names is as follows.</para> 1.6869 + 1.6870 + <para id="x_545">If you explicitly name real files on the command line, 1.6871 + Mercurial works with exactly those files, as you would expect. 1.6872 + <!-- BEGIN filenames.files --> 1.6873 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add COPYING README examples/simple.py</userinput> 1.6874 +</screen> 1.6875 +<!-- END filenames.files --> 1.6876 +</para> 1.6877 + 1.6878 + <para id="x_546">When you provide a directory name, Mercurial will interpret 1.6879 + this as <quote>operate on every file in this directory and its 1.6880 + subdirectories</quote>. Mercurial traverses the files and 1.6881 + subdirectories in a directory in alphabetical order. When it 1.6882 + encounters a subdirectory, it will traverse that subdirectory 1.6883 + before continuing with the current directory.</para> 1.6884 + 1.6885 + <!-- BEGIN filenames.dirs --> 1.6886 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status src</userinput> 1.6887 +? src/main.py 1.6888 +? src/watcher/_watcher.c 1.6889 +? src/watcher/watcher.py 1.6890 +? src/xyzzy.txt 1.6891 +</screen> 1.6892 +<!-- END filenames.dirs --> 1.6893 + 1.6894 + </sect1> 1.6895 + 1.6896 + <sect1> 1.6897 + <title>Running commands without any file names</title> 1.6898 + 1.6899 + <para id="x_547">Mercurial's commands that work with file names have useful 1.6900 + default behaviors when you invoke them without providing any 1.6901 + file names or patterns. What kind of behavior you should 1.6902 + expect depends on what the command does. Here are a few rules 1.6903 + of thumb you can use to predict what a command is likely to do 1.6904 + if you don't give it any names to work with.</para> 1.6905 + <itemizedlist> 1.6906 + <listitem><para id="x_548">Most commands will operate on the entire working 1.6907 + directory. This is what the <command role="hg-cmd" moreinfo="none">hg 1.6908 + add</command> command does, for example.</para> 1.6909 + </listitem> 1.6910 + <listitem><para id="x_549">If the command has effects that are difficult or 1.6911 + impossible to reverse, it will force you to explicitly 1.6912 + provide at least one name or pattern (see below). This 1.6913 + protects you from accidentally deleting files by running 1.6914 + <command role="hg-cmd" moreinfo="none">hg remove</command> with no 1.6915 + arguments, for example.</para> 1.6916 + </listitem></itemizedlist> 1.6917 + 1.6918 + <para id="x_54a">It's easy to work around these default behaviors if they 1.6919 + don't suit you. If a command normally operates on the whole 1.6920 + working directory, you can invoke it on just the current 1.6921 + directory and its subdirectories by giving it the name 1.6922 + <quote><filename class="directory" moreinfo="none">.</filename></quote>.</para> 1.6923 + 1.6924 + <!-- BEGIN filenames.wdir-subdir --> 1.6925 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd src</userinput> 1.6926 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n</userinput> 1.6927 +adding ../MANIFEST.in 1.6928 +adding ../examples/performant.py 1.6929 +adding ../setup.py 1.6930 +adding main.py 1.6931 +adding watcher/_watcher.c 1.6932 +adding watcher/watcher.py 1.6933 +adding xyzzy.txt 1.6934 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n .</userinput> 1.6935 +adding main.py 1.6936 +adding watcher/_watcher.c 1.6937 +adding watcher/watcher.py 1.6938 +adding xyzzy.txt 1.6939 +</screen> 1.6940 +<!-- END filenames.wdir-subdir --> 1.6941 + 1.6942 + 1.6943 + <para id="x_54b">Along the same lines, some commands normally print file 1.6944 + names relative to the root of the repository, even if you're 1.6945 + invoking them from a subdirectory. Such a command will print 1.6946 + file names relative to your subdirectory if you give it explicit 1.6947 + names. Here, we're going to run <command role="hg-cmd" moreinfo="none">hg 1.6948 + status</command> from a subdirectory, and get it to operate on 1.6949 + the entire working directory while printing file names relative 1.6950 + to our subdirectory, by passing it the output of the <command role="hg-cmd" moreinfo="none">hg root</command> command.</para> 1.6951 + 1.6952 + <!-- BEGIN filenames.wdir-relname --> 1.6953 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.6954 +A COPYING 1.6955 +A README 1.6956 +A examples/simple.py 1.6957 +? MANIFEST.in 1.6958 +? examples/performant.py 1.6959 +? setup.py 1.6960 +? src/main.py 1.6961 +? src/watcher/_watcher.c 1.6962 +? src/watcher/watcher.py 1.6963 +? src/xyzzy.txt 1.6964 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput> 1.6965 +A ../COPYING 1.6966 +A ../README 1.6967 +A ../examples/simple.py 1.6968 +? ../MANIFEST.in 1.6969 +? ../examples/performant.py 1.6970 +? ../setup.py 1.6971 +? main.py 1.6972 +? watcher/_watcher.c 1.6973 +? watcher/watcher.py 1.6974 +? xyzzy.txt 1.6975 +</screen> 1.6976 +<!-- END filenames.wdir-relname --> 1.6977 + 1.6978 + </sect1> 1.6979 + 1.6980 + <sect1> 1.6981 + <title>Telling you what's going on</title> 1.6982 + 1.6983 + <para id="x_54c">The <command role="hg-cmd" moreinfo="none">hg add</command> example in the 1.6984 + preceding section illustrates something else that's helpful 1.6985 + about Mercurial commands. If a command operates on a file that 1.6986 + you didn't name explicitly on the command line, it will usually 1.6987 + print the name of the file, so that you will not be surprised 1.6988 + what's going on.</para> 1.6989 + 1.6990 + <para id="x_54d">The principle here is of <emphasis>least 1.6991 + surprise</emphasis>. If you've exactly named a file on the 1.6992 + command line, there's no point in repeating it back at you. If 1.6993 + Mercurial is acting on a file <emphasis>implicitly</emphasis>, e.g. 1.6994 + because you provided no names, or a directory, or a pattern (see 1.6995 + below), it is safest to tell you what files it's operating on.</para> 1.6996 + 1.6997 + <para id="x_54e">For commands that behave this way, you can silence them 1.6998 + using the <option role="hg-opt-global">-q</option> option. You 1.6999 + can also get them to print the name of every file, even those 1.7000 + you've named explicitly, using the <option role="hg-opt-global">-v</option> option.</para> 1.7001 + </sect1> 1.7002 + 1.7003 + <sect1> 1.7004 + <title>Using patterns to identify files</title> 1.7005 + 1.7006 + <para id="x_54f">In addition to working with file and directory names, 1.7007 + Mercurial lets you use <emphasis>patterns</emphasis> to identify 1.7008 + files. Mercurial's pattern handling is expressive.</para> 1.7009 + 1.7010 + <para id="x_550">On Unix-like systems (Linux, MacOS, etc.), the job of 1.7011 + matching file names to patterns normally falls to the shell. On 1.7012 + these systems, you must explicitly tell Mercurial that a name is 1.7013 + a pattern. On Windows, the shell does not expand patterns, so 1.7014 + Mercurial will automatically identify names that are patterns, 1.7015 + and expand them for you.</para> 1.7016 + 1.7017 + <para id="x_551">To provide a pattern in place of a regular name on the 1.7018 + command line, the mechanism is simple:</para> 1.7019 + <programlisting format="linespecific">syntax:patternbody</programlisting> 1.7020 + <para id="x_552">That is, a pattern is identified by a short text string that 1.7021 + says what kind of pattern this is, followed by a colon, followed 1.7022 + by the actual pattern.</para> 1.7023 + 1.7024 + <para id="x_553">Mercurial supports two kinds of pattern syntax. The most 1.7025 + frequently used is called <literal moreinfo="none">glob</literal>; this is the 1.7026 + same kind of pattern matching used by the Unix shell, and should 1.7027 + be familiar to Windows command prompt users, too.</para> 1.7028 + 1.7029 + <para id="x_554">When Mercurial does automatic pattern matching on Windows, 1.7030 + it uses <literal moreinfo="none">glob</literal> syntax. You can thus omit the 1.7031 + <quote><literal moreinfo="none">glob:</literal></quote> prefix on Windows, but 1.7032 + it's safe to use it, too.</para> 1.7033 + 1.7034 + <para id="x_555">The <literal moreinfo="none">re</literal> syntax is more powerful; it lets 1.7035 + you specify patterns using regular expressions, also known as 1.7036 + regexps.</para> 1.7037 + 1.7038 + <para id="x_556">By the way, in the examples that follow, notice that I'm 1.7039 + careful to wrap all of my patterns in quote characters, so that 1.7040 + they won't get expanded by the shell before Mercurial sees 1.7041 + them.</para> 1.7042 + 1.7043 + <sect2> 1.7044 + <title>Shell-style <literal moreinfo="none">glob</literal> patterns</title> 1.7045 + 1.7046 + <para id="x_557">This is an overview of the kinds of patterns you can use 1.7047 + when you're matching on glob patterns.</para> 1.7048 + 1.7049 + <para id="x_558">The <quote><literal moreinfo="none">*</literal></quote> character matches 1.7050 + any string, within a single directory.</para> 1.7051 + 1.7052 + <!-- BEGIN filenames.glob.star --> 1.7053 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add 'glob:*.py'</userinput> 1.7054 +adding main.py 1.7055 +</screen> 1.7056 +<!-- END filenames.glob.star --> 1.7057 + 1.7058 + 1.7059 + <para id="x_559">The <quote><literal moreinfo="none">**</literal></quote> pattern matches 1.7060 + any string, and crosses directory boundaries. It's not a 1.7061 + standard Unix glob token, but it's accepted by several popular 1.7062 + Unix shells, and is very useful.</para> 1.7063 + 1.7064 + <!-- BEGIN filenames.glob.starstar --> 1.7065 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.7066 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput> 1.7067 +A examples/simple.py 1.7068 +A src/main.py 1.7069 +? examples/performant.py 1.7070 +? setup.py 1.7071 +? src/watcher/watcher.py 1.7072 +</screen> 1.7073 +<!-- END filenames.glob.starstar --> 1.7074 + 1.7075 + 1.7076 + <para id="x_55a">The <quote><literal moreinfo="none">?</literal></quote> pattern matches 1.7077 + any single character.</para> 1.7078 + 1.7079 + <!-- BEGIN filenames.glob.question --> 1.7080 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.?'</userinput> 1.7081 +? src/watcher/_watcher.c 1.7082 +</screen> 1.7083 +<!-- END filenames.glob.question --> 1.7084 + 1.7085 + 1.7086 + <para id="x_55b">The <quote><literal moreinfo="none">[</literal></quote> character begins a 1.7087 + <emphasis>character class</emphasis>. This matches any single 1.7088 + character within the class. The class ends with a 1.7089 + <quote><literal moreinfo="none">]</literal></quote> character. A class may 1.7090 + contain multiple <emphasis>range</emphasis>s of the form 1.7091 + <quote><literal moreinfo="none">a-f</literal></quote>, which is shorthand for 1.7092 + <quote><literal moreinfo="none">abcdef</literal></quote>.</para> 1.7093 + 1.7094 + <!-- BEGIN filenames.glob.range --> 1.7095 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**[nr-t]'</userinput> 1.7096 +? MANIFEST.in 1.7097 +? src/xyzzy.txt 1.7098 +</screen> 1.7099 +<!-- END filenames.glob.range --> 1.7100 + 1.7101 + 1.7102 + <para id="x_55c">If the first character after the 1.7103 + <quote><literal moreinfo="none">[</literal></quote> in a character class is a 1.7104 + <quote><literal moreinfo="none">!</literal></quote>, it 1.7105 + <emphasis>negates</emphasis> the class, making it match any 1.7106 + single character not in the class.</para> 1.7107 + 1.7108 + <para id="x_55d">A <quote><literal moreinfo="none">{</literal></quote> begins a group of 1.7109 + subpatterns, where the whole group matches if any subpattern 1.7110 + in the group matches. The <quote><literal moreinfo="none">,</literal></quote> 1.7111 + character separates subpatterns, and 1.7112 + <quote><literal moreinfo="none">}</literal></quote> ends the group.</para> 1.7113 + 1.7114 + <!-- BEGIN filenames.glob.group --> 1.7115 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.{in,py}'</userinput> 1.7116 +? MANIFEST.in 1.7117 +? setup.py 1.7118 +</screen> 1.7119 +<!-- END filenames.glob.group --> 1.7120 + 1.7121 + 1.7122 + <sect3> 1.7123 + <title>Watch out!</title> 1.7124 + 1.7125 + <para id="x_55e">Don't forget that if you want to match a pattern in any 1.7126 + directory, you should not be using the 1.7127 + <quote><literal moreinfo="none">*</literal></quote> match-any token, as this 1.7128 + will only match within one directory. Instead, use the 1.7129 + <quote><literal moreinfo="none">**</literal></quote> token. This small 1.7130 + example illustrates the difference between the two.</para> 1.7131 + 1.7132 + <!-- BEGIN filenames.glob.star-starstar --> 1.7133 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.py'</userinput> 1.7134 +? setup.py 1.7135 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput> 1.7136 +A examples/simple.py 1.7137 +A src/main.py 1.7138 +? examples/performant.py 1.7139 +? setup.py 1.7140 +? src/watcher/watcher.py 1.7141 +</screen> 1.7142 +<!-- END filenames.glob.star-starstar --> 1.7143 + 1.7144 + </sect3> 1.7145 + </sect2> 1.7146 + 1.7147 + <sect2> 1.7148 + <title>Regular expression matching with <literal moreinfo="none">re</literal> 1.7149 + patterns</title> 1.7150 + 1.7151 + <para id="x_55f">Mercurial accepts the same regular expression syntax as 1.7152 + the Python programming language (it uses Python's regexp 1.7153 + engine internally). This is based on the Perl language's 1.7154 + regexp syntax, which is the most popular dialect in use (it's 1.7155 + also used in Java, for example).</para> 1.7156 + 1.7157 + <para id="x_560">I won't discuss Mercurial's regexp dialect in any detail 1.7158 + here, as regexps are not often used. Perl-style regexps are 1.7159 + in any case already exhaustively documented on a multitude of 1.7160 + web sites, and in many books. Instead, I will focus here on a 1.7161 + few things you should know if you find yourself needing to use 1.7162 + regexps with Mercurial.</para> 1.7163 + 1.7164 + <para id="x_561">A regexp is matched against an entire file name, relative 1.7165 + to the root of the repository. In other words, even if you're 1.7166 + already in subbdirectory <filename class="directory" moreinfo="none">foo</filename>, if you want to match files 1.7167 + under this directory, your pattern must start with 1.7168 + <quote><literal moreinfo="none">foo/</literal></quote>.</para> 1.7169 + 1.7170 + <para id="x_562">One thing to note, if you're familiar with Perl-style 1.7171 + regexps, is that Mercurial's are <emphasis>rooted</emphasis>. 1.7172 + That is, a regexp starts matching against the beginning of a 1.7173 + string; it doesn't look for a match anywhere within the 1.7174 + string. To match anywhere in a string, start your pattern 1.7175 + with <quote><literal moreinfo="none">.*</literal></quote>.</para> 1.7176 + </sect2> 1.7177 + </sect1> 1.7178 + 1.7179 + <sect1> 1.7180 + <title>Filtering files</title> 1.7181 + 1.7182 + <para id="x_563">Not only does Mercurial give you a variety of ways to 1.7183 + specify files; it lets you further winnow those files using 1.7184 + <emphasis>filters</emphasis>. Commands that work with file 1.7185 + names accept two filtering options.</para> 1.7186 + <itemizedlist> 1.7187 + <listitem><para id="x_564"><option role="hg-opt-global">-I</option>, or 1.7188 + <option role="hg-opt-global">--include</option>, lets you 1.7189 + specify a pattern that file names must match in order to be 1.7190 + processed.</para> 1.7191 + </listitem> 1.7192 + <listitem><para id="x_565"><option role="hg-opt-global">-X</option>, or 1.7193 + <option role="hg-opt-global">--exclude</option>, gives you a 1.7194 + way to <emphasis>avoid</emphasis> processing files, if they 1.7195 + match this pattern.</para> 1.7196 + </listitem></itemizedlist> 1.7197 + <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, 1.7198 + and intermix them as you please. Mercurial interprets the 1.7199 + patterns you provide using glob syntax by default (but you can 1.7200 + use regexps if you need to).</para> 1.7201 + 1.7202 + <para id="x_567">You can read a <option role="hg-opt-global">-I</option> 1.7203 + filter as <quote>process only the files that match this 1.7204 + filter</quote>.</para> 1.7205 + 1.7206 + <!-- BEGIN filenames.filter.include --> 1.7207 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -I '*.in'</userinput> 1.7208 +? MANIFEST.in 1.7209 +</screen> 1.7210 +<!-- END filenames.filter.include --> 1.7211 + 1.7212 + 1.7213 + <para id="x_568">The <option role="hg-opt-global">-X</option> filter is best 1.7214 + read as <quote>process only the files that don't match this 1.7215 + pattern</quote>.</para> 1.7216 + 1.7217 + <!-- BEGIN filenames.filter.exclude --> 1.7218 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -X '**.py' src</userinput> 1.7219 +? src/watcher/_watcher.c 1.7220 +? src/xyzzy.txt 1.7221 +</screen> 1.7222 +<!-- END filenames.filter.exclude --> 1.7223 + 1.7224 + </sect1> 1.7225 + 1.7226 + <sect1> 1.7227 + <title>Permanently ignoring unwanted files and directories</title> 1.7228 + 1.7229 + <para id="x_569">When you create a new repository, the chances are 1.7230 + that over time it will grow to contain files that ought to 1.7231 + <emphasis>not</emphasis> be managed by Mercurial, but which you 1.7232 + don't want to see listed every time you run <command moreinfo="none">hg 1.7233 + status</command>. For instance, <quote>build products</quote> 1.7234 + are files that are created as part of a build but which should 1.7235 + not be managed by a revision control system. The most common 1.7236 + build products are output files produced by software tools such 1.7237 + as compilers. As another example, many text editors litter a 1.7238 + directory with lock files, temporary working files, and backup 1.7239 + files, which it also makes no sense to manage.</para> 1.7240 + 1.7241 + <para id="x_6b4">To have Mercurial permanently ignore such files, create a 1.7242 + file named <filename moreinfo="none">.hgignore</filename> in the root of your 1.7243 + repository. You <emphasis>should</emphasis> <command moreinfo="none">hg 1.7244 + add</command> this file so that it gets tracked with the rest of 1.7245 + your repository contents, since your collaborators will probably 1.7246 + find it useful too.</para> 1.7247 + 1.7248 + <para id="x_6b5">By default, the <filename moreinfo="none">.hgignore</filename> file should 1.7249 + contain a list of regular expressions, one per line. Empty 1.7250 + lines are skipped. Most people prefer to describe the files they 1.7251 + want to ignore using the <quote>glob</quote> syntax that we 1.7252 + described above, so a typical <filename moreinfo="none">.hgignore</filename> 1.7253 + file will start with this directive:</para> 1.7254 + 1.7255 + <programlisting format="linespecific">syntax: glob</programlisting> 1.7256 + 1.7257 + <para id="x_6b6">This tells Mercurial to interpret the lines that follow as 1.7258 + glob patterns, not regular expressions.</para> 1.7259 + 1.7260 + <para id="x_6b7">Here is a typical-looking <filename moreinfo="none">.hgignore</filename> 1.7261 + file.</para> 1.7262 + 1.7263 + <programlisting format="linespecific">syntax: glob 1.7264 +# This line is a comment, and will be skipped. 1.7265 +# Empty lines are skipped too. 1.7266 + 1.7267 +# Backup files left behind by the Emacs editor. 1.7268 +*~ 1.7269 + 1.7270 +# Lock files used by the Emacs editor. 1.7271 +# Notice that the "#" character is quoted with a backslash. 1.7272 +# This prevents it from being interpreted as starting a comment. 1.7273 +.\#* 1.7274 + 1.7275 +# Temporary files used by the vim editor. 1.7276 +.*.swp 1.7277 + 1.7278 +# A hidden file created by the Mac OS X Finder. 1.7279 +.DS_Store 1.7280 +</programlisting> 1.7281 + </sect1> 1.7282 + 1.7283 + <sect1 id="sec:names:case"> 1.7284 + <title>Case sensitivity</title> 1.7285 + 1.7286 + <para id="x_56a">If you're working in a mixed development environment that 1.7287 + contains both Linux (or other Unix) systems and Macs or Windows 1.7288 + systems, you should keep in the back of your mind the knowledge 1.7289 + that they treat the case (<quote>N</quote> versus 1.7290 + <quote>n</quote>) of file names in incompatible ways. This is 1.7291 + not very likely to affect you, and it's easy to deal with if it 1.7292 + does, but it could surprise you if you don't know about 1.7293 + it.</para> 1.7294 + 1.7295 + <para id="x_56b">Operating systems and filesystems differ in the way they 1.7296 + handle the <emphasis>case</emphasis> of characters in file and 1.7297 + directory names. There are three common ways to handle case in 1.7298 + names.</para> 1.7299 + <itemizedlist> 1.7300 + <listitem><para id="x_56c">Completely case insensitive. Uppercase and 1.7301 + lowercase versions of a letter are treated as identical, 1.7302 + both when creating a file and during subsequent accesses. 1.7303 + This is common on older DOS-based systems.</para> 1.7304 + </listitem> 1.7305 + <listitem><para id="x_56d">Case preserving, but insensitive. When a file 1.7306 + or directory is created, the case of its name is stored, and 1.7307 + can be retrieved and displayed by the operating system. 1.7308 + When an existing file is being looked up, its case is 1.7309 + ignored. This is the standard arrangement on Windows and 1.7310 + MacOS. The names <filename moreinfo="none">foo</filename> and 1.7311 + <filename moreinfo="none">FoO</filename> identify the same file. This 1.7312 + treatment of uppercase and lowercase letters as 1.7313 + interchangeable is also referred to as <emphasis>case 1.7314 + folding</emphasis>.</para> 1.7315 + </listitem> 1.7316 + <listitem><para id="x_56e">Case sensitive. The case of a name 1.7317 + is significant at all times. The names 1.7318 + <filename moreinfo="none">foo</filename> and <filename moreinfo="none">FoO</filename> 1.7319 + identify different files. This is the way Linux and Unix 1.7320 + systems normally work.</para> 1.7321 + </listitem></itemizedlist> 1.7322 + 1.7323 + <para id="x_56f">On Unix-like systems, it is possible to have any or all of 1.7324 + the above ways of handling case in action at once. For example, 1.7325 + if you use a USB thumb drive formatted with a FAT32 filesystem 1.7326 + on a Linux system, Linux will handle names on that filesystem in 1.7327 + a case preserving, but insensitive, way.</para> 1.7328 + 1.7329 + <sect2> 1.7330 + <title>Safe, portable repository storage</title> 1.7331 + 1.7332 + <para id="x_570">Mercurial's repository storage mechanism is <emphasis>case 1.7333 + safe</emphasis>. It translates file names so that they can 1.7334 + be safely stored on both case sensitive and case insensitive 1.7335 + filesystems. This means that you can use normal file copying 1.7336 + tools to transfer a Mercurial repository onto, for example, a 1.7337 + USB thumb drive, and safely move that drive and repository 1.7338 + back and forth between a Mac, a PC running Windows, and a 1.7339 + Linux box.</para> 1.7340 + 1.7341 + </sect2> 1.7342 + <sect2> 1.7343 + <title>Detecting case conflicts</title> 1.7344 + 1.7345 + <para id="x_571">When operating in the working directory, Mercurial honours 1.7346 + the naming policy of the filesystem where the working 1.7347 + directory is located. If the filesystem is case preserving, 1.7348 + but insensitive, Mercurial will treat names that differ only 1.7349 + in case as the same.</para> 1.7350 + 1.7351 + <para id="x_572">An important aspect of this approach is that it is 1.7352 + possible to commit a changeset on a case sensitive (typically 1.7353 + Linux or Unix) filesystem that will cause trouble for users on 1.7354 + case insensitive (usually Windows and MacOS) users. If a 1.7355 + Linux user commits changes to two files, one named 1.7356 + <filename moreinfo="none">myfile.c</filename> and the other named 1.7357 + <filename moreinfo="none">MyFile.C</filename>, they will be stored correctly 1.7358 + in the repository. And in the working directories of other 1.7359 + Linux users, they will be correctly represented as separate 1.7360 + files.</para> 1.7361 + 1.7362 + <para id="x_573">If a Windows or Mac user pulls this change, they will not 1.7363 + initially have a problem, because Mercurial's repository 1.7364 + storage mechanism is case safe. However, once they try to 1.7365 + <command role="hg-cmd" moreinfo="none">hg update</command> the working 1.7366 + directory to that changeset, or <command role="hg-cmd" moreinfo="none">hg 1.7367 + merge</command> with that changeset, Mercurial will spot the 1.7368 + conflict between the two file names that the filesystem would 1.7369 + treat as the same, and forbid the update or merge from 1.7370 + occurring.</para> 1.7371 + </sect2> 1.7372 + 1.7373 + <sect2> 1.7374 + <title>Fixing a case conflict</title> 1.7375 + 1.7376 + <para id="x_574">If you are using Windows or a Mac in a mixed environment 1.7377 + where some of your collaborators are using Linux or Unix, and 1.7378 + Mercurial reports a case folding conflict when you try to 1.7379 + <command role="hg-cmd" moreinfo="none">hg update</command> or <command role="hg-cmd" moreinfo="none">hg merge</command>, the procedure to fix the 1.7380 + problem is simple.</para> 1.7381 + 1.7382 + <para id="x_575">Just find a nearby Linux or Unix box, clone the problem 1.7383 + repository onto it, and use Mercurial's <command role="hg-cmd" moreinfo="none">hg rename</command> command to change the 1.7384 + names of any offending files or directories so that they will 1.7385 + no longer cause case folding conflicts. Commit this change, 1.7386 + <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 1.7387 + MacOS system, and <command role="hg-cmd" moreinfo="none">hg update</command> 1.7388 + to the revision with the non-conflicting names.</para> 1.7389 + 1.7390 + <para id="x_576">The changeset with case-conflicting names will remain in 1.7391 + your project's history, and you still won't be able to 1.7392 + <command role="hg-cmd" moreinfo="none">hg update</command> your working 1.7393 + directory to that changeset on a Windows or MacOS system, but 1.7394 + you can continue development unimpeded.</para> 1.7395 + </sect2> 1.7396 + </sect1> 1.7397 +</chapter> 1.7398 + 1.7399 +<!-- 1.7400 +local variables: 1.7401 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.7402 +end: 1.7403 +--> 1.7404 + 1.7405 + <!-- BEGIN ch08 --> 1.7406 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.7407 + 1.7408 +<chapter id="chap:branch"> 1.7409 + <?dbhtml filename="managing-releases-and-branchy-development.html"?> 1.7410 + <title>Managing releases and branchy development</title> 1.7411 + 1.7412 + <para id="x_369">Mercurial provides several mechanisms for you to manage a 1.7413 + project that is making progress on multiple fronts at once. To 1.7414 + understand these mechanisms, let's first take a brief look at a 1.7415 + fairly normal software project structure.</para> 1.7416 + 1.7417 + <para id="x_36a">Many software projects issue periodic <quote>major</quote> 1.7418 + releases that contain substantial new features. In parallel, they 1.7419 + may issue <quote>minor</quote> releases. These are usually 1.7420 + identical to the major releases off which they're based, but with 1.7421 + a few bugs fixed.</para> 1.7422 + 1.7423 + <para id="x_36b">In this chapter, we'll start by talking about how to keep 1.7424 + records of project milestones such as releases. We'll then 1.7425 + continue on to talk about the flow of work between different 1.7426 + phases of a project, and how Mercurial can help you to isolate and 1.7427 + manage this work.</para> 1.7428 + 1.7429 + <sect1> 1.7430 + <title>Giving a persistent name to a revision</title> 1.7431 + 1.7432 + <para id="x_36c">Once you decide that you'd like to call a particular 1.7433 + revision a <quote>release</quote>, it's a good idea to record 1.7434 + the identity of that revision. This will let you reproduce that 1.7435 + release at a later date, for whatever purpose you might need at 1.7436 + the time (reproducing a bug, porting to a new platform, etc). 1.7437 + <!-- BEGIN tag.init --> 1.7438 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mytag</userinput> 1.7439 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mytag</userinput> 1.7440 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello > myfile</userinput> 1.7441 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Initial commit'</userinput> 1.7442 +adding myfile 1.7443 +</screen> 1.7444 +<!-- END tag.init --> 1.7445 +</para> 1.7446 + 1.7447 + <para id="x_36d">Mercurial lets you give a permanent name to any revision 1.7448 + using the <command role="hg-cmd" moreinfo="none">hg tag</command> command. Not 1.7449 + surprisingly, these names are called <quote>tags</quote>.</para> 1.7450 + 1.7451 + <!-- BEGIN tag.tag --> 1.7452 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput> 1.7453 +</screen> 1.7454 +<!-- END tag.tag --> 1.7455 + 1.7456 + 1.7457 + <para id="x_36e">A tag is nothing more than a <quote>symbolic name</quote> 1.7458 + for a revision. Tags exist purely for your convenience, so that 1.7459 + you have a handy permanent way to refer to a revision; Mercurial 1.7460 + doesn't interpret the tag names you use in any way. Neither 1.7461 + does Mercurial place any restrictions on the name of a tag, 1.7462 + beyond a few that are necessary to ensure that a tag can be 1.7463 + parsed unambiguously. A tag name cannot contain any of the 1.7464 + following characters:</para> 1.7465 + <itemizedlist> 1.7466 + <listitem><para id="x_36f">Colon (ASCII 58, 1.7467 + <quote><literal moreinfo="none">:</literal></quote>)</para> 1.7468 + </listitem> 1.7469 + <listitem><para id="x_370">Carriage return (ASCII 13, 1.7470 + <quote><literal moreinfo="none">\r</literal></quote>)</para> 1.7471 + </listitem> 1.7472 + <listitem><para id="x_371">Newline (ASCII 10, 1.7473 + <quote><literal moreinfo="none">\n</literal></quote>)</para> 1.7474 + </listitem></itemizedlist> 1.7475 + 1.7476 + <para id="x_372">You can use the <command role="hg-cmd" moreinfo="none">hg tags</command> 1.7477 + command to display the tags present in your repository. In the 1.7478 + output, each tagged revision is identified first by its name, 1.7479 + then by revision number, and finally by the unique hash of the 1.7480 + revision.</para> 1.7481 + 1.7482 + <!-- BEGIN tag.tags --> 1.7483 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> 1.7484 +tip 1:f283c2669b38 1.7485 +v1.0 0:0c957785065f 1.7486 +</screen> 1.7487 +<!-- END tag.tags --> 1.7488 + 1.7489 + 1.7490 + <para id="x_373">Notice that <literal moreinfo="none">tip</literal> is listed in the output 1.7491 + of <command role="hg-cmd" moreinfo="none">hg tags</command>. The 1.7492 + <literal moreinfo="none">tip</literal> tag is a special <quote>floating</quote> 1.7493 + tag, which always identifies the newest revision in the 1.7494 + repository.</para> 1.7495 + 1.7496 + <para id="x_374">In the output of the <command role="hg-cmd" moreinfo="none">hg 1.7497 + tags</command> command, tags are listed in reverse order, by 1.7498 + revision number. This usually means that recent tags are listed 1.7499 + before older tags. It also means that <literal moreinfo="none">tip</literal> is 1.7500 + always going to be the first tag listed in the output of 1.7501 + <command role="hg-cmd" moreinfo="none">hg tags</command>.</para> 1.7502 + 1.7503 + <para id="x_375">When you run <command role="hg-cmd" moreinfo="none">hg log</command>, if it 1.7504 + displays a revision that has tags associated with it, it will 1.7505 + print those tags.</para> 1.7506 + 1.7507 + <!-- BEGIN tag.log --> 1.7508 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput> 1.7509 +changeset: 1:f283c2669b38 1.7510 +tag: tip 1.7511 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7512 +date: Sun Aug 16 14:05:16 2009 +0000 1.7513 +summary: Added tag v1.0 for changeset 0c957785065f 1.7514 + 1.7515 +changeset: 0:0c957785065f 1.7516 +tag: v1.0 1.7517 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7518 +date: Sun Aug 16 14:05:15 2009 +0000 1.7519 +summary: Initial commit 1.7520 + 1.7521 +</screen> 1.7522 +<!-- END tag.log --> 1.7523 + 1.7524 + 1.7525 + <para id="x_376">Any time you need to provide a revision ID to a Mercurial 1.7526 + command, the command will accept a tag name in its place. 1.7527 + Internally, Mercurial will translate your tag name into the 1.7528 + corresponding revision ID, then use that.</para> 1.7529 + 1.7530 + <!-- BEGIN tag.log.v1.0 --> 1.7531 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye > myfile2</userinput> 1.7532 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Second commit'</userinput> 1.7533 +adding myfile2 1.7534 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r v1.0</userinput> 1.7535 +changeset: 0:0c957785065f 1.7536 +tag: v1.0 1.7537 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7538 +date: Sun Aug 16 14:05:15 2009 +0000 1.7539 +summary: Initial commit 1.7540 + 1.7541 +</screen> 1.7542 +<!-- END tag.log.v1.0 --> 1.7543 + 1.7544 + 1.7545 + <para id="x_377">There's no limit on the number of tags you can have in a 1.7546 + repository, or on the number of tags that a single revision can 1.7547 + have. As a practical matter, it's not a great idea to have 1.7548 + <quote>too many</quote> (a number which will vary from project 1.7549 + to project), simply because tags are supposed to help you to 1.7550 + find revisions. If you have lots of tags, the ease of using 1.7551 + them to identify revisions diminishes rapidly.</para> 1.7552 + 1.7553 + <para id="x_378">For example, if your project has milestones as frequent as 1.7554 + every few days, it's perfectly reasonable to tag each one of 1.7555 + those. But if you have a continuous build system that makes 1.7556 + sure every revision can be built cleanly, you'd be introducing a 1.7557 + lot of noise if you were to tag every clean build. Instead, you 1.7558 + could tag failed builds (on the assumption that they're rare!), 1.7559 + or simply not use tags to track buildability.</para> 1.7560 + 1.7561 + <para id="x_379">If you want to remove a tag that you no longer want, use 1.7562 + <command role="hg-cmd" moreinfo="none">hg tag --remove</command>.</para> 1.7563 + 1.7564 + <!-- BEGIN tag.remove --> 1.7565 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag --remove v1.0</userinput> 1.7566 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> 1.7567 +tip 3:0f446f1d1f7f 1.7568 +</screen> 1.7569 +<!-- END tag.remove --> 1.7570 + 1.7571 + 1.7572 + <para id="x_37a">You can also modify a tag at any time, so that it identifies 1.7573 + a different revision, by simply issuing a new <command role="hg-cmd" moreinfo="none">hg tag</command> command. You'll have to use the 1.7574 + <option role="hg-opt-tag">-f</option> option to tell Mercurial 1.7575 + that you <emphasis>really</emphasis> want to update the 1.7576 + tag.</para> 1.7577 + 1.7578 + <!-- BEGIN tag.replace --> 1.7579 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 1 v1.1</userinput> 1.7580 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> 1.7581 +tip 4:12fc7bf92915 1.7582 +v1.1 1:f283c2669b38 1.7583 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 2 v1.1</userinput> 1.7584 +abort: tag 'v1.1' already exists (use -f to force) 1.7585 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -f -r 2 v1.1</userinput> 1.7586 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> 1.7587 +tip 5:17e25cf010af 1.7588 +v1.1 2:737882b3cc76 1.7589 +</screen> 1.7590 +<!-- END tag.replace --> 1.7591 + 1.7592 + 1.7593 + <para id="x_37b">There will still be a permanent record of the previous 1.7594 + identity of the tag, but Mercurial will no longer use it. 1.7595 + There's thus no penalty to tagging the wrong revision; all you 1.7596 + have to do is turn around and tag the correct revision once you 1.7597 + discover your error.</para> 1.7598 + 1.7599 + <para id="x_37c">Mercurial stores tags in a normal revision-controlled file 1.7600 + in your repository. If you've created any tags, you'll find 1.7601 + 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 1.7602 + this file, then automatically commits the change to it. This 1.7603 + means that every time you run <command role="hg-cmd" moreinfo="none">hg 1.7604 + tag</command>, you'll see a corresponding changeset in the 1.7605 + output of <command role="hg-cmd" moreinfo="none">hg log</command>.</para> 1.7606 + 1.7607 + <!-- BEGIN tag.tip --> 1.7608 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.7609 +changeset: 5:17e25cf010af 1.7610 +tag: tip 1.7611 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7612 +date: Sun Aug 16 14:05:16 2009 +0000 1.7613 +summary: Added tag v1.1 for changeset 737882b3cc76 1.7614 + 1.7615 +</screen> 1.7616 +<!-- END tag.tip --> 1.7617 + 1.7618 + 1.7619 + <sect2> 1.7620 + <title>Handling tag conflicts during a merge</title> 1.7621 + 1.7622 + <para id="x_37d">You won't often need to care about the <filename role="special" moreinfo="none">.hgtags</filename> file, but it sometimes 1.7623 + makes its presence known during a merge. The format of the 1.7624 + file is simple: it consists of a series of lines. Each line 1.7625 + starts with a changeset hash, followed by a space, followed by 1.7626 + the name of a tag.</para> 1.7627 + 1.7628 + <para id="x_37e">If you're resolving a conflict in the <filename role="special" moreinfo="none">.hgtags</filename> file during a merge, 1.7629 + there's one twist to modifying the <filename role="special" moreinfo="none">.hgtags</filename> file: when Mercurial is 1.7630 + parsing the tags in a repository, it 1.7631 + <emphasis>never</emphasis> reads the working copy of the 1.7632 + <filename role="special" moreinfo="none">.hgtags</filename> file. Instead, it 1.7633 + reads the <emphasis>most recently committed</emphasis> 1.7634 + revision of the file.</para> 1.7635 + 1.7636 + <para id="x_37f">An unfortunate consequence of this design is that you 1.7637 + can't actually verify that your merged <filename role="special" moreinfo="none">.hgtags</filename> file is correct until 1.7638 + <emphasis>after</emphasis> you've committed a change. So if 1.7639 + you find yourself resolving a conflict on <filename role="special" moreinfo="none">.hgtags</filename> during a merge, be sure to 1.7640 + run <command role="hg-cmd" moreinfo="none">hg tags</command> after you commit. 1.7641 + If it finds an error in the <filename role="special" moreinfo="none">.hgtags</filename> file, it will report the 1.7642 + location of the error, which you can then fix and commit. You 1.7643 + should then run <command role="hg-cmd" moreinfo="none">hg tags</command> 1.7644 + again, just to be sure that your fix is correct.</para> 1.7645 + </sect2> 1.7646 + 1.7647 + <sect2> 1.7648 + <title>Tags and cloning</title> 1.7649 + 1.7650 + <para id="x_380">You may have noticed that the <command role="hg-cmd" moreinfo="none">hg 1.7651 + clone</command> command has a <option role="hg-opt-clone">-r</option> option that lets you clone 1.7652 + an exact copy of the repository as of a particular changeset. 1.7653 + The new clone will not contain any project history that comes 1.7654 + after the revision you specified. This has an interaction 1.7655 + with tags that can surprise the unwary.</para> 1.7656 + 1.7657 + <para id="x_381">Recall that a tag is stored as a revision to 1.7658 + the <filename role="special" moreinfo="none">.hgtags</filename> file. When you 1.7659 + create a tag, the changeset in which its recorded refers to an 1.7660 + older changeset. When you run <command role="hg-cmd" moreinfo="none">hg clone 1.7661 + -r foo</command> to clone a repository as of tag 1.7662 + <literal moreinfo="none">foo</literal>, the new clone <emphasis>will not 1.7663 + contain any revision newer than the one the tag refers to, 1.7664 + including the revision where the tag was created</emphasis>. 1.7665 + The result is that you'll get exactly the right subset of the 1.7666 + project's history in the new repository, but 1.7667 + <emphasis>not</emphasis> the tag you might have 1.7668 + expected.</para> 1.7669 + </sect2> 1.7670 + 1.7671 + <sect2> 1.7672 + <title>When permanent tags are too much</title> 1.7673 + 1.7674 + <para id="x_382">Since Mercurial's tags are revision controlled and carried 1.7675 + around with a project's history, everyone you work with will 1.7676 + see the tags you create. But giving names to revisions has 1.7677 + uses beyond simply noting that revision 1.7678 + <literal moreinfo="none">4237e45506ee</literal> is really 1.7679 + <literal moreinfo="none">v2.0.2</literal>. If you're trying to track down a 1.7680 + subtle bug, you might want a tag to remind you of something 1.7681 + like <quote>Anne saw the symptoms with this 1.7682 + revision</quote>.</para> 1.7683 + 1.7684 + <para id="x_383">For cases like this, what you might want to use are 1.7685 + <emphasis>local</emphasis> tags. You can create a local tag 1.7686 + with the <option role="hg-opt-tag">-l</option> option to the 1.7687 + <command role="hg-cmd" moreinfo="none">hg tag</command> command. This will 1.7688 + 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 1.7689 + controlled. Any tags you create using <option role="hg-opt-tag">-l</option> remain strictly local to the 1.7690 + repository you're currently working in.</para> 1.7691 + </sect2> 1.7692 + </sect1> 1.7693 + 1.7694 + <sect1> 1.7695 + <title>The flow of changes—big picture vs. little</title> 1.7696 + 1.7697 + <para id="x_384">To return to the outline I sketched at the 1.7698 + beginning of the chapter, let's think about a project that has 1.7699 + multiple concurrent pieces of work under development at 1.7700 + once.</para> 1.7701 + 1.7702 + <para id="x_385">There might be a push for a new <quote>main</quote> release; 1.7703 + a new minor bugfix release to the last main release; and an 1.7704 + unexpected <quote>hot fix</quote> to an old release that is now 1.7705 + in maintenance mode.</para> 1.7706 + 1.7707 + <para id="x_386">The usual way people refer to these different concurrent 1.7708 + directions of development is as <quote>branches</quote>. 1.7709 + However, we've already seen numerous times that Mercurial treats 1.7710 + <emphasis>all of history</emphasis> as a series of branches and 1.7711 + merges. Really, what we have here is two ideas that are 1.7712 + peripherally related, but which happen to share a name.</para> 1.7713 + <itemizedlist> 1.7714 + <listitem><para id="x_387"><quote>Big picture</quote> branches represent 1.7715 + the sweep of a project's evolution; people give them names, 1.7716 + and talk about them in conversation.</para> 1.7717 + </listitem> 1.7718 + <listitem><para id="x_388"><quote>Little picture</quote> branches are 1.7719 + artefacts of the day-to-day activity of developing and 1.7720 + merging changes. They expose the narrative of how the code 1.7721 + was developed.</para> 1.7722 + </listitem></itemizedlist> 1.7723 + </sect1> 1.7724 + 1.7725 + <sect1> 1.7726 + <title>Managing big-picture branches in repositories</title> 1.7727 + 1.7728 + <para id="x_389">The easiest way to isolate a <quote>big picture</quote> 1.7729 + branch in Mercurial is in a dedicated repository. If you have 1.7730 + an existing shared repository—let's call it 1.7731 + <literal moreinfo="none">myproject</literal>—that reaches a 1.7732 + <quote>1.0</quote> milestone, you can start to prepare for 1.7733 + future maintenance releases on top of version 1.0 by tagging the 1.7734 + revision from which you prepared the 1.0 release.</para> 1.7735 + 1.7736 + <!-- BEGIN branch-repo.tag --> 1.7737 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput> 1.7738 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput> 1.7739 +</screen> 1.7740 +<!-- END branch-repo.tag --> 1.7741 + 1.7742 + 1.7743 + <para id="x_38a">You can then clone a new shared 1.7744 + <literal moreinfo="none">myproject-1.0.1</literal> repository as of that 1.7745 + tag.</para> 1.7746 + 1.7747 + <!-- BEGIN branch-repo.clone --> 1.7748 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.7749 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-1.0.1</userinput> 1.7750 +updating working directory 1.7751 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.7752 +</screen> 1.7753 +<!-- END branch-repo.clone --> 1.7754 + 1.7755 + 1.7756 + <para id="x_38b">Afterwards, if someone needs to work on a bug fix that ought 1.7757 + to go into an upcoming 1.0.1 minor release, they clone the 1.7758 + <literal moreinfo="none">myproject-1.0.1</literal> repository, make their 1.7759 + changes, and push them back.</para> 1.7760 + 1.7761 + <!-- BEGIN branch-repo.bugfix --> 1.7762 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject-1.0.1 my-1.0.1-bugfix</userinput> 1.7763 +updating working directory 1.7764 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.7765 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-1.0.1-bugfix</userinput> 1.7766 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'I fixed a bug using only echo!' >> myfile</userinput> 1.7767 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Important fix for 1.0.1'</userinput> 1.7768 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> 1.7769 +pushing to /tmp/branch-repo3rVLLS/myproject-1.0.1 1.7770 +searching for changes 1.7771 +adding changesets 1.7772 +adding manifests 1.7773 +adding file changes 1.7774 +added 1 changesets with 1 changes to 1 files 1.7775 +</screen> 1.7776 +<!-- END branch-repo.bugfix --> 1.7777 + 1.7778 + 1.7779 + <para id="x_38c">Meanwhile, development for 1.7780 + the next major release can continue, isolated and unabated, in 1.7781 + the <literal moreinfo="none">myproject</literal> repository.</para> 1.7782 + 1.7783 + <!-- BEGIN branch-repo.new --> 1.7784 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.7785 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject my-feature</userinput> 1.7786 +updating working directory 1.7787 +2 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.7788 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-feature</userinput> 1.7789 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This sure is an exciting new feature!' > mynewfile</userinput> 1.7790 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New feature'</userinput> 1.7791 +adding mynewfile 1.7792 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> 1.7793 +pushing to /tmp/branch-repo3rVLLS/myproject 1.7794 +searching for changes 1.7795 +adding changesets 1.7796 +adding manifests 1.7797 +adding file changes 1.7798 +added 1 changesets with 1 changes to 1 files 1.7799 +</screen> 1.7800 +<!-- END branch-repo.new --> 1.7801 + 1.7802 + </sect1> 1.7803 + 1.7804 + <sect1> 1.7805 + <title>Don't repeat yourself: merging across branches</title> 1.7806 + 1.7807 + <para id="x_38d">In many cases, if you have a bug to fix on a maintenance 1.7808 + branch, the chances are good that the bug exists on your 1.7809 + project's main branch (and possibly other maintenance branches, 1.7810 + too). It's a rare developer who wants to fix the same bug 1.7811 + multiple times, so let's look at a few ways that Mercurial can 1.7812 + help you to manage these bugfixes without duplicating your 1.7813 + work.</para> 1.7814 + 1.7815 + <para id="x_38e">In the simplest instance, all you need to do is pull changes 1.7816 + from your maintenance branch into your local clone of the target 1.7817 + branch.</para> 1.7818 + 1.7819 + <!-- BEGIN branch-repo.pull --> 1.7820 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.7821 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-merge</userinput> 1.7822 +updating working directory 1.7823 +3 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.7824 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject-merge</userinput> 1.7825 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../myproject-1.0.1</userinput> 1.7826 +pulling from ../myproject-1.0.1 1.7827 +searching for changes 1.7828 +adding changesets 1.7829 +adding manifests 1.7830 +adding file changes 1.7831 +added 1 changesets with 1 changes to 1 files (+1 heads) 1.7832 +(run 'hg heads' to see heads, 'hg merge' to merge) 1.7833 +</screen> 1.7834 +<!-- END branch-repo.pull --> 1.7835 + 1.7836 + 1.7837 + <para id="x_38f">You'll then need to merge the heads of the two branches, and 1.7838 + push back to the main branch.</para> 1.7839 + 1.7840 + <!-- BEGIN branch-repo.merge --> 1.7841 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.7842 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.7843 +(branch merge, don't forget to commit) 1.7844 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge bugfix from 1.0.1 branch'</userinput> 1.7845 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> 1.7846 +pushing to /tmp/branch-repo3rVLLS/myproject 1.7847 +searching for changes 1.7848 +adding changesets 1.7849 +adding manifests 1.7850 +adding file changes 1.7851 +added 2 changesets with 1 changes to 1 files 1.7852 +</screen> 1.7853 +<!-- END branch-repo.merge --> 1.7854 + 1.7855 + </sect1> 1.7856 + 1.7857 + <sect1> 1.7858 + <title>Naming branches within one repository</title> 1.7859 + 1.7860 + <para id="x_390">In most instances, isolating branches in repositories is the 1.7861 + right approach. Its simplicity makes it easy to understand; and 1.7862 + so it's hard to make mistakes. There's a one-to-one 1.7863 + relationship between branches you're working in and directories 1.7864 + on your system. This lets you use normal (non-Mercurial-aware) 1.7865 + tools to work on files within a branch/repository.</para> 1.7866 + 1.7867 + <para id="x_391">If you're more in the <quote>power user</quote> category 1.7868 + (<emphasis>and</emphasis> your collaborators are too), there is 1.7869 + an alternative way of handling branches that you can consider. 1.7870 + I've already mentioned the human-level distinction between 1.7871 + <quote>small picture</quote> and <quote>big picture</quote> 1.7872 + branches. While Mercurial works with multiple <quote>small 1.7873 + picture</quote> branches in a repository all the time (for 1.7874 + example after you pull changes in, but before you merge them), 1.7875 + it can <emphasis>also</emphasis> work with multiple <quote>big 1.7876 + picture</quote> branches.</para> 1.7877 + 1.7878 + <para id="x_392">The key to working this way is that Mercurial lets you 1.7879 + assign a persistent <emphasis>name</emphasis> to a branch. 1.7880 + There always exists a branch named <literal moreinfo="none">default</literal>. 1.7881 + Even before you start naming branches yourself, you can find 1.7882 + traces of the <literal moreinfo="none">default</literal> branch if you look for 1.7883 + them.</para> 1.7884 + 1.7885 + <para id="x_393">As an example, when you run the <command role="hg-cmd" moreinfo="none">hg 1.7886 + commit</command> command, and it pops up your editor so that 1.7887 + you can enter a commit message, look for a line that contains 1.7888 + the text <quote><literal moreinfo="none">HG: branch default</literal></quote> at 1.7889 + the bottom. This is telling you that your commit will occur on 1.7890 + the branch named <literal moreinfo="none">default</literal>.</para> 1.7891 + 1.7892 + <para id="x_394">To start working with named branches, use the <command role="hg-cmd" moreinfo="none">hg branches</command> command. This command 1.7893 + lists the named branches already present in your repository, 1.7894 + telling you which changeset is the tip of each.</para> 1.7895 + 1.7896 + <!-- BEGIN branch-named.branches --> 1.7897 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.7898 +changeset: 0:90897f9e54e3 1.7899 +tag: tip 1.7900 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7901 +date: Sun Aug 16 14:04:42 2009 +0000 1.7902 +summary: Initial commit 1.7903 + 1.7904 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput> 1.7905 +default 0:90897f9e54e3 1.7906 +</screen> 1.7907 +<!-- END branch-named.branches --> 1.7908 + 1.7909 + 1.7910 + <para id="x_395">Since you haven't created any named branches yet, the only 1.7911 + one that exists is <literal moreinfo="none">default</literal>.</para> 1.7912 + 1.7913 + <para id="x_396">To find out what the <quote>current</quote> branch is, run 1.7914 + the <command role="hg-cmd" moreinfo="none">hg branch</command> command, giving 1.7915 + it no arguments. This tells you what branch the parent of the 1.7916 + current changeset is on.</para> 1.7917 + 1.7918 + <!-- BEGIN branch-named.branch --> 1.7919 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> 1.7920 +default 1.7921 +</screen> 1.7922 +<!-- END branch-named.branch --> 1.7923 + 1.7924 + 1.7925 + <para id="x_397">To create a new branch, run the <command role="hg-cmd" moreinfo="none">hg 1.7926 + branch</command> command again. This time, give it one 1.7927 + argument: the name of the branch you want to create.</para> 1.7928 + 1.7929 + <!-- BEGIN branch-named.create --> 1.7930 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch foo</userinput> 1.7931 +marked working directory as branch foo 1.7932 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> 1.7933 +foo 1.7934 +</screen> 1.7935 +<!-- END branch-named.create --> 1.7936 + 1.7937 + 1.7938 + <para id="x_398">After you've created a branch, you might wonder what effect 1.7939 + the <command role="hg-cmd" moreinfo="none">hg branch</command> command has had. 1.7940 + What do the <command role="hg-cmd" moreinfo="none">hg status</command> and 1.7941 + <command role="hg-cmd" moreinfo="none">hg tip</command> commands report?</para> 1.7942 + 1.7943 + <!-- BEGIN branch-named.status --> 1.7944 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.7945 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.7946 +changeset: 0:90897f9e54e3 1.7947 +tag: tip 1.7948 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7949 +date: Sun Aug 16 14:04:42 2009 +0000 1.7950 +summary: Initial commit 1.7951 + 1.7952 +</screen> 1.7953 +<!-- END branch-named.status --> 1.7954 + 1.7955 + 1.7956 + <para id="x_399">Nothing has changed in the 1.7957 + working directory, and there's been no new history created. As 1.7958 + this suggests, running the <command role="hg-cmd" moreinfo="none">hg 1.7959 + branch</command> command has no permanent effect; it only 1.7960 + tells Mercurial what branch name to use the 1.7961 + <emphasis>next</emphasis> time you commit a changeset.</para> 1.7962 + 1.7963 + <para id="x_39a">When you commit a change, Mercurial records the name of the 1.7964 + branch on which you committed. Once you've switched from the 1.7965 + <literal moreinfo="none">default</literal> branch to another and committed, 1.7966 + you'll see the name of the new branch show up in the output of 1.7967 + <command role="hg-cmd" moreinfo="none">hg log</command>, <command role="hg-cmd" moreinfo="none">hg tip</command>, and other commands that 1.7968 + display the same kind of output.</para> 1.7969 + 1.7970 + <!-- BEGIN branch-named.commit --> 1.7971 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'hello again' >> myfile</userinput> 1.7972 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Second commit'</userinput> 1.7973 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.7974 +changeset: 1:5656f8ffdd49 1.7975 +branch: foo 1.7976 +tag: tip 1.7977 +user: Bryan O'Sullivan <bos@serpentine.com> 1.7978 +date: Sun Aug 16 14:04:42 2009 +0000 1.7979 +summary: Second commit 1.7980 + 1.7981 +</screen> 1.7982 +<!-- END branch-named.commit --> 1.7983 + 1.7984 + 1.7985 + <para id="x_39b">The <command role="hg-cmd" moreinfo="none">hg log</command>-like commands 1.7986 + will print the branch name of every changeset that's not on the 1.7987 + <literal moreinfo="none">default</literal> branch. As a result, if you never 1.7988 + use named branches, you'll never see this information.</para> 1.7989 + 1.7990 + <para id="x_39c">Once you've named a branch and committed a change with that 1.7991 + name, every subsequent commit that descends from that change 1.7992 + will inherit the same branch name. You can change the name of a 1.7993 + branch at any time, using the <command role="hg-cmd" moreinfo="none">hg 1.7994 + branch</command> command.</para> 1.7995 + 1.7996 + <!-- BEGIN branch-named.rebranch --> 1.7997 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> 1.7998 +foo 1.7999 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch bar</userinput> 1.8000 +marked working directory as branch bar 1.8001 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo new file > newfile</userinput> 1.8002 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Third commit'</userinput> 1.8003 +adding newfile 1.8004 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.8005 +changeset: 2:c59d680fc2ec 1.8006 +branch: bar 1.8007 +tag: tip 1.8008 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8009 +date: Sun Aug 16 14:04:42 2009 +0000 1.8010 +summary: Third commit 1.8011 + 1.8012 +</screen> 1.8013 +<!-- END branch-named.rebranch --> 1.8014 + 1.8015 + 1.8016 + <para id="x_39d">In practice, this is something you won't do very often, as 1.8017 + branch names tend to have fairly long lifetimes. (This isn't a 1.8018 + rule, just an observation.)</para> 1.8019 + </sect1> 1.8020 + 1.8021 + <sect1> 1.8022 + <title>Dealing with multiple named branches in a 1.8023 + repository</title> 1.8024 + 1.8025 + <para id="x_39e">If you have more than one named branch in a repository, 1.8026 + Mercurial will remember the branch that your working directory 1.8027 + is on when you start a command like <command role="hg-cmd" moreinfo="none">hg 1.8028 + update</command> or <command role="hg-cmd" moreinfo="none">hg pull 1.8029 + -u</command>. It will update the working directory to the tip 1.8030 + of this branch, no matter what the <quote>repo-wide</quote> tip 1.8031 + is. To update to a revision that's on a different named branch, 1.8032 + you may need to use the <option role="hg-opt-update">-C</option> 1.8033 + option to <command role="hg-cmd" moreinfo="none">hg update</command>.</para> 1.8034 + 1.8035 + <para id="x_39f">This behavior is a little subtle, so let's see it in 1.8036 + action. First, let's remind ourselves what branch we're 1.8037 + currently on, and what branches are in our repository.</para> 1.8038 + 1.8039 + <!-- BEGIN branch-named.parents --> 1.8040 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.8041 +changeset: 2:c59d680fc2ec 1.8042 +branch: bar 1.8043 +tag: tip 1.8044 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8045 +date: Sun Aug 16 14:04:42 2009 +0000 1.8046 +summary: Third commit 1.8047 + 1.8048 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput> 1.8049 +bar 2:c59d680fc2ec 1.8050 +foo 1:5656f8ffdd49 (inactive) 1.8051 +default 0:90897f9e54e3 (inactive) 1.8052 +</screen> 1.8053 +<!-- END branch-named.parents --> 1.8054 + 1.8055 + 1.8056 + <para id="x_3a0">We're on the <literal moreinfo="none">bar</literal> branch, but there also 1.8057 + exists an older <command role="hg-cmd" moreinfo="none">hg foo</command> 1.8058 + branch.</para> 1.8059 + 1.8060 + <para id="x_3a1">We can <command role="hg-cmd" moreinfo="none">hg update</command> back and 1.8061 + forth between the tips of the <literal moreinfo="none">foo</literal> and 1.8062 + <literal moreinfo="none">bar</literal> branches without needing to use the 1.8063 + <option role="hg-opt-update">-C</option> option, because this 1.8064 + only involves going backwards and forwards linearly through our 1.8065 + change history.</para> 1.8066 + 1.8067 + <!-- BEGIN branch-named.update-switchy --> 1.8068 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput> 1.8069 +0 files updated, 0 files merged, 1 files removed, 0 files unresolved 1.8070 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.8071 +changeset: 1:5656f8ffdd49 1.8072 +branch: foo 1.8073 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8074 +date: Sun Aug 16 14:04:42 2009 +0000 1.8075 +summary: Second commit 1.8076 + 1.8077 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update bar</userinput> 1.8078 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.8079 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.8080 +changeset: 2:c59d680fc2ec 1.8081 +branch: bar 1.8082 +tag: tip 1.8083 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8084 +date: Sun Aug 16 14:04:42 2009 +0000 1.8085 +summary: Third commit 1.8086 + 1.8087 +</screen> 1.8088 +<!-- END branch-named.update-switchy --> 1.8089 + 1.8090 + 1.8091 + <para id="x_3a2">If we go back to the <literal moreinfo="none">foo</literal> branch and then 1.8092 + run <command role="hg-cmd" moreinfo="none">hg update</command>, it will keep us 1.8093 + on <literal moreinfo="none">foo</literal>, not move us to the tip of 1.8094 + <literal moreinfo="none">bar</literal>.</para> 1.8095 + 1.8096 + <!-- BEGIN branch-named.update-nothing --> 1.8097 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput> 1.8098 +0 files updated, 0 files merged, 1 files removed, 0 files unresolved 1.8099 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput> 1.8100 +0 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.8101 +</screen> 1.8102 +<!-- END branch-named.update-nothing --> 1.8103 + 1.8104 + 1.8105 + <para id="x_3a3">Committing a new change on the <literal moreinfo="none">foo</literal> branch 1.8106 + introduces a new head.</para> 1.8107 + 1.8108 + <!-- BEGIN branch-named.foo-commit --> 1.8109 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo something > somefile</userinput> 1.8110 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New file'</userinput> 1.8111 +adding somefile 1.8112 +created new head 1.8113 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> 1.8114 +changeset: 3:4dd2f7a37288 1.8115 +branch: foo 1.8116 +tag: tip 1.8117 +parent: 1:5656f8ffdd49 1.8118 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8119 +date: Sun Aug 16 14:04:43 2009 +0000 1.8120 +summary: New file 1.8121 + 1.8122 +changeset: 2:c59d680fc2ec 1.8123 +branch: bar 1.8124 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8125 +date: Sun Aug 16 14:04:42 2009 +0000 1.8126 +summary: Third commit 1.8127 + 1.8128 +</screen> 1.8129 +<!-- END branch-named.foo-commit --> 1.8130 + 1.8131 + </sect1> 1.8132 + 1.8133 + <sect1> 1.8134 + <title>Branch names and merging</title> 1.8135 + 1.8136 + <para id="x_3a4">As you've probably noticed, merges in Mercurial are not 1.8137 + symmetrical. Let's say our repository has two heads, 17 and 23. 1.8138 + If I <command role="hg-cmd" moreinfo="none">hg update</command> to 17 and then 1.8139 + <command role="hg-cmd" moreinfo="none">hg merge</command> with 23, Mercurial 1.8140 + records 17 as the first parent of the merge, and 23 as the 1.8141 + second. Whereas if I <command role="hg-cmd" moreinfo="none">hg update</command> 1.8142 + to 23 and then <command role="hg-cmd" moreinfo="none">hg merge</command> with 1.8143 + 17, it records 23 as the first parent, and 17 as the 1.8144 + second.</para> 1.8145 + 1.8146 + <para id="x_3a5">This affects Mercurial's choice of branch name when you 1.8147 + merge. After a merge, Mercurial will retain the branch name of 1.8148 + the first parent when you commit the result of the merge. If 1.8149 + your first parent's branch name is <literal moreinfo="none">foo</literal>, and 1.8150 + you merge with <literal moreinfo="none">bar</literal>, the branch name will 1.8151 + still be <literal moreinfo="none">foo</literal> after you merge.</para> 1.8152 + 1.8153 + <para id="x_3a6">It's not unusual for a repository to contain multiple heads, 1.8154 + each with the same branch name. Let's say I'm working on the 1.8155 + <literal moreinfo="none">foo</literal> branch, and so are you. We commit 1.8156 + different changes; I pull your changes; I now have two heads, 1.8157 + each claiming to be on the <literal moreinfo="none">foo</literal> branch. The 1.8158 + result of a merge will be a single head on the 1.8159 + <literal moreinfo="none">foo</literal> branch, as you might hope.</para> 1.8160 + 1.8161 + <para id="x_3a7">But if I'm working on the <literal moreinfo="none">bar</literal> branch, and 1.8162 + I merge work from the <literal moreinfo="none">foo</literal> branch, the result 1.8163 + will remain on the <literal moreinfo="none">bar</literal> branch.</para> 1.8164 + 1.8165 + <!-- BEGIN branch-named.merge --> 1.8166 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> 1.8167 +bar 1.8168 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge foo</userinput> 1.8169 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.8170 +(branch merge, don't forget to commit) 1.8171 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge'</userinput> 1.8172 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.8173 +changeset: 4:9f05d4ef3efe 1.8174 +branch: bar 1.8175 +tag: tip 1.8176 +parent: 2:c59d680fc2ec 1.8177 +parent: 3:4dd2f7a37288 1.8178 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8179 +date: Sun Aug 16 14:04:44 2009 +0000 1.8180 +summary: Merge 1.8181 + 1.8182 +</screen> 1.8183 +<!-- END branch-named.merge --> 1.8184 + 1.8185 + 1.8186 + <para id="x_3a8">To give a more concrete example, if I'm working on the 1.8187 + <literal moreinfo="none">bleeding-edge</literal> branch, and I want to bring in 1.8188 + the latest fixes from the <literal moreinfo="none">stable</literal> branch, 1.8189 + Mercurial will choose the <quote>right</quote> 1.8190 + (<literal moreinfo="none">bleeding-edge</literal>) branch name when I pull and 1.8191 + merge from <literal moreinfo="none">stable</literal>.</para> 1.8192 + </sect1> 1.8193 + 1.8194 + <sect1> 1.8195 + <title>Branch naming is generally useful</title> 1.8196 + 1.8197 + <para id="x_3a9">You shouldn't think of named branches as applicable only to 1.8198 + situations where you have multiple long-lived branches 1.8199 + cohabiting in a single repository. They're very useful even in 1.8200 + the one-branch-per-repository case.</para> 1.8201 + 1.8202 + <para id="x_3aa">In the simplest case, giving a name to each branch gives you 1.8203 + a permanent record of which branch a changeset originated on. 1.8204 + This gives you more context when you're trying to follow the 1.8205 + history of a long-lived branchy project.</para> 1.8206 + 1.8207 + <para id="x_3ab">If you're working with shared repositories, you can set up a 1.8208 + <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook on each 1.8209 + that will block incoming changes that have the 1.8210 + <quote>wrong</quote> branch name. This provides a simple, but 1.8211 + effective, defence against people accidentally pushing changes 1.8212 + from a <quote>bleeding edge</quote> branch to a 1.8213 + <quote>stable</quote> branch. Such a hook might look like this 1.8214 + inside the shared repo's <filename role="special" moreinfo="none"> 1.8215 + /.hgrc</filename>.</para> 1.8216 + <programlisting format="linespecific">[hooks] 1.8217 +pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting> 1.8218 + </sect1> 1.8219 +</chapter> 1.8220 + 1.8221 +<!-- 1.8222 +local variables: 1.8223 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.8224 +end: 1.8225 +--> 1.8226 + 1.8227 + <!-- BEGIN ch09 --> 1.8228 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.8229 + 1.8230 +<chapter id="chap:undo"> 1.8231 + <?dbhtml filename="finding-and-fixing-mistakes.html"?> 1.8232 + <title>Finding and fixing mistakes</title> 1.8233 + 1.8234 + <para id="x_d2">To err might be human, but to really handle the consequences 1.8235 + well takes a top-notch revision control system. In this chapter, 1.8236 + we'll discuss some of the techniques you can use when you find 1.8237 + that a problem has crept into your project. Mercurial has some 1.8238 + highly capable features that will help you to isolate the sources 1.8239 + of problems, and to handle them appropriately.</para> 1.8240 + 1.8241 + <sect1> 1.8242 + <title>Erasing local history</title> 1.8243 + 1.8244 + <sect2> 1.8245 + <title>The accidental commit</title> 1.8246 + 1.8247 + <para id="x_d3">I have the occasional but persistent problem of typing 1.8248 + rather more quickly than I can think, which sometimes results 1.8249 + in me committing a changeset that is either incomplete or 1.8250 + plain wrong. In my case, the usual kind of incomplete 1.8251 + changeset is one in which I've created a new source file, but 1.8252 + forgotten to <command role="hg-cmd" moreinfo="none">hg add</command> it. A 1.8253 + <quote>plain wrong</quote> changeset is not as common, but no 1.8254 + less annoying.</para> 1.8255 + 1.8256 + </sect2> 1.8257 + <sect2 id="sec:undo:rollback"> 1.8258 + <title>Rolling back a transaction</title> 1.8259 + 1.8260 + <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I 1.8261 + mentioned that Mercurial treats each modification of a 1.8262 + repository as a <emphasis>transaction</emphasis>. Every time 1.8263 + you commit a changeset or pull changes from another 1.8264 + repository, Mercurial remembers what you did. You can undo, 1.8265 + or <emphasis>roll back</emphasis>, exactly one of these 1.8266 + actions using the <command role="hg-cmd" moreinfo="none">hg rollback</command> 1.8267 + command. (See <xref linkend="sec:undo:rollback-after-push"/> 1.8268 + for an important caveat about the use of this command.)</para> 1.8269 + 1.8270 + <para id="x_d5">Here's a mistake that I often find myself making: 1.8271 + committing a change in which I've created a new file, but 1.8272 + forgotten to <command role="hg-cmd" moreinfo="none">hg add</command> 1.8273 + it.</para> 1.8274 + 1.8275 + <!-- BEGIN rollback.commit --> 1.8276 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8277 +M a 1.8278 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b</userinput> 1.8279 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b'</userinput> 1.8280 +</screen> 1.8281 +<!-- END rollback.commit --> 1.8282 + 1.8283 + 1.8284 + <para id="x_d6">Looking at the output of <command role="hg-cmd" moreinfo="none">hg 1.8285 + status</command> after the commit immediately confirms the 1.8286 + error.</para> 1.8287 + 1.8288 + <!-- BEGIN rollback.status --> 1.8289 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8290 +? b 1.8291 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.8292 +changeset: 1:246e2aada1c5 1.8293 +tag: tip 1.8294 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8295 +date: Sun Aug 16 14:05:14 2009 +0000 1.8296 +summary: Add file b 1.8297 + 1.8298 +</screen> 1.8299 +<!-- END rollback.status --> 1.8300 + 1.8301 + 1.8302 + <para id="x_d7">The commit captured the changes to the file 1.8303 + <filename moreinfo="none">a</filename>, but not the new file 1.8304 + <filename moreinfo="none">b</filename>. If I were to push this changeset to a 1.8305 + repository that I shared with a colleague, the chances are 1.8306 + high that something in <filename moreinfo="none">a</filename> would refer to 1.8307 + <filename moreinfo="none">b</filename>, which would not be present in their 1.8308 + repository when they pulled my changes. I would thus become 1.8309 + the object of some indignation.</para> 1.8310 + 1.8311 + <para id="x_d8">However, luck is with me—I've caught my error 1.8312 + before I pushed the changeset. I use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, and Mercurial 1.8313 + makes that last changeset vanish.</para> 1.8314 + 1.8315 + <!-- BEGIN rollback.rollback --> 1.8316 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput> 1.8317 +rolling back last transaction 1.8318 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.8319 +changeset: 0:c37ce4157509 1.8320 +tag: tip 1.8321 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8322 +date: Sun Aug 16 14:05:14 2009 +0000 1.8323 +summary: First commit 1.8324 + 1.8325 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8326 +M a 1.8327 +? b 1.8328 +</screen> 1.8329 +<!-- END rollback.rollback --> 1.8330 + 1.8331 + 1.8332 + <para id="x_d9">Notice that the changeset is no longer present in the 1.8333 + repository's history, and the working directory once again 1.8334 + thinks that the file <filename moreinfo="none">a</filename> is modified. The 1.8335 + commit and rollback have left the working directory exactly as 1.8336 + it was prior to the commit; the changeset has been completely 1.8337 + erased. I can now safely <command role="hg-cmd" moreinfo="none">hg 1.8338 + add</command> the file <filename moreinfo="none">b</filename>, and rerun my 1.8339 + commit.</para> 1.8340 + 1.8341 + <!-- BEGIN rollback.add --> 1.8342 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput> 1.8343 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b, this time for real'</userinput> 1.8344 +</screen> 1.8345 +<!-- END rollback.add --> 1.8346 + 1.8347 + 1.8348 + </sect2> 1.8349 + <sect2> 1.8350 + <title>The erroneous pull</title> 1.8351 + 1.8352 + <para id="x_da">It's common practice with Mercurial to maintain separate 1.8353 + development branches of a project in different repositories. 1.8354 + Your development team might have one shared repository for 1.8355 + your project's <quote>0.9</quote> release, and another, 1.8356 + containing different changes, for the <quote>1.0</quote> 1.8357 + release.</para> 1.8358 + 1.8359 + <para id="x_db">Given this, you can imagine that the consequences could be 1.8360 + messy if you had a local <quote>0.9</quote> repository, and 1.8361 + accidentally pulled changes from the shared <quote>1.0</quote> 1.8362 + repository into it. At worst, you could be paying 1.8363 + insufficient attention, and push those changes into the shared 1.8364 + <quote>0.9</quote> tree, confusing your entire team (but don't 1.8365 + worry, we'll return to this horror scenario later). However, 1.8366 + it's more likely that you'll notice immediately, because 1.8367 + Mercurial will display the URL it's pulling from, or you will 1.8368 + see it pull a suspiciously large number of changes into the 1.8369 + repository.</para> 1.8370 + 1.8371 + <para id="x_dc">The <command role="hg-cmd" moreinfo="none">hg rollback</command> command 1.8372 + will work nicely to expunge all of the changesets that you 1.8373 + just pulled. Mercurial groups all changes from one <command role="hg-cmd" moreinfo="none">hg pull</command> into a single transaction, 1.8374 + so one <command role="hg-cmd" moreinfo="none">hg rollback</command> is all you 1.8375 + need to undo this mistake.</para> 1.8376 + 1.8377 + </sect2> 1.8378 + <sect2 id="sec:undo:rollback-after-push"> 1.8379 + <title>Rolling back is useless once you've pushed</title> 1.8380 + 1.8381 + <para id="x_dd">The value of the <command role="hg-cmd" moreinfo="none">hg 1.8382 + rollback</command> command drops to zero once you've pushed 1.8383 + your changes to another repository. Rolling back a change 1.8384 + makes it disappear entirely, but <emphasis>only</emphasis> in 1.8385 + the repository in which you perform the <command role="hg-cmd" moreinfo="none">hg rollback</command>. Because a rollback 1.8386 + eliminates history, there's no way for the disappearance of a 1.8387 + change to propagate between repositories.</para> 1.8388 + 1.8389 + <para id="x_de">If you've pushed a change to another 1.8390 + repository—particularly if it's a shared 1.8391 + repository—it has essentially <quote>escaped into the 1.8392 + wild,</quote> and you'll have to recover from your mistake 1.8393 + in a different way. If you push a changeset somewhere, then 1.8394 + roll it back, then pull from the repository you pushed to, the 1.8395 + changeset you thought you'd gotten rid of will simply reappear 1.8396 + in your repository.</para> 1.8397 + 1.8398 + <para id="x_df">(If you absolutely know for sure that the change 1.8399 + you want to roll back is the most recent change in the 1.8400 + repository that you pushed to, <emphasis>and</emphasis> you 1.8401 + know that nobody else could have pulled it from that 1.8402 + repository, you can roll back the changeset there, too, but 1.8403 + you really should not expect this to work reliably. Sooner or 1.8404 + later a change really will make it into a repository that you 1.8405 + don't directly control (or have forgotten about), and come 1.8406 + back to bite you.)</para> 1.8407 + 1.8408 + </sect2> 1.8409 + <sect2> 1.8410 + <title>You can only roll back once</title> 1.8411 + 1.8412 + <para id="x_e0">Mercurial stores exactly one transaction in its 1.8413 + transaction log; that transaction is the most recent one that 1.8414 + occurred in the repository. This means that you can only roll 1.8415 + back one transaction. If you expect to be able to roll back 1.8416 + one transaction, then its predecessor, this is not the 1.8417 + behavior you will get.</para> 1.8418 + 1.8419 + <!-- BEGIN rollback.twice --> 1.8420 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput> 1.8421 +rolling back last transaction 1.8422 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput> 1.8423 +no rollback information available 1.8424 +</screen> 1.8425 +<!-- END rollback.twice --> 1.8426 + 1.8427 + 1.8428 + <para id="x_e1">Once you've rolled back one transaction in a repository, 1.8429 + you can't roll back again in that repository until you perform 1.8430 + another commit or pull.</para> 1.8431 + 1.8432 + </sect2> 1.8433 + </sect1> 1.8434 + <sect1> 1.8435 + <title>Reverting the mistaken change</title> 1.8436 + 1.8437 + <para id="x_e2">If you make a modification to a file, and decide that you 1.8438 + really didn't want to change the file at all, and you haven't 1.8439 + yet committed your changes, the <command role="hg-cmd" moreinfo="none">hg 1.8440 + revert</command> command is the one you'll need. It looks at 1.8441 + the changeset that's the parent of the working directory, and 1.8442 + restores the contents of the file to their state as of that 1.8443 + changeset. (That's a long-winded way of saying that, in the 1.8444 + normal case, it undoes your modifications.)</para> 1.8445 + 1.8446 + <para id="x_e3">Let's illustrate how the <command role="hg-cmd" moreinfo="none">hg 1.8447 + revert</command> command works with yet another small example. 1.8448 + We'll begin by modifying a file that Mercurial is already 1.8449 + tracking.</para> 1.8450 + 1.8451 + <!-- BEGIN daily.revert.modify --> 1.8452 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput> 1.8453 +original content 1.8454 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo unwanted change >> file</userinput> 1.8455 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff file</userinput> 1.8456 +diff -r 2eacf948d309 file 1.8457 +--- a/file Sun Aug 16 14:05:00 2009 +0000 1.8458 ++++ b/file Sun Aug 16 14:05:00 2009 +0000 1.8459 +@@ -1,1 +1,2 @@ 1.8460 + original content 1.8461 ++unwanted change 1.8462 +</screen> 1.8463 +<!-- END daily.revert.modify --> 1.8464 + 1.8465 + 1.8466 + <para id="x_e4">If we don't 1.8467 + want that change, we can simply <command role="hg-cmd" moreinfo="none">hg 1.8468 + revert</command> the file.</para> 1.8469 + 1.8470 + <!-- BEGIN daily.revert.unmodify --> 1.8471 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8472 +M file 1.8473 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput> 1.8474 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput> 1.8475 +original content 1.8476 +</screen> 1.8477 +<!-- END daily.revert.unmodify --> 1.8478 + 1.8479 + 1.8480 + <para id="x_e5">The <command role="hg-cmd" moreinfo="none">hg revert</command> command 1.8481 + provides us with an extra degree of safety by saving our 1.8482 + modified file with a <filename moreinfo="none">.orig</filename> 1.8483 + extension.</para> 1.8484 + 1.8485 + <!-- BEGIN daily.revert.status --> 1.8486 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8487 +? file.orig 1.8488 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file.orig</userinput> 1.8489 +original content 1.8490 +unwanted change 1.8491 +</screen> 1.8492 +<!-- END daily.revert.status --> 1.8493 + 1.8494 + 1.8495 + <tip> 1.8496 + <title>Be careful with <filename moreinfo="none">.orig</filename> files</title> 1.8497 + 1.8498 + <para id="x_6b8">It's extremely unlikely that you are either using 1.8499 + Mercurial to manage files with <filename moreinfo="none">.orig</filename> 1.8500 + extensions or that you even care about the contents of such 1.8501 + files. Just in case, though, it's useful to remember that 1.8502 + <command role="hg-cmd" moreinfo="none">hg revert</command> will 1.8503 + unconditionally overwrite an existing file with a 1.8504 + <filename moreinfo="none">.orig</filename> extension. For instance, if you 1.8505 + already have a file named <filename moreinfo="none">foo.orig</filename> when 1.8506 + you revert <filename moreinfo="none">foo</filename>, the contents of 1.8507 + <filename moreinfo="none">foo.orig</filename> will be clobbered.</para> 1.8508 + </tip> 1.8509 + 1.8510 + <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 1.8511 + will describe each of these in more detail in the section that 1.8512 + follows.</para> 1.8513 + <itemizedlist> 1.8514 + <listitem><para id="x_e7">If you modify a file, it will restore the file 1.8515 + to its unmodified state.</para> 1.8516 + </listitem> 1.8517 + <listitem><para id="x_e8">If you <command role="hg-cmd" moreinfo="none">hg add</command> a 1.8518 + file, it will undo the <quote>added</quote> state of the 1.8519 + file, but leave the file itself untouched.</para> 1.8520 + </listitem> 1.8521 + <listitem><para id="x_e9">If you delete a file without telling Mercurial, 1.8522 + it will restore the file to its unmodified contents.</para> 1.8523 + </listitem> 1.8524 + <listitem><para id="x_ea">If you use the <command role="hg-cmd" moreinfo="none">hg 1.8525 + remove</command> command to remove a file, it will undo 1.8526 + the <quote>removed</quote> state of the file, and restore 1.8527 + the file to its unmodified contents.</para> 1.8528 + </listitem></itemizedlist> 1.8529 + 1.8530 + <sect2 id="sec:undo:mgmt"> 1.8531 + <title>File management errors</title> 1.8532 + 1.8533 + <para id="x_eb">The <command role="hg-cmd" moreinfo="none">hg revert</command> command is 1.8534 + useful for more than just modified files. It lets you reverse 1.8535 + the results of all of Mercurial's file management 1.8536 + commands—<command role="hg-cmd" moreinfo="none">hg add</command>, 1.8537 + <command role="hg-cmd" moreinfo="none">hg remove</command>, and so on.</para> 1.8538 + 1.8539 + <para id="x_ec">If you <command role="hg-cmd" moreinfo="none">hg add</command> a file, 1.8540 + then decide that in fact you don't want Mercurial to track it, 1.8541 + use <command role="hg-cmd" moreinfo="none">hg revert</command> to undo the 1.8542 + add. Don't worry; Mercurial will not modify the file in any 1.8543 + way. It will just <quote>unmark</quote> the file.</para> 1.8544 + 1.8545 + <!-- BEGIN daily.revert.add --> 1.8546 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo oops > oops</userinput> 1.8547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add oops</userinput> 1.8548 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status oops</userinput> 1.8549 +A oops 1.8550 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert oops</userinput> 1.8551 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8552 +? oops 1.8553 +</screen> 1.8554 +<!-- END daily.revert.add --> 1.8555 + 1.8556 + 1.8557 + <para id="x_ed">Similarly, if you ask Mercurial to <command role="hg-cmd" moreinfo="none">hg remove</command> a file, you can use 1.8558 + <command role="hg-cmd" moreinfo="none">hg revert</command> to restore it to 1.8559 + the contents it had as of the parent of the working directory. 1.8560 + <!-- BEGIN daily.revert.remove --> 1.8561 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove file</userinput> 1.8562 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8563 +R file 1.8564 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput> 1.8565 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8566 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput> 1.8567 +file 1.8568 +</screen> 1.8569 +<!-- END daily.revert.remove --> 1.8570 + This works just as 1.8571 + well for a file that you deleted by hand, without telling 1.8572 + Mercurial (recall that in Mercurial terminology, this kind of 1.8573 + file is called <quote>missing</quote>).</para> 1.8574 + 1.8575 + <!-- BEGIN daily.revert.missing --> 1.8576 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm file</userinput> 1.8577 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8578 +! file 1.8579 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput> 1.8580 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput> 1.8581 +file 1.8582 +</screen> 1.8583 +<!-- END daily.revert.missing --> 1.8584 + 1.8585 + 1.8586 + <para id="x_ee">If you revert a <command role="hg-cmd" moreinfo="none">hg copy</command>, 1.8587 + the copied-to file remains in your working directory 1.8588 + afterwards, untracked. Since a copy doesn't affect the 1.8589 + copied-from file in any way, Mercurial doesn't do anything 1.8590 + with the copied-from file.</para> 1.8591 + 1.8592 + <!-- BEGIN daily.revert.copy --> 1.8593 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput> 1.8594 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert new-file</userinput> 1.8595 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.8596 +? new-file 1.8597 +</screen> 1.8598 +<!-- END daily.revert.copy --> 1.8599 + 1.8600 + </sect2> 1.8601 + </sect1> 1.8602 + 1.8603 + <sect1> 1.8604 + <title>Dealing with committed changes</title> 1.8605 + 1.8606 + <para id="x_f5">Consider a case where you have committed a change 1.8607 + <emphasis>a</emphasis>, and another change 1.8608 + <emphasis>b</emphasis> on top of it; you then realise that 1.8609 + change <emphasis>a</emphasis> was incorrect. Mercurial lets you 1.8610 + <quote>back out</quote> an entire changeset automatically, and 1.8611 + building blocks that let you reverse part of a changeset by 1.8612 + hand.</para> 1.8613 + 1.8614 + <para id="x_f6">Before you read this section, here's something to 1.8615 + keep in mind: the <command role="hg-cmd" moreinfo="none">hg backout</command> 1.8616 + command undoes the effect of a change by 1.8617 + <emphasis>adding</emphasis> to your repository's history, not by 1.8618 + modifying or erasing it. It's the right tool to use if you're 1.8619 + fixing bugs, but not if you're trying to undo some change that 1.8620 + has catastrophic consequences. To deal with those, see 1.8621 + <xref linkend="sec:undo:aaaiiieee"/>.</para> 1.8622 + 1.8623 + <sect2> 1.8624 + <title>Backing out a changeset</title> 1.8625 + 1.8626 + <para id="x_f7">The <command role="hg-cmd" moreinfo="none">hg backout</command> command 1.8627 + lets you <quote>undo</quote> the effects of an entire 1.8628 + changeset in an automated fashion. Because Mercurial's 1.8629 + history is immutable, this command <emphasis>does 1.8630 + not</emphasis> get rid of the changeset you want to undo. 1.8631 + Instead, it creates a new changeset that 1.8632 + <emphasis>reverses</emphasis> the effect of the to-be-undone 1.8633 + changeset.</para> 1.8634 + 1.8635 + <para id="x_f8">The operation of the <command role="hg-cmd" moreinfo="none">hg 1.8636 + backout</command> command is a little intricate, so let's 1.8637 + illustrate it with some examples. First, we'll create a 1.8638 + repository with some simple changes.</para> 1.8639 + 1.8640 + <!-- BEGIN backout.init --> 1.8641 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput> 1.8642 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput> 1.8643 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first change >> myfile</userinput> 1.8644 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile</userinput> 1.8645 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'first change'</userinput> 1.8646 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo second change >> myfile</userinput> 1.8647 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'second change'</userinput> 1.8648 +</screen> 1.8649 +<!-- END backout.init --> 1.8650 + 1.8651 + 1.8652 + <para id="x_f9">The <command role="hg-cmd" moreinfo="none">hg backout</command> command 1.8653 + takes a single changeset ID as its argument; this is the 1.8654 + changeset to back out. Normally, <command role="hg-cmd" moreinfo="none">hg 1.8655 + backout</command> will drop you into a text editor to write 1.8656 + a commit message, so you can record why you're backing the 1.8657 + change out. In this example, we provide a commit message on 1.8658 + the command line using the <option role="hg-opt-backout">-m</option> option.</para> 1.8659 + 1.8660 + </sect2> 1.8661 + <sect2> 1.8662 + <title>Backing out the tip changeset</title> 1.8663 + 1.8664 + <para id="x_fa">We're going to start by backing out the last changeset we 1.8665 + committed.</para> 1.8666 + 1.8667 + <!-- BEGIN backout.simple --> 1.8668 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' tip</userinput> 1.8669 +reverting myfile 1.8670 +changeset 2:611a0cae251c backs out changeset 1:43700a9b3ec8 1.8671 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.8672 +first change 1.8673 +</screen> 1.8674 +<!-- END backout.simple --> 1.8675 + 1.8676 + 1.8677 + <para id="x_fb">You can see that the second line from 1.8678 + <filename moreinfo="none">myfile</filename> is no longer present. Taking a 1.8679 + look at the output of <command role="hg-cmd" moreinfo="none">hg log</command> 1.8680 + gives us an idea of what the <command role="hg-cmd" moreinfo="none">hg 1.8681 + backout</command> command has done. 1.8682 + <!-- BEGIN backout.simple.log --> 1.8683 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput> 1.8684 +2[tip] 611a0cae251c 2009-08-16 14:04 +0000 bos 1.8685 + back out second change 1.8686 + 1.8687 +1 43700a9b3ec8 2009-08-16 14:04 +0000 bos 1.8688 + second change 1.8689 + 1.8690 +0 f2ef23d503fd 2009-08-16 14:04 +0000 bos 1.8691 + first change 1.8692 + 1.8693 +</screen> 1.8694 +<!-- END backout.simple.log --> 1.8695 + Notice that the new changeset 1.8696 + that <command role="hg-cmd" moreinfo="none">hg backout</command> has created 1.8697 + is a child of the changeset we backed out. It's easier to see 1.8698 + this in <xref linkend="fig:undo:backout"/>, which presents a 1.8699 + graphical view of the change history. As you can see, the 1.8700 + history is nice and linear.</para> 1.8701 + 1.8702 + <figure id="fig:undo:backout" float="0"> 1.8703 + <title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title> 1.8704 + <mediaobject> 1.8705 + <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject> 1.8706 + <textobject><phrase>XXX add text</phrase></textobject> 1.8707 + </mediaobject> 1.8708 + </figure> 1.8709 + 1.8710 + </sect2> 1.8711 + <sect2> 1.8712 + <title>Backing out a non-tip change</title> 1.8713 + 1.8714 + <para id="x_fd">If you want to back out a change other than the last one 1.8715 + you committed, pass the <option role="hg-opt-backout">--merge</option> option to the 1.8716 + <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para> 1.8717 + 1.8718 + <!-- BEGIN backout.non-tip.clone --> 1.8719 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.8720 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo non-tip-repo</userinput> 1.8721 +requesting all changes 1.8722 +adding changesets 1.8723 +adding manifests 1.8724 +adding file changes 1.8725 +added 2 changesets with 2 changes to 1 files 1.8726 +updating working directory 1.8727 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.8728 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd non-tip-repo</userinput> 1.8729 +</screen> 1.8730 +<!-- END backout.non-tip.clone --> 1.8731 + 1.8732 + 1.8733 + <para id="x_fe">This makes backing out any changeset a 1.8734 + <quote>one-shot</quote> operation that's usually simple and 1.8735 + fast.</para> 1.8736 + 1.8737 + <!-- BEGIN backout.non-tip.backout --> 1.8738 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change >> myfile</userinput> 1.8739 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput> 1.8740 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout --merge -m 'back out second change' 1</userinput> 1.8741 +reverting myfile 1.8742 +created new head 1.8743 +changeset 3:611a0cae251c backs out changeset 1:43700a9b3ec8 1.8744 +merging with changeset 3:611a0cae251c 1.8745 +merging myfile 1.8746 +0 files updated, 1 files merged, 0 files removed, 0 files unresolved 1.8747 +(branch merge, don't forget to commit) 1.8748 +</screen> 1.8749 +<!-- END backout.non-tip.backout --> 1.8750 + 1.8751 + 1.8752 + <para id="x_ff">If you take a look at the contents of 1.8753 + <filename moreinfo="none">myfile</filename> after the backout finishes, you'll 1.8754 + see that the first and third changes are present, but not the 1.8755 + second.</para> 1.8756 + 1.8757 + <!-- BEGIN backout.non-tip.cat --> 1.8758 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.8759 +first change 1.8760 +third change 1.8761 +</screen> 1.8762 +<!-- END backout.non-tip.cat --> 1.8763 + 1.8764 + 1.8765 + <para id="x_100">As the graphical history in <xref linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial 1.8766 + still commits one change in this kind of situation (the 1.8767 + box-shaped node is the ones that Mercurial commits 1.8768 + automatically), but the revision graph now looks different. 1.8769 + Before Mercurial begins the backout process, it first 1.8770 + remembers what the current parent of the working directory is. 1.8771 + It then backs out the target changeset, and commits that as a 1.8772 + changeset. Finally, it merges back to the previous parent of 1.8773 + the working directory, but notice that it <emphasis>does not 1.8774 + commit</emphasis> the result of the merge. The repository 1.8775 + now contains two heads, and the working directory is in a 1.8776 + merge state.</para> 1.8777 + 1.8778 + <figure id="fig:undo:backout-non-tip" float="0"> 1.8779 + <title>Automated backout of a non-tip change using the 1.8780 + <command role="hg-cmd" moreinfo="none">hg backout</command> command</title> 1.8781 + <mediaobject> 1.8782 + <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject> 1.8783 + <textobject><phrase>XXX add text</phrase></textobject> 1.8784 + </mediaobject> 1.8785 + </figure> 1.8786 + 1.8787 + <para id="x_103">The result is that you end up <quote>back where you 1.8788 + were</quote>, only with some extra history that undoes the 1.8789 + effect of the changeset you wanted to back out.</para> 1.8790 + 1.8791 + <para id="x_6b9">You might wonder why Mercurial does not commit the result 1.8792 + of the merge that it performed. The reason lies in Mercurial 1.8793 + behaving conservatively: a merge naturally has more scope for 1.8794 + error than simply undoing the effect of the tip changeset, 1.8795 + so your work will be safest if you first inspect (and test!) 1.8796 + the result of the merge, <emphasis>then</emphasis> commit 1.8797 + it.</para> 1.8798 + 1.8799 + <sect3> 1.8800 + <title>Always use the <option role="hg-opt-backout">--merge</option> option</title> 1.8801 + 1.8802 + <para id="x_104">In fact, since the <option role="hg-opt-backout">--merge</option> option will do the 1.8803 + <quote>right thing</quote> whether or not the changeset 1.8804 + you're backing out is the tip (i.e. it won't try to merge if 1.8805 + it's backing out the tip, since there's no need), you should 1.8806 + <emphasis>always</emphasis> use this option when you run the 1.8807 + <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para> 1.8808 + 1.8809 + </sect3> 1.8810 + </sect2> 1.8811 + <sect2> 1.8812 + <title>Gaining more control of the backout process</title> 1.8813 + 1.8814 + <para id="x_105">While I've recommended that you always use the <option role="hg-opt-backout">--merge</option> option when backing 1.8815 + out a change, the <command role="hg-cmd" moreinfo="none">hg backout</command> 1.8816 + command lets you decide how to merge a backout changeset. 1.8817 + Taking control of the backout process by hand is something you 1.8818 + will rarely need to do, but it can be useful to understand 1.8819 + what the <command role="hg-cmd" moreinfo="none">hg backout</command> command 1.8820 + is doing for you automatically. To illustrate this, let's 1.8821 + clone our first repository, but omit the backout change that 1.8822 + it contains.</para> 1.8823 + 1.8824 + <!-- BEGIN backout.manual.clone --> 1.8825 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.8826 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo newrepo</userinput> 1.8827 +requesting all changes 1.8828 +adding changesets 1.8829 +adding manifests 1.8830 +adding file changes 1.8831 +added 2 changesets with 2 changes to 1 files 1.8832 +updating working directory 1.8833 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.8834 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd newrepo</userinput> 1.8835 +</screen> 1.8836 +<!-- END backout.manual.clone --> 1.8837 + 1.8838 + 1.8839 + <para id="x_106">As with our 1.8840 + earlier example, We'll commit a third changeset, then back out 1.8841 + its parent, and see what happens.</para> 1.8842 + 1.8843 + <!-- BEGIN backout.manual.backout --> 1.8844 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change >> myfile</userinput> 1.8845 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput> 1.8846 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' 1</userinput> 1.8847 +reverting myfile 1.8848 +created new head 1.8849 +changeset 3:bf906ee0baae backs out changeset 1:43700a9b3ec8 1.8850 +the backout changeset is a new head - do not forget to merge 1.8851 +(use "backout --merge" if you want to auto-merge) 1.8852 +</screen> 1.8853 +<!-- END backout.manual.backout --> 1.8854 + 1.8855 + 1.8856 + <para id="x_107">Our new changeset is again a descendant of the changeset 1.8857 + we backout out; it's thus a new head, <emphasis>not</emphasis> 1.8858 + a descendant of the changeset that was the tip. The <command role="hg-cmd" moreinfo="none">hg backout</command> command was quite 1.8859 + explicit in telling us this.</para> 1.8860 + 1.8861 + <!-- BEGIN backout.manual.log --> 1.8862 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput> 1.8863 +3[tip]:1 bf906ee0baae 2009-08-16 14:04 +0000 bos 1.8864 + back out second change 1.8865 + 1.8866 +2 2521379001ad 2009-08-16 14:04 +0000 bos 1.8867 + third change 1.8868 + 1.8869 +1 43700a9b3ec8 2009-08-16 14:04 +0000 bos 1.8870 + second change 1.8871 + 1.8872 +0 f2ef23d503fd 2009-08-16 14:04 +0000 bos 1.8873 + first change 1.8874 + 1.8875 +</screen> 1.8876 +<!-- END backout.manual.log --> 1.8877 + 1.8878 + 1.8879 + <para id="x_108">Again, it's easier to see what has happened by looking at 1.8880 + a graph of the revision history, in <xref linkend="fig:undo:backout-manual"/>. This makes it clear 1.8881 + that when we use <command role="hg-cmd" moreinfo="none">hg backout</command> 1.8882 + to back out a change other than the tip, Mercurial adds a new 1.8883 + head to the repository (the change it committed is 1.8884 + box-shaped).</para> 1.8885 + 1.8886 + <figure id="fig:undo:backout-manual" float="0"> 1.8887 + <title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title> 1.8888 + <mediaobject> 1.8889 + <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject> 1.8890 + <textobject><phrase>XXX add text</phrase></textobject> 1.8891 + </mediaobject> 1.8892 + </figure> 1.8893 + 1.8894 + <para id="x_10a">After the <command role="hg-cmd" moreinfo="none">hg backout</command> 1.8895 + command has completed, it leaves the new 1.8896 + <quote>backout</quote> changeset as the parent of the working 1.8897 + directory.</para> 1.8898 + 1.8899 + <!-- BEGIN backout.manual.parents --> 1.8900 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> 1.8901 +changeset: 2:2521379001ad 1.8902 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8903 +date: Sun Aug 16 14:04:37 2009 +0000 1.8904 +summary: third change 1.8905 + 1.8906 +</screen> 1.8907 +<!-- END backout.manual.parents --> 1.8908 + 1.8909 + 1.8910 + <para id="x_10b">Now we have two isolated sets of changes.</para> 1.8911 + 1.8912 + <!-- BEGIN backout.manual.heads --> 1.8913 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> 1.8914 +changeset: 3:bf906ee0baae 1.8915 +tag: tip 1.8916 +parent: 1:43700a9b3ec8 1.8917 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8918 +date: Sun Aug 16 14:04:37 2009 +0000 1.8919 +summary: back out second change 1.8920 + 1.8921 +changeset: 2:2521379001ad 1.8922 +user: Bryan O'Sullivan <bos@serpentine.com> 1.8923 +date: Sun Aug 16 14:04:37 2009 +0000 1.8924 +summary: third change 1.8925 + 1.8926 +</screen> 1.8927 +<!-- END backout.manual.heads --> 1.8928 + 1.8929 + 1.8930 + <para id="x_10c">Let's think about what we expect to see as the contents of 1.8931 + <filename moreinfo="none">myfile</filename> now. The first change should be 1.8932 + present, because we've never backed it out. The second change 1.8933 + should be missing, as that's the change we backed out. Since 1.8934 + the history graph shows the third change as a separate head, 1.8935 + we <emphasis>don't</emphasis> expect to see the third change 1.8936 + present in <filename moreinfo="none">myfile</filename>.</para> 1.8937 + 1.8938 + <!-- BEGIN backout.manual.cat --> 1.8939 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.8940 +first change 1.8941 +</screen> 1.8942 +<!-- END backout.manual.cat --> 1.8943 + 1.8944 + 1.8945 + <para id="x_10d">To get the third change back into the file, we just do a 1.8946 + normal merge of our two heads.</para> 1.8947 + 1.8948 + <!-- BEGIN backout.manual.merge --> 1.8949 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> 1.8950 +abort: outstanding uncommitted changes 1.8951 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'merged backout with previous tip'</userinput> 1.8952 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> 1.8953 +first change 1.8954 +</screen> 1.8955 +<!-- END backout.manual.merge --> 1.8956 + 1.8957 + 1.8958 + <para id="x_10e">Afterwards, the graphical history of our 1.8959 + repository looks like 1.8960 + <xref linkend="fig:undo:backout-manual-merge"/>.</para> 1.8961 + 1.8962 + <figure id="fig:undo:backout-manual-merge" float="0"> 1.8963 + <title>Manually merging a backout change</title> 1.8964 + <mediaobject> 1.8965 + <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject> 1.8966 + <textobject><phrase>XXX add text</phrase></textobject> 1.8967 + </mediaobject> 1.8968 + </figure> 1.8969 + 1.8970 + </sect2> 1.8971 + <sect2> 1.8972 + <title>Why <command role="hg-cmd" moreinfo="none">hg backout</command> works as 1.8973 + it does</title> 1.8974 + 1.8975 + <para id="x_110">Here's a brief description of how the <command role="hg-cmd" moreinfo="none">hg backout</command> command works.</para> 1.8976 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.8977 + <listitem><para id="x_111">It ensures that the working directory is 1.8978 + <quote>clean</quote>, i.e. that the output of <command role="hg-cmd" moreinfo="none">hg status</command> would be empty.</para> 1.8979 + </listitem> 1.8980 + <listitem><para id="x_112">It remembers the current parent of the working 1.8981 + directory. Let's call this changeset 1.8982 + <literal moreinfo="none">orig</literal>.</para> 1.8983 + </listitem> 1.8984 + <listitem><para id="x_113">It does the equivalent of a <command role="hg-cmd" moreinfo="none">hg update</command> to sync the working 1.8985 + directory to the changeset you want to back out. Let's 1.8986 + call this changeset <literal moreinfo="none">backout</literal>.</para> 1.8987 + </listitem> 1.8988 + <listitem><para id="x_114">It finds the parent of that changeset. Let's 1.8989 + call that changeset <literal moreinfo="none">parent</literal>.</para> 1.8990 + </listitem> 1.8991 + <listitem><para id="x_115">For each file that the 1.8992 + <literal moreinfo="none">backout</literal> changeset affected, it does the 1.8993 + equivalent of a <command role="hg-cmd" moreinfo="none">hg revert -r 1.8994 + parent</command> on that file, to restore it to the 1.8995 + contents it had before that changeset was 1.8996 + committed.</para> 1.8997 + </listitem> 1.8998 + <listitem><para id="x_116">It commits the result as a new changeset. 1.8999 + This changeset has <literal moreinfo="none">backout</literal> as its 1.9000 + parent.</para> 1.9001 + </listitem> 1.9002 + <listitem><para id="x_117">If you specify <option role="hg-opt-backout">--merge</option> on the command 1.9003 + line, it merges with <literal moreinfo="none">orig</literal>, and commits 1.9004 + the result of the merge.</para> 1.9005 + </listitem></orderedlist> 1.9006 + 1.9007 + <para id="x_118">An alternative way to implement the <command role="hg-cmd" moreinfo="none">hg backout</command> command would be to 1.9008 + <command role="hg-cmd" moreinfo="none">hg export</command> the 1.9009 + to-be-backed-out changeset as a diff, then use the <option role="cmd-opt-patch">--reverse</option> option to the 1.9010 + <command moreinfo="none">patch</command> command to reverse the effect of the 1.9011 + change without fiddling with the working directory. This 1.9012 + sounds much simpler, but it would not work nearly as 1.9013 + well.</para> 1.9014 + 1.9015 + <para id="x_119">The reason that <command role="hg-cmd" moreinfo="none">hg 1.9016 + backout</command> does an update, a commit, a merge, and 1.9017 + another commit is to give the merge machinery the best chance 1.9018 + to do a good job when dealing with all the changes 1.9019 + <emphasis>between</emphasis> the change you're backing out and 1.9020 + the current tip.</para> 1.9021 + 1.9022 + <para id="x_11a">If you're backing out a changeset that's 100 revisions 1.9023 + back in your project's history, the chances that the 1.9024 + <command moreinfo="none">patch</command> command will be able to apply a 1.9025 + reverse diff cleanly are not good, because intervening changes 1.9026 + are likely to have <quote>broken the context</quote> that 1.9027 + <command moreinfo="none">patch</command> uses to determine whether it can 1.9028 + apply a patch (if this sounds like gibberish, see <xref linkend="sec:mq:patch"/> for a 1.9029 + discussion of the <command moreinfo="none">patch</command> command). Also, 1.9030 + Mercurial's merge machinery will handle files and directories 1.9031 + being renamed, permission changes, and modifications to binary 1.9032 + files, none of which <command moreinfo="none">patch</command> can deal 1.9033 + with.</para> 1.9034 + 1.9035 + </sect2> 1.9036 + </sect1> 1.9037 + <sect1 id="sec:undo:aaaiiieee"> 1.9038 + <title>Changes that should never have been</title> 1.9039 + 1.9040 + <para id="x_11b">Most of the time, the <command role="hg-cmd" moreinfo="none">hg 1.9041 + backout</command> command is exactly what you need if you want 1.9042 + to undo the effects of a change. It leaves a permanent record 1.9043 + of exactly what you did, both when committing the original 1.9044 + changeset and when you cleaned up after it.</para> 1.9045 + 1.9046 + <para id="x_11c">On rare occasions, though, you may find that you've 1.9047 + committed a change that really should not be present in the 1.9048 + repository at all. For example, it would be very unusual, and 1.9049 + usually considered a mistake, to commit a software project's 1.9050 + object files as well as its source files. Object files have 1.9051 + almost no intrinsic value, and they're <emphasis>big</emphasis>, 1.9052 + so they increase the size of the repository and the amount of 1.9053 + time it takes to clone or pull changes.</para> 1.9054 + 1.9055 + <para id="x_11d">Before I discuss the options that you have if you commit a 1.9056 + <quote>brown paper bag</quote> change (the kind that's so bad 1.9057 + that you want to pull a brown paper bag over your head), let me 1.9058 + first discuss some approaches that probably won't work.</para> 1.9059 + 1.9060 + <para id="x_11e">Since Mercurial treats history as 1.9061 + accumulative—every change builds on top of all changes 1.9062 + that preceded it—you generally can't just make disastrous 1.9063 + changes disappear. The one exception is when you've just 1.9064 + committed a change, and it hasn't been pushed or pulled into 1.9065 + another repository. That's when you can safely use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, as I detailed in 1.9066 + <xref linkend="sec:undo:rollback"/>.</para> 1.9067 + 1.9068 + <para id="x_11f">After you've pushed a bad change to another repository, you 1.9069 + <emphasis>could</emphasis> still use <command role="hg-cmd" moreinfo="none">hg 1.9070 + rollback</command> to make your local copy of the change 1.9071 + disappear, but it won't have the consequences you want. The 1.9072 + change will still be present in the remote repository, so it 1.9073 + will reappear in your local repository the next time you 1.9074 + pull.</para> 1.9075 + 1.9076 + <para id="x_120">If a situation like this arises, and you know which 1.9077 + repositories your bad change has propagated into, you can 1.9078 + <emphasis>try</emphasis> to get rid of the change from 1.9079 + <emphasis>every</emphasis> one of those repositories. This is, 1.9080 + of course, not a satisfactory solution: if you miss even a 1.9081 + single repository while you're expunging, the change is still 1.9082 + <quote>in the wild</quote>, and could propagate further.</para> 1.9083 + 1.9084 + <para id="x_121">If you've committed one or more changes 1.9085 + <emphasis>after</emphasis> the change that you'd like to see 1.9086 + disappear, your options are further reduced. Mercurial doesn't 1.9087 + provide a way to <quote>punch a hole</quote> in history, leaving 1.9088 + changesets intact.</para> 1.9089 + 1.9090 + <sect2> 1.9091 + <title>Backing out a merge</title> 1.9092 + 1.9093 + <para id="x_6ba">Since merges are often complicated, it is not unheard of 1.9094 + for a merge to be mangled badly, but committed erroneously. 1.9095 + Mercurial provides an important safeguard against bad merges 1.9096 + by refusing to commit unresolved files, but human ingenuity 1.9097 + guarantees that it is still possible to mess a merge up and 1.9098 + commit it.</para> 1.9099 + 1.9100 + <para id="x_6bb">Given a bad merge that has been committed, usually the 1.9101 + best way to approach it is to simply try to repair the damage 1.9102 + by hand. A complete disaster that cannot be easily fixed up 1.9103 + by hand ought to be very rare, but the <command role="hg-cmd" moreinfo="none">hg backout</command> command may help in 1.9104 + making the cleanup easier. It offers a <option role="hg-opt-backout">--parent</option> option, which lets 1.9105 + you specify which parent to revert to when backing out a 1.9106 + merge.</para> 1.9107 + 1.9108 + <figure id="fig:undo:bad-merge-1" float="0"> 1.9109 + <title>A bad merge</title> 1.9110 + <mediaobject> 1.9111 + <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject> 1.9112 + <textobject><phrase>XXX add text</phrase></textobject> 1.9113 + </mediaobject> 1.9114 + </figure> 1.9115 + 1.9116 + <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 1.9117 + <emphasis>redo</emphasis> the merge of revisions 2 and 1.9118 + 3.</para> 1.9119 + 1.9120 + <para id="x_6bd">One way to do so would be as follows.</para> 1.9121 + 1.9122 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.9123 + <listitem> 1.9124 + <para id="x_6be">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4 1.9125 + --parent=2</command>. This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision 1.9126 + 4, which is the bad merge, and to when deciding which 1.9127 + revision to prefer, to choose parent 2, one of the parents 1.9128 + of the merge. The effect can be seen in <xref linkend="fig:undo:bad-merge-2"/>.</para> 1.9129 + <figure id="fig:undo:bad-merge-2" float="0"> 1.9130 + <title>Backing out the merge, favoring one parent</title> 1.9131 + <mediaobject> 1.9132 + <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject> 1.9133 + <textobject><phrase>XXX add text</phrase></textobject> 1.9134 + </mediaobject> 1.9135 + </figure> 1.9136 + </listitem> 1.9137 + 1.9138 + <listitem> 1.9139 + <para id="x_6bf">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4 1.9140 + --parent=3</command>. This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision 1.9141 + 4 again, but this time to choose parent 3, the other 1.9142 + parent of the merge. The result is visible in <xref linkend="fig:undo:bad-merge-3"/>, in which the repository 1.9143 + now contains three heads.</para> 1.9144 + <figure id="fig:undo:bad-merge-3" float="0"> 1.9145 + <title>Backing out the merge, favoring the other 1.9146 + parent</title> 1.9147 + <mediaobject> 1.9148 + <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject> 1.9149 + <textobject><phrase>XXX add text</phrase></textobject> 1.9150 + </mediaobject> 1.9151 + </figure> 1.9152 + </listitem> 1.9153 + 1.9154 + <listitem> 1.9155 + <para id="x_6c0">Redo the bad merge by merging the two backout heads, 1.9156 + which reduces the number of heads in the repository to 1.9157 + two, as can be seen in <xref linkend="fig:undo:bad-merge-4"/>.</para> 1.9158 + <figure id="fig:undo:bad-merge-4" float="0"> 1.9159 + <title>Merging the backouts</title> 1.9160 + <mediaobject> 1.9161 + <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject> 1.9162 + <textobject><phrase>XXX add text</phrase></textobject> 1.9163 + </mediaobject> 1.9164 + </figure> 1.9165 + </listitem> 1.9166 + 1.9167 + <listitem> 1.9168 + <para id="x_6c1">Merge with the commit that was made after the bad 1.9169 + merge, as shown in <xref linkend="fig:undo:bad-merge-5"/>.</para> 1.9170 + <figure id="fig:undo:bad-merge-5" float="0"> 1.9171 + <title>Merging the backouts</title> 1.9172 + <mediaobject> 1.9173 + <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject> 1.9174 + <textobject><phrase>XXX add text</phrase></textobject> 1.9175 + </mediaobject> 1.9176 + </figure> 1.9177 + </listitem> 1.9178 + </orderedlist> 1.9179 + </sect2> 1.9180 + 1.9181 + <sect2> 1.9182 + <title>Protect yourself from <quote>escaped</quote> 1.9183 + changes</title> 1.9184 + 1.9185 + <para id="x_123">If you've committed some changes to your local repository 1.9186 + and they've been pushed or pulled somewhere else, this isn't 1.9187 + necessarily a disaster. You can protect yourself ahead of 1.9188 + time against some classes of bad changeset. This is 1.9189 + particularly easy if your team usually pulls changes from a 1.9190 + central repository.</para> 1.9191 + 1.9192 + <para id="x_124">By configuring some hooks on that repository to validate 1.9193 + incoming changesets (see chapter <xref linkend="chap:hook"/>), 1.9194 + you can 1.9195 + automatically prevent some kinds of bad changeset from being 1.9196 + pushed to the central repository at all. With such a 1.9197 + configuration in place, some kinds of bad changeset will 1.9198 + naturally tend to <quote>die out</quote> because they can't 1.9199 + propagate into the central repository. Better yet, this 1.9200 + happens without any need for explicit intervention.</para> 1.9201 + 1.9202 + <para id="x_125">For instance, an incoming change hook that 1.9203 + verifies that a changeset will actually compile can prevent 1.9204 + people from inadvertently <quote>breaking the 1.9205 + build</quote>.</para> 1.9206 + </sect2> 1.9207 + 1.9208 + <sect2> 1.9209 + <title>What to do about sensitive changes that escape</title> 1.9210 + 1.9211 + <para id="x_6c2">Even a carefully run project can suffer an unfortunate 1.9212 + event such as the committing and uncontrolled propagation of a 1.9213 + file that contains important passwords.</para> 1.9214 + 1.9215 + <para id="x_6c3">If something like this happens to you, and the information 1.9216 + that gets accidentally propagated is truly sensitive, your 1.9217 + first step should be to mitigate the effect of the leak 1.9218 + without trying to control the leak itself. If you are not 100% 1.9219 + certain that you know exactly who could have seen the changes, 1.9220 + you should immediately change passwords, cancel credit cards, 1.9221 + or find some other way to make sure that the information that 1.9222 + has leaked is no longer useful. In other words, assume that 1.9223 + the change has propagated far and wide, and that there's 1.9224 + nothing more you can do.</para> 1.9225 + 1.9226 + <para id="x_6c4">You might hope that there would be mechanisms you could 1.9227 + use to either figure out who has seen a change or to erase the 1.9228 + change permanently everywhere, but there are good reasons why 1.9229 + these are not possible.</para> 1.9230 + 1.9231 + <para id="x_6c5">Mercurial does not provide an audit trail of who has 1.9232 + pulled changes from a repository, because it is usually either 1.9233 + impossible to record such information or trivial to spoof it. 1.9234 + In a multi-user or networked environment, you should thus be 1.9235 + extremely skeptical of yourself if you think that you have 1.9236 + identified every place that a sensitive changeset has 1.9237 + propagated to. Don't forget that people can and will send 1.9238 + bundles by email, have their backup software save data 1.9239 + offsite, carry repositories on USB sticks, and find other 1.9240 + completely innocent ways to confound your attempts to track 1.9241 + down every copy of a problematic change.</para> 1.9242 + 1.9243 + <para id="x_6c6">Mercurial also does not provide a way to make a file or 1.9244 + changeset completely disappear from history, because there is 1.9245 + no way to enforce its disappearance; someone could easily 1.9246 + modify their copy of Mercurial to ignore such directives. In 1.9247 + addition, even if Mercurial provided such a capability, 1.9248 + someone who simply hadn't pulled a <quote>make this file 1.9249 + disappear</quote> changeset wouldn't be affected by it, nor 1.9250 + would web crawlers visiting at the wrong time, disk backups, 1.9251 + or other mechanisms. Indeed, no distributed revision control 1.9252 + system can make data reliably vanish. Providing the illusion 1.9253 + of such control could easily give a false sense of security, 1.9254 + and be worse than not providing it at all.</para> 1.9255 + </sect2> 1.9256 + </sect1> 1.9257 + 1.9258 + <sect1 id="sec:undo:bisect"> 1.9259 + <title>Finding the source of a bug</title> 1.9260 + 1.9261 + <para id="x_126">While it's all very well to be able to back out a changeset 1.9262 + that introduced a bug, this requires that you know which 1.9263 + changeset to back out. Mercurial provides an invaluable 1.9264 + command, called <command role="hg-cmd" moreinfo="none">hg bisect</command>, that 1.9265 + helps you to automate this process and accomplish it very 1.9266 + efficiently.</para> 1.9267 + 1.9268 + <para id="x_127">The idea behind the <command role="hg-cmd" moreinfo="none">hg 1.9269 + bisect</command> command is that a changeset has introduced 1.9270 + some change of behavior that you can identify with a simple 1.9271 + pass/fail test. You don't know which piece of code introduced the 1.9272 + change, but you know how to test for the presence of the bug. 1.9273 + The <command role="hg-cmd" moreinfo="none">hg bisect</command> command uses your 1.9274 + test to direct its search for the changeset that introduced the 1.9275 + code that caused the bug.</para> 1.9276 + 1.9277 + <para id="x_128">Here are a few scenarios to help you understand how you 1.9278 + might apply this command.</para> 1.9279 + <itemizedlist> 1.9280 + <listitem><para id="x_129">The most recent version of your software has a 1.9281 + bug that you remember wasn't present a few weeks ago, but 1.9282 + you don't know when it was introduced. Here, your binary 1.9283 + test checks for the presence of that bug.</para> 1.9284 + </listitem> 1.9285 + <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to 1.9286 + close the entry in your team's bug database. The bug 1.9287 + database requires a changeset ID when you close an entry, 1.9288 + but you don't remember which changeset you fixed the bug in. 1.9289 + Once again, your binary test checks for the presence of the 1.9290 + bug.</para> 1.9291 + </listitem> 1.9292 + <listitem><para id="x_12b">Your software works correctly, but runs 15% 1.9293 + slower than the last time you measured it. You want to know 1.9294 + which changeset introduced the performance regression. In 1.9295 + this case, your binary test measures the performance of your 1.9296 + software, to see whether it's <quote>fast</quote> or 1.9297 + <quote>slow</quote>.</para> 1.9298 + </listitem> 1.9299 + <listitem><para id="x_12c">The sizes of the components of your project that 1.9300 + you ship exploded recently, and you suspect that something 1.9301 + changed in the way you build your project.</para> 1.9302 + </listitem></itemizedlist> 1.9303 + 1.9304 + <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 1.9305 + for finding the sources of bugs. You can use it to find any 1.9306 + <quote>emergent property</quote> of a repository (anything that 1.9307 + you can't find from a simple text search of the files in the 1.9308 + tree) for which you can write a binary test.</para> 1.9309 + 1.9310 + <para id="x_12e">We'll introduce a little bit of terminology here, just to 1.9311 + make it clear which parts of the search process are your 1.9312 + responsibility, and which are Mercurial's. A 1.9313 + <emphasis>test</emphasis> is something that 1.9314 + <emphasis>you</emphasis> run when <command role="hg-cmd" moreinfo="none">hg 1.9315 + bisect</command> chooses a changeset. A 1.9316 + <emphasis>probe</emphasis> is what <command role="hg-cmd" moreinfo="none">hg 1.9317 + bisect</command> runs to tell whether a revision is good. 1.9318 + Finally, we'll use the word <quote>bisect</quote>, as both a 1.9319 + noun and a verb, to stand in for the phrase <quote>search using 1.9320 + the <command role="hg-cmd" moreinfo="none">hg bisect</command> 1.9321 + command</quote>.</para> 1.9322 + 1.9323 + <para id="x_12f">One simple way to automate the searching process would be 1.9324 + simply to probe every changeset. However, this scales poorly. 1.9325 + If it took ten minutes to test a single changeset, and you had 1.9326 + 10,000 changesets in your repository, the exhaustive approach 1.9327 + would take on average 35 <emphasis>days</emphasis> to find the 1.9328 + changeset that introduced a bug. Even if you knew that the bug 1.9329 + was introduced by one of the last 500 changesets, and limited 1.9330 + your search to those, you'd still be looking at over 40 hours to 1.9331 + find the changeset that introduced your bug.</para> 1.9332 + 1.9333 + <para id="x_130">What the <command role="hg-cmd" moreinfo="none">hg bisect</command> command 1.9334 + does is use its knowledge of the <quote>shape</quote> of your 1.9335 + project's revision history to perform a search in time 1.9336 + proportional to the <emphasis>logarithm</emphasis> of the number 1.9337 + of changesets to check (the kind of search it performs is called 1.9338 + a dichotomic search). With this approach, searching through 1.9339 + 10,000 changesets will take less than three hours, even at ten 1.9340 + minutes per test (the search will require about 14 tests). 1.9341 + Limit your search to the last hundred changesets, and it will 1.9342 + take only about an hour (roughly seven tests).</para> 1.9343 + 1.9344 + <para id="x_131">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command is 1.9345 + aware of the <quote>branchy</quote> nature of a Mercurial 1.9346 + project's revision history, so it has no problems dealing with 1.9347 + branches, merges, or multiple heads in a repository. It can 1.9348 + prune entire branches of history with a single probe, which is 1.9349 + how it operates so efficiently.</para> 1.9350 + 1.9351 + <sect2> 1.9352 + <title>Using the <command role="hg-cmd" moreinfo="none">hg bisect</command> 1.9353 + command</title> 1.9354 + 1.9355 + <para id="x_132">Here's an example of <command role="hg-cmd" moreinfo="none">hg 1.9356 + bisect</command> in action.</para> 1.9357 + 1.9358 + <note> 1.9359 + <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: 1.9360 + it was distributed with Mercurial as an extension. This 1.9361 + section describes the built-in command, not the old 1.9362 + extension.</para> 1.9363 + </note> 1.9364 + 1.9365 + <para id="x_134">Now let's create a repository, so that we can try out the 1.9366 + <command role="hg-cmd" moreinfo="none">hg bisect</command> command in 1.9367 + isolation.</para> 1.9368 + 1.9369 + <!-- BEGIN bisect.init --> 1.9370 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mybug</userinput> 1.9371 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mybug</userinput> 1.9372 +</screen> 1.9373 +<!-- END bisect.init --> 1.9374 + 1.9375 + 1.9376 + <para id="x_135">We'll simulate a project that has a bug in it in a 1.9377 + simple-minded way: create trivial changes in a loop, and 1.9378 + nominate one specific change that will have the 1.9379 + <quote>bug</quote>. This loop creates 35 changesets, each 1.9380 + adding a single file to the repository. We'll represent our 1.9381 + <quote>bug</quote> with a file that contains the text <quote>i 1.9382 + have a gub</quote>.</para> 1.9383 + 1.9384 + <!-- BEGIN bisect.commits --> 1.9385 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">buggy_change=22</userinput> 1.9386 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">for (( i = 0; i < 35; i++ )); do</userinput> 1.9387 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> if [[ $i = $buggy_change ]]; then</userinput> 1.9388 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo 'i have a gub' > myfile$i</userinput> 1.9389 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg commit -q -A -m 'buggy changeset'</userinput> 1.9390 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> else</userinput> 1.9391 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo 'nothing to see here, move along' > myfile$i</userinput> 1.9392 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg commit -q -A -m 'normal changeset'</userinput> 1.9393 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> fi</userinput> 1.9394 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">done</userinput> 1.9395 +</screen> 1.9396 +<!-- END bisect.commits --> 1.9397 + 1.9398 + 1.9399 + <para id="x_136">The next thing that we'd like to do is figure out how to 1.9400 + use the <command role="hg-cmd" moreinfo="none">hg bisect</command> command. 1.9401 + We can use Mercurial's normal built-in help mechanism for 1.9402 + this.</para> 1.9403 + 1.9404 + <!-- BEGIN bisect.help --> 1.9405 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help bisect</userinput> 1.9406 +hg bisect [-gbsr] [-c CMD] [REV] 1.9407 + 1.9408 +subdivision search of changesets 1.9409 + 1.9410 + This command helps to find changesets which introduce problems. 1.9411 + To use, mark the earliest changeset you know exhibits the problem 1.9412 + as bad, then mark the latest changeset which is free from the 1.9413 + problem as good. Bisect will update your working directory to a 1.9414 + revision for testing (unless the --noupdate option is specified). 1.9415 + Once you have performed tests, mark the working directory as bad 1.9416 + or good and bisect will either update to another candidate changeset 1.9417 + or announce that it has found the bad revision. 1.9418 + 1.9419 + As a shortcut, you can also use the revision argument to mark a 1.9420 + revision as good or bad without checking it out first. 1.9421 + 1.9422 + If you supply a command it will be used for automatic bisection. Its exit 1.9423 + status will be used as flag to mark revision as bad or good. In case exit 1.9424 + status is 0 the revision is marked as good, 125 - skipped, 127 (command not 1.9425 + found) - bisection will be aborted; any other status bigger than 0 will 1.9426 + mark revision as bad. 1.9427 + 1.9428 +options: 1.9429 + 1.9430 + -r --reset reset bisect state 1.9431 + -g --good mark changeset good 1.9432 + -b --bad mark changeset bad 1.9433 + -s --skip skip testing changeset 1.9434 + -c --command use command to check changeset state 1.9435 + -U --noupdate do not update to target 1.9436 + 1.9437 +use "hg -v help bisect" to show global options 1.9438 +</screen> 1.9439 +<!-- END bisect.help --> 1.9440 + 1.9441 + 1.9442 + <para id="x_137">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command 1.9443 + works in steps. Each step proceeds as follows.</para> 1.9444 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.9445 + <listitem><para id="x_138">You run your binary test.</para> 1.9446 + <itemizedlist> 1.9447 + <listitem><para id="x_139">If the test succeeded, you tell <command role="hg-cmd" moreinfo="none">hg bisect</command> by running the 1.9448 + <command role="hg-cmd" moreinfo="none">hg bisect --good</command> 1.9449 + command.</para> 1.9450 + </listitem> 1.9451 + <listitem><para id="x_13a">If it failed, run the <command role="hg-cmd" moreinfo="none">hg bisect --bad</command> 1.9452 + command.</para></listitem></itemizedlist> 1.9453 + </listitem> 1.9454 + <listitem><para id="x_13b">The command uses your information to decide 1.9455 + which changeset to test next.</para> 1.9456 + </listitem> 1.9457 + <listitem><para id="x_13c">It updates the working directory to that 1.9458 + changeset, and the process begins again.</para> 1.9459 + </listitem></orderedlist> 1.9460 + <para id="x_13d">The process ends when <command role="hg-cmd" moreinfo="none">hg 1.9461 + bisect</command> identifies a unique changeset that marks 1.9462 + the point where your test transitioned from 1.9463 + <quote>succeeding</quote> to <quote>failing</quote>.</para> 1.9464 + 1.9465 + <para id="x_13e">To start the search, we must run the <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command.</para> 1.9466 + 1.9467 + <!-- BEGIN bisect.search.init --> 1.9468 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput> 1.9469 +</screen> 1.9470 +<!-- END bisect.search.init --> 1.9471 + 1.9472 + 1.9473 + <para id="x_13f">In our case, the binary test we use is simple: we check to 1.9474 + see if any file in the repository contains the string <quote>i 1.9475 + have a gub</quote>. If it does, this changeset contains the 1.9476 + change that <quote>caused the bug</quote>. By convention, a 1.9477 + changeset that has the property we're searching for is 1.9478 + <quote>bad</quote>, while one that doesn't is 1.9479 + <quote>good</quote>.</para> 1.9480 + 1.9481 + <para id="x_140">Most of the time, the revision to which the working 1.9482 + directory is synced (usually the tip) already exhibits the 1.9483 + problem introduced by the buggy change, so we'll mark it as 1.9484 + <quote>bad</quote>.</para> 1.9485 + 1.9486 + <!-- BEGIN bisect.search.bad-init --> 1.9487 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --bad</userinput> 1.9488 +</screen> 1.9489 +<!-- END bisect.search.bad-init --> 1.9490 + 1.9491 + 1.9492 + <para id="x_141">Our next task is to nominate a changeset that we know 1.9493 + <emphasis>doesn't</emphasis> have the bug; the <command role="hg-cmd" moreinfo="none">hg bisect</command> command will 1.9494 + <quote>bracket</quote> its search between the first pair of 1.9495 + good and bad changesets. In our case, we know that revision 1.9496 + 10 didn't have the bug. (I'll have more words about choosing 1.9497 + the first <quote>good</quote> changeset later.)</para> 1.9498 + 1.9499 + <!-- BEGIN bisect.search.good-init --> 1.9500 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --good 10</userinput> 1.9501 +Testing changeset 22:69f52b967ab8 (24 changesets remaining, ~4 tests) 1.9502 +0 files updated, 0 files merged, 12 files removed, 0 files unresolved 1.9503 +</screen> 1.9504 +<!-- END bisect.search.good-init --> 1.9505 + 1.9506 + 1.9507 + <para id="x_142">Notice that this command printed some output.</para> 1.9508 + <itemizedlist> 1.9509 + <listitem><para id="x_143">It told us how many changesets it must 1.9510 + consider before it can identify the one that introduced 1.9511 + the bug, and how many tests that will require.</para> 1.9512 + </listitem> 1.9513 + <listitem><para id="x_144">It updated the working directory to the next 1.9514 + changeset to test, and told us which changeset it's 1.9515 + testing.</para> 1.9516 + </listitem></itemizedlist> 1.9517 + 1.9518 + <para id="x_145">We now run our test in the working directory. We use the 1.9519 + <command moreinfo="none">grep</command> command to see if our 1.9520 + <quote>bad</quote> file is present in the working directory. 1.9521 + If it is, this revision is bad; if not, this revision is good. 1.9522 + <!-- BEGIN bisect.search.step1 --> 1.9523 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">if grep -q 'i have a gub' *</userinput> 1.9524 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">then</userinput> 1.9525 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=bad</userinput> 1.9526 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">else</userinput> 1.9527 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=good</userinput> 1.9528 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">fi</userinput> 1.9529 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo this revision is $result</userinput> 1.9530 +this revision is bad 1.9531 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --$result</userinput> 1.9532 +Testing changeset 16:f1dd8bc690ae (12 changesets remaining, ~3 tests) 1.9533 +0 files updated, 0 files merged, 6 files removed, 0 files unresolved 1.9534 +</screen> 1.9535 +<!-- END bisect.search.step1 --> 1.9536 +</para> 1.9537 + 1.9538 + <para id="x_146">This test looks like a perfect candidate for automation, 1.9539 + so let's turn it into a shell function.</para> 1.9540 + <!-- BEGIN bisect.search.mytest --> 1.9541 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest() {</userinput> 1.9542 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> if grep -q 'i have a gub' *</userinput> 1.9543 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> then</userinput> 1.9544 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=bad</userinput> 1.9545 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> else</userinput> 1.9546 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=good</userinput> 1.9547 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> fi</userinput> 1.9548 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo this revision is $result</userinput> 1.9549 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg bisect --$result</userinput> 1.9550 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">}</userinput> 1.9551 +</screen> 1.9552 +<!-- END bisect.search.mytest --> 1.9553 + 1.9554 + 1.9555 + <para id="x_147">We can now run an entire test step with a single command, 1.9556 + <literal moreinfo="none">mytest</literal>.</para> 1.9557 + 1.9558 + <!-- BEGIN bisect.search.step2 --> 1.9559 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> 1.9560 +this revision is good 1.9561 +Testing changeset 19:88d99d97058a (6 changesets remaining, ~2 tests) 1.9562 +3 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.9563 +</screen> 1.9564 +<!-- END bisect.search.step2 --> 1.9565 + 1.9566 + 1.9567 + <para id="x_148">A few more invocations of our canned test step command, 1.9568 + and we're done.</para> 1.9569 + 1.9570 + <!-- BEGIN bisect.search.rest --> 1.9571 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> 1.9572 +this revision is good 1.9573 +Testing changeset 20:32a195a31d51 (3 changesets remaining, ~1 tests) 1.9574 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.9575 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> 1.9576 +this revision is good 1.9577 +Testing changeset 21:a2efe8e4f624 (2 changesets remaining, ~1 tests) 1.9578 +1 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.9579 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> 1.9580 +this revision is good 1.9581 +The first bad revision is: 1.9582 +changeset: 22:69f52b967ab8 1.9583 +user: Bryan O'Sullivan <bos@serpentine.com> 1.9584 +date: Sun Aug 16 14:04:39 2009 +0000 1.9585 +summary: buggy changeset 1.9586 + 1.9587 +</screen> 1.9588 +<!-- END bisect.search.rest --> 1.9589 + 1.9590 + 1.9591 + <para id="x_149">Even though we had 40 changesets to search through, the 1.9592 + <command role="hg-cmd" moreinfo="none">hg bisect</command> command let us find 1.9593 + the changeset that introduced our <quote>bug</quote> with only 1.9594 + five tests. Because the number of tests that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command performs grows 1.9595 + logarithmically with the number of changesets to search, the 1.9596 + advantage that it has over the <quote>brute force</quote> 1.9597 + search approach increases with every changeset you add.</para> 1.9598 + 1.9599 + </sect2> 1.9600 + <sect2> 1.9601 + <title>Cleaning up after your search</title> 1.9602 + 1.9603 + <para id="x_14a">When you're finished using the <command role="hg-cmd" moreinfo="none">hg 1.9604 + bisect</command> command in a repository, you can use the 1.9605 + <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command to 1.9606 + drop the information it was using to drive your search. The 1.9607 + command doesn't use much space, so it doesn't matter if you 1.9608 + forget to run this command. However, <command role="hg-cmd" moreinfo="none">hg bisect</command> won't let you start a new 1.9609 + search in that repository until you do a <command role="hg-cmd" moreinfo="none">hg bisect --reset</command>.</para> 1.9610 + 1.9611 + <!-- BEGIN bisect.search.reset --> 1.9612 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput> 1.9613 +</screen> 1.9614 +<!-- END bisect.search.reset --> 1.9615 + 1.9616 + 1.9617 + </sect2> 1.9618 + </sect1> 1.9619 + <sect1> 1.9620 + <title>Tips for finding bugs effectively</title> 1.9621 + 1.9622 + <sect2> 1.9623 + <title>Give consistent input</title> 1.9624 + 1.9625 + <para id="x_14b">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command 1.9626 + requires that you correctly report the result of every test 1.9627 + you perform. If you tell it that a test failed when it really 1.9628 + succeeded, it <emphasis>might</emphasis> be able to detect the 1.9629 + inconsistency. If it can identify an inconsistency in your 1.9630 + reports, it will tell you that a particular changeset is both 1.9631 + good and bad. However, it can't do this perfectly; it's about 1.9632 + as likely to report the wrong changeset as the source of the 1.9633 + bug.</para> 1.9634 + 1.9635 + </sect2> 1.9636 + <sect2> 1.9637 + <title>Automate as much as possible</title> 1.9638 + 1.9639 + <para id="x_14c">When I started using the <command role="hg-cmd" moreinfo="none">hg 1.9640 + bisect</command> command, I tried a few times to run my 1.9641 + tests by hand, on the command line. This is an approach that 1.9642 + I, at least, am not suited to. After a few tries, I found 1.9643 + that I was making enough mistakes that I was having to restart 1.9644 + my searches several times before finally getting correct 1.9645 + results.</para> 1.9646 + 1.9647 + <para id="x_14d">My initial problems with driving the <command role="hg-cmd" moreinfo="none">hg bisect</command> command by hand occurred 1.9648 + even with simple searches on small repositories; if the 1.9649 + problem you're looking for is more subtle, or the number of 1.9650 + tests that <command role="hg-cmd" moreinfo="none">hg bisect</command> must 1.9651 + perform increases, the likelihood of operator error ruining 1.9652 + the search is much higher. Once I started automating my 1.9653 + tests, I had much better results.</para> 1.9654 + 1.9655 + <para id="x_14e">The key to automated testing is twofold:</para> 1.9656 + <itemizedlist> 1.9657 + <listitem><para id="x_14f">always test for the same symptom, and</para> 1.9658 + </listitem> 1.9659 + <listitem><para id="x_150">always feed consistent input to the <command role="hg-cmd" moreinfo="none">hg bisect</command> command.</para> 1.9660 + </listitem></itemizedlist> 1.9661 + <para id="x_151">In my tutorial example above, the <command moreinfo="none">grep</command> 1.9662 + command tests for the symptom, and the <literal moreinfo="none">if</literal> 1.9663 + statement takes the result of this check and ensures that we 1.9664 + always feed the same input to the <command role="hg-cmd" moreinfo="none">hg 1.9665 + bisect</command> command. The <literal moreinfo="none">mytest</literal> 1.9666 + function marries these together in a reproducible way, so that 1.9667 + every test is uniform and consistent.</para> 1.9668 + 1.9669 + </sect2> 1.9670 + <sect2> 1.9671 + <title>Check your results</title> 1.9672 + 1.9673 + <para id="x_152">Because the output of a <command role="hg-cmd" moreinfo="none">hg 1.9674 + bisect</command> search is only as good as the input you 1.9675 + give it, don't take the changeset it reports as the absolute 1.9676 + truth. A simple way to cross-check its report is to manually 1.9677 + run your test at each of the following changesets:</para> 1.9678 + <itemizedlist> 1.9679 + <listitem><para id="x_153">The changeset that it reports as the first bad 1.9680 + revision. Your test should still report this as 1.9681 + bad.</para> 1.9682 + </listitem> 1.9683 + <listitem><para id="x_154">The parent of that changeset (either parent, 1.9684 + if it's a merge). Your test should report this changeset 1.9685 + as good.</para> 1.9686 + </listitem> 1.9687 + <listitem><para id="x_155">A child of that changeset. Your test should 1.9688 + report this changeset as bad.</para> 1.9689 + </listitem></itemizedlist> 1.9690 + 1.9691 + </sect2> 1.9692 + <sect2> 1.9693 + <title>Beware interference between bugs</title> 1.9694 + 1.9695 + <para id="x_156">It's possible that your search for one bug could be 1.9696 + disrupted by the presence of another. For example, let's say 1.9697 + your software crashes at revision 100, and worked correctly at 1.9698 + revision 50. Unknown to you, someone else introduced a 1.9699 + different crashing bug at revision 60, and fixed it at 1.9700 + revision 80. This could distort your results in one of 1.9701 + several ways.</para> 1.9702 + 1.9703 + <para id="x_157">It is possible that this other bug completely 1.9704 + <quote>masks</quote> yours, which is to say that it occurs 1.9705 + before your bug has a chance to manifest itself. If you can't 1.9706 + avoid that other bug (for example, it prevents your project 1.9707 + from building), and so can't tell whether your bug is present 1.9708 + in a particular changeset, the <command role="hg-cmd" moreinfo="none">hg 1.9709 + bisect</command> command cannot help you directly. Instead, 1.9710 + you can mark a changeset as untested by running <command role="hg-cmd" moreinfo="none">hg bisect --skip</command>.</para> 1.9711 + 1.9712 + <para id="x_158">A different problem could arise if your test for a bug's 1.9713 + presence is not specific enough. If you check for <quote>my 1.9714 + program crashes</quote>, then both your crashing bug and an 1.9715 + unrelated crashing bug that masks it will look like the same 1.9716 + thing, and mislead <command role="hg-cmd" moreinfo="none">hg 1.9717 + bisect</command>.</para> 1.9718 + 1.9719 + <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 1.9720 + test a revision because your project was in a broken and hence 1.9721 + untestable state at that revision, perhaps because someone 1.9722 + checked in a change that prevented the project from 1.9723 + building.</para> 1.9724 + 1.9725 + </sect2> 1.9726 + <sect2> 1.9727 + <title>Bracket your search lazily</title> 1.9728 + 1.9729 + <para id="x_15a">Choosing the first <quote>good</quote> and 1.9730 + <quote>bad</quote> changesets that will mark the end points of 1.9731 + your search is often easy, but it bears a little discussion 1.9732 + nevertheless. From the perspective of <command role="hg-cmd" moreinfo="none">hg bisect</command>, the <quote>newest</quote> 1.9733 + changeset is conventionally <quote>bad</quote>, and the older 1.9734 + changeset is <quote>good</quote>.</para> 1.9735 + 1.9736 + <para id="x_15b">If you're having trouble remembering when a suitable 1.9737 + <quote>good</quote> change was, so that you can tell <command role="hg-cmd" moreinfo="none">hg bisect</command>, you could do worse than 1.9738 + testing changesets at random. Just remember to eliminate 1.9739 + contenders that can't possibly exhibit the bug (perhaps 1.9740 + because the feature with the bug isn't present yet) and those 1.9741 + where another problem masks the bug (as I discussed 1.9742 + above).</para> 1.9743 + 1.9744 + <para id="x_15c">Even if you end up <quote>early</quote> by thousands of 1.9745 + changesets or months of history, you will only add a handful 1.9746 + of tests to the total number that <command role="hg-cmd" moreinfo="none">hg 1.9747 + bisect</command> must perform, thanks to its logarithmic 1.9748 + behavior.</para> 1.9749 + 1.9750 + </sect2> 1.9751 + </sect1> 1.9752 +</chapter> 1.9753 + 1.9754 +<!-- 1.9755 +local variables: 1.9756 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.9757 +end: 1.9758 +--> 1.9759 + 1.9760 + <!-- BEGIN ch10 --> 1.9761 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.9762 + 1.9763 +<chapter id="chap:hook"> 1.9764 + <?dbhtml filename="handling-repository-events-with-hooks.html"?> 1.9765 + <title>Handling repository events with hooks</title> 1.9766 + 1.9767 + <para id="x_1e6">Mercurial offers a powerful mechanism to let you perform 1.9768 + automated actions in response to events that occur in a 1.9769 + repository. In some cases, you can even control Mercurial's 1.9770 + response to those events.</para> 1.9771 + 1.9772 + <para id="x_1e7">The name Mercurial uses for one of these actions is a 1.9773 + <emphasis>hook</emphasis>. Hooks are called 1.9774 + <quote>triggers</quote> in some revision control systems, but the 1.9775 + two names refer to the same idea.</para> 1.9776 + 1.9777 + <sect1> 1.9778 + <title>An overview of hooks in Mercurial</title> 1.9779 + 1.9780 + <para id="x_1e8">Here is a brief list of the hooks that Mercurial 1.9781 + supports. We will revisit each of these hooks in more detail 1.9782 + later, in <xref linkend="sec:hook:ref"/>.</para> 1.9783 + 1.9784 + <para id="x_1f6">Each of the hooks whose description begins with the word 1.9785 + <quote>Controlling</quote> has the ability to determine whether 1.9786 + an activity can proceed. If the hook succeeds, the activity may 1.9787 + proceed; if it fails, the activity is either not permitted or 1.9788 + undone, depending on the hook.</para> 1.9789 + 1.9790 + <itemizedlist> 1.9791 + <listitem><para id="x_1e9"><literal role="hook" moreinfo="none">changegroup</literal>: This 1.9792 + is run after a group of changesets has been brought into the 1.9793 + repository from elsewhere.</para> 1.9794 + </listitem> 1.9795 + <listitem><para id="x_1ea"><literal role="hook" moreinfo="none">commit</literal>: This is 1.9796 + run after a new changeset has been created in the local 1.9797 + repository.</para> 1.9798 + </listitem> 1.9799 + <listitem><para id="x_1eb"><literal role="hook" moreinfo="none">incoming</literal>: This is 1.9800 + run once for each new changeset that is brought into the 1.9801 + repository from elsewhere. Notice the difference from 1.9802 + <literal role="hook" moreinfo="none">changegroup</literal>, which is run 1.9803 + once per <emphasis>group</emphasis> of changesets brought 1.9804 + in.</para> 1.9805 + </listitem> 1.9806 + <listitem><para id="x_1ec"><literal role="hook" moreinfo="none">outgoing</literal>: This is 1.9807 + run after a group of changesets has been transmitted from 1.9808 + this repository.</para> 1.9809 + </listitem> 1.9810 + <listitem><para id="x_1ed"><literal role="hook" moreinfo="none">prechangegroup</literal>: 1.9811 + This is run before starting to bring a group of changesets 1.9812 + into the repository. 1.9813 + </para> 1.9814 + </listitem> 1.9815 + <listitem><para id="x_1ee"><literal role="hook" moreinfo="none">precommit</literal>: 1.9816 + Controlling. This is run before starting a commit. 1.9817 + </para> 1.9818 + </listitem> 1.9819 + <listitem><para id="x_1ef"><literal role="hook" moreinfo="none">preoutgoing</literal>: 1.9820 + Controlling. This is run before starting to transmit a group 1.9821 + of changesets from this repository. 1.9822 + </para> 1.9823 + </listitem> 1.9824 + <listitem><para id="x_1f0"><literal role="hook" moreinfo="none">pretag</literal>: 1.9825 + Controlling. This is run before creating a tag. 1.9826 + </para> 1.9827 + </listitem> 1.9828 + <listitem><para id="x_1f1"><literal role="hook" moreinfo="none">pretxnchangegroup</literal>: Controlling. This 1.9829 + is run after a group of changesets has been brought into the 1.9830 + local repository from another, but before the transaction 1.9831 + completes that will make the changes permanent in the 1.9832 + repository. 1.9833 + </para> 1.9834 + </listitem> 1.9835 + <listitem><para id="x_1f2"><literal role="hook" moreinfo="none">pretxncommit</literal>: 1.9836 + Controlling. This is run after a new changeset has been 1.9837 + created in the local repository, but before the transaction 1.9838 + completes that will make it permanent. 1.9839 + </para> 1.9840 + </listitem> 1.9841 + <listitem><para id="x_1f3"><literal role="hook" moreinfo="none">preupdate</literal>: 1.9842 + Controlling. This is run before starting an update or merge 1.9843 + of the working directory. 1.9844 + </para> 1.9845 + </listitem> 1.9846 + <listitem><para id="x_1f4"><literal role="hook" moreinfo="none">tag</literal>: This is run 1.9847 + after a tag is created. 1.9848 + </para> 1.9849 + </listitem> 1.9850 + <listitem><para id="x_1f5"><literal role="hook" moreinfo="none">update</literal>: This is 1.9851 + run after an update or merge of the working directory has 1.9852 + finished. 1.9853 + </para> 1.9854 + </listitem></itemizedlist> 1.9855 + 1.9856 + </sect1> 1.9857 + <sect1> 1.9858 + <title>Hooks and security</title> 1.9859 + 1.9860 + <sect2> 1.9861 + <title>Hooks are run with your privileges</title> 1.9862 + 1.9863 + <para id="x_1f7">When you run a Mercurial command in a repository, and the 1.9864 + command causes a hook to run, that hook runs on 1.9865 + <emphasis>your</emphasis> system, under 1.9866 + <emphasis>your</emphasis> user account, with 1.9867 + <emphasis>your</emphasis> privilege level. Since hooks are 1.9868 + arbitrary pieces of executable code, you should treat them 1.9869 + with an appropriate level of suspicion. Do not install a hook 1.9870 + unless you are confident that you know who created it and what 1.9871 + it does. 1.9872 + </para> 1.9873 + 1.9874 + <para id="x_1f8">In some cases, you may be exposed to hooks that you did 1.9875 + not install yourself. If you work with Mercurial on an 1.9876 + unfamiliar system, Mercurial will run hooks defined in that 1.9877 + system's global <filename role="special" moreinfo="none">~/.hgrc</filename> 1.9878 + file. 1.9879 + </para> 1.9880 + 1.9881 + <para id="x_1f9">If you are working with a repository owned by another 1.9882 + user, Mercurial can run hooks defined in that user's 1.9883 + repository, but it will still run them as <quote>you</quote>. 1.9884 + For example, if you <command role="hg-cmd" moreinfo="none">hg pull</command> 1.9885 + 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 1.9886 + under your user account, even though you don't own that 1.9887 + repository. 1.9888 + </para> 1.9889 + 1.9890 + <note> 1.9891 + <para id="x_1fa"> This only applies if you are pulling from a repository 1.9892 + on a local or network filesystem. If you're pulling over 1.9893 + http or ssh, any <literal role="hook" moreinfo="none">outgoing</literal> 1.9894 + hook will run under whatever account is executing the server 1.9895 + process, on the server. 1.9896 + </para> 1.9897 + </note> 1.9898 + 1.9899 + <para id="x_1fb">To see what hooks are defined in a repository, 1.9900 + use the <command role="hg-cmd" moreinfo="none">hg showconfig hooks</command> 1.9901 + command. If you are working in one repository, but talking to 1.9902 + 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 1.9903 + incoming</command>), remember that it is the other 1.9904 + repository's hooks you should be checking, not your own. 1.9905 + </para> 1.9906 + </sect2> 1.9907 + 1.9908 + <sect2> 1.9909 + <title>Hooks do not propagate</title> 1.9910 + 1.9911 + <para id="x_1fc">In Mercurial, hooks are not revision controlled, and do 1.9912 + not propagate when you clone, or pull from, a repository. The 1.9913 + reason for this is simple: a hook is a completely arbitrary 1.9914 + piece of executable code. It runs under your user identity, 1.9915 + with your privilege level, on your machine. 1.9916 + </para> 1.9917 + 1.9918 + <para id="x_1fd">It would be extremely reckless for any distributed 1.9919 + revision control system to implement revision-controlled 1.9920 + hooks, as this would offer an easily exploitable way to 1.9921 + subvert the accounts of users of the revision control system. 1.9922 + </para> 1.9923 + 1.9924 + <para id="x_1fe">Since Mercurial does not propagate hooks, if you are 1.9925 + collaborating with other people on a common project, you 1.9926 + should not assume that they are using the same Mercurial hooks 1.9927 + as you are, or that theirs are correctly configured. You 1.9928 + should document the hooks you expect people to use. 1.9929 + </para> 1.9930 + 1.9931 + <para id="x_1ff">In a corporate intranet, this is somewhat easier to 1.9932 + control, as you can for example provide a 1.9933 + <quote>standard</quote> installation of Mercurial on an NFS 1.9934 + filesystem, and use a site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file to define hooks that all users will 1.9935 + see. However, this too has its limits; see below. 1.9936 + </para> 1.9937 + </sect2> 1.9938 + 1.9939 + <sect2> 1.9940 + <title>Hooks can be overridden</title> 1.9941 + 1.9942 + <para id="x_200">Mercurial allows you to override a hook definition by 1.9943 + redefining the hook. You can disable it by setting its value 1.9944 + to the empty string, or change its behavior as you wish. 1.9945 + </para> 1.9946 + 1.9947 + <para id="x_201">If you deploy a system- or site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file that defines some 1.9948 + hooks, you should thus understand that your users can disable 1.9949 + or override those hooks. 1.9950 + </para> 1.9951 + </sect2> 1.9952 + 1.9953 + <sect2> 1.9954 + <title>Ensuring that critical hooks are run</title> 1.9955 + 1.9956 + <para id="x_202">Sometimes you may want to enforce a policy that you do not 1.9957 + want others to be able to work around. For example, you may 1.9958 + have a requirement that every changeset must pass a rigorous 1.9959 + set of tests. Defining this requirement via a hook in a 1.9960 + site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> won't 1.9961 + work for remote users on laptops, and of course local users 1.9962 + can subvert it at will by overriding the hook. 1.9963 + </para> 1.9964 + 1.9965 + <para id="x_203">Instead, you can set up your policies for use of Mercurial 1.9966 + so that people are expected to propagate changes through a 1.9967 + well-known <quote>canonical</quote> server that you have 1.9968 + locked down and configured appropriately. 1.9969 + </para> 1.9970 + 1.9971 + <para id="x_204">One way to do this is via a combination of social 1.9972 + engineering and technology. Set up a restricted-access 1.9973 + account; users can push changes over the network to 1.9974 + repositories managed by this account, but they cannot log into 1.9975 + the account and run normal shell commands. In this scenario, 1.9976 + a user can commit a changeset that contains any old garbage 1.9977 + they want. 1.9978 + </para> 1.9979 + 1.9980 + <para id="x_205">When someone pushes a changeset to the server that 1.9981 + everyone pulls from, the server will test the changeset before 1.9982 + it accepts it as permanent, and reject it if it fails to pass 1.9983 + the test suite. If people only pull changes from this 1.9984 + filtering server, it will serve to ensure that all changes 1.9985 + that people pull have been automatically vetted. 1.9986 + </para> 1.9987 + 1.9988 + </sect2> 1.9989 + </sect1> 1.9990 + 1.9991 + <sect1 id="sec:hook:simple"> 1.9992 + <title>A short tutorial on using hooks</title> 1.9993 + 1.9994 + <para id="x_212">It is easy to write a Mercurial hook. Let's start with a 1.9995 + hook that runs when you finish a <command role="hg-cmd" moreinfo="none">hg 1.9996 + commit</command>, and simply prints the hash of the changeset 1.9997 + you just created. The hook is called <literal role="hook" moreinfo="none">commit</literal>. 1.9998 + </para> 1.9999 + 1.10000 + <para id="x_213">All hooks follow the pattern in this example.</para> 1.10001 + 1.10002 +<!-- BEGIN hook.simple.init --> 1.10003 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hook-test</userinput> 1.10004 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hook-test</userinput> 1.10005 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '[hooks]' >> .hg/hgrc</userinput> 1.10006 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit = echo committed $HG_NODE' >> .hg/hgrc</userinput> 1.10007 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> 1.10008 +[hooks] 1.10009 +commit = echo committed $HG_NODE 1.10010 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.10011 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> 1.10012 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'testing commit hook'</userinput> 1.10013 +committed 13a334d1e5ca83fea465aa779110eec3c5ddd6b1 1.10014 +</screen> 1.10015 +<!-- END hook.simple.init --> 1.10016 + 1.10017 + 1.10018 + <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 1.10019 + the event to trigger on; on the right is the action to take. As 1.10020 + you can see, you can run an arbitrary shell command in a hook. 1.10021 + Mercurial passes extra information to the hook using environment 1.10022 + variables (look for <envar>HG_NODE</envar> in the example). 1.10023 + </para> 1.10024 + 1.10025 + <sect2> 1.10026 + <title>Performing multiple actions per event</title> 1.10027 + 1.10028 + <para id="x_215">Quite often, you will want to define more than one hook 1.10029 + for a particular kind of event, as shown below.</para> 1.10030 + 1.10031 +<!-- BEGIN hook.simple.ext --> 1.10032 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit.when = echo -n "date of commit: "; date' >> .hg/hgrc</userinput> 1.10033 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a >> a</userinput> 1.10034 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i have two hooks'</userinput> 1.10035 +committed 3be6e2778fb853cbc7e5138d0b9c29386504670b 1.10036 +date of commit: Sun Aug 16 14:05:05 GMT 2009 1.10037 +</screen> 1.10038 +<!-- END hook.simple.ext --> 1.10039 + 1.10040 + 1.10041 + <para id="x_216">Mercurial lets you do this by adding an 1.10042 + <emphasis>extension</emphasis> to the end of a hook's name. 1.10043 + You extend a hook's name by giving the name of the hook, 1.10044 + followed by a full stop (the 1.10045 + <quote><literal moreinfo="none">.</literal></quote> character), followed by 1.10046 + some more text of your choosing. For example, Mercurial will 1.10047 + run both <literal moreinfo="none">commit.foo</literal> and 1.10048 + <literal moreinfo="none">commit.bar</literal> when the 1.10049 + <literal moreinfo="none">commit</literal> event occurs. 1.10050 + </para> 1.10051 + 1.10052 + <para id="x_217">To give a well-defined order of execution when there are 1.10053 + multiple hooks defined for an event, Mercurial sorts hooks by 1.10054 + extension, and executes the hook commands in this sorted 1.10055 + order. In the above example, it will execute 1.10056 + <literal moreinfo="none">commit.bar</literal> before 1.10057 + <literal moreinfo="none">commit.foo</literal>, and <literal moreinfo="none">commit</literal> 1.10058 + before both. 1.10059 + </para> 1.10060 + 1.10061 + <para id="x_218">It is a good idea to use a somewhat descriptive 1.10062 + extension when you define a new hook. This will help you to 1.10063 + remember what the hook was for. If the hook fails, you'll get 1.10064 + an error message that contains the hook name and extension, so 1.10065 + using a descriptive extension could give you an immediate hint 1.10066 + as to why the hook failed (see <xref linkend="sec:hook:perm"/> for an example). 1.10067 + </para> 1.10068 + 1.10069 + </sect2> 1.10070 + <sect2 id="sec:hook:perm"> 1.10071 + <title>Controlling whether an activity can proceed</title> 1.10072 + 1.10073 + <para id="x_219">In our earlier examples, we used the <literal role="hook" moreinfo="none">commit</literal> hook, which is run after a 1.10074 + commit has completed. This is one of several Mercurial hooks 1.10075 + that run after an activity finishes. Such hooks have no way 1.10076 + of influencing the activity itself. 1.10077 + </para> 1.10078 + 1.10079 + <para id="x_21a">Mercurial defines a number of events that occur before an 1.10080 + activity starts; or after it starts, but before it finishes. 1.10081 + Hooks that trigger on these events have the added ability to 1.10082 + choose whether the activity can continue, or will abort. 1.10083 + </para> 1.10084 + 1.10085 + <para id="x_21b">The <literal role="hook" moreinfo="none">pretxncommit</literal> hook runs 1.10086 + after a commit has all but completed. In other words, the 1.10087 + metadata representing the changeset has been written out to 1.10088 + disk, but the transaction has not yet been allowed to 1.10089 + complete. The <literal role="hook" moreinfo="none">pretxncommit</literal> 1.10090 + hook has the ability to decide whether the transaction can 1.10091 + complete, or must be rolled back. 1.10092 + </para> 1.10093 + 1.10094 + <para id="x_21c">If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook 1.10095 + exits with a status code of zero, the transaction is allowed 1.10096 + 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 1.10097 + non-zero status code, the transaction is rolled back; the 1.10098 + metadata representing the changeset is erased; and the 1.10099 + <literal role="hook" moreinfo="none">commit</literal> hook is not run. 1.10100 + </para> 1.10101 + 1.10102 +<!-- BEGIN hook.simple.pretxncommit --> 1.10103 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat check_bug_id</userinput> 1.10104 +#!/bin/sh 1.10105 +# check that a commit comment mentions a numeric bug id 1.10106 +hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]" 1.10107 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc</userinput> 1.10108 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a >> a</userinput> 1.10109 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i am not mentioning a bug id'</userinput> 1.10110 +transaction abort! 1.10111 +rollback completed 1.10112 +abort: pretxncommit.bug_id_required hook exited with status 1 1.10113 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i refer you to bug 666'</userinput> 1.10114 +committed 1a52be73a1ca4fa05e269f99003ed00912e8e836 1.10115 +date of commit: Sun Aug 16 14:05:05 GMT 2009 1.10116 +</screen> 1.10117 +<!-- END hook.simple.pretxncommit --> 1.10118 + 1.10119 + 1.10120 + <para id="x_21d">The hook in the example above checks that a commit comment 1.10121 + contains a bug ID. If it does, the commit can complete. If 1.10122 + not, the commit is rolled back. 1.10123 + </para> 1.10124 + 1.10125 + </sect2> 1.10126 + </sect1> 1.10127 + <sect1> 1.10128 + <title>Writing your own hooks</title> 1.10129 + 1.10130 + <para id="x_21e">When you are writing a hook, you might find it useful to run 1.10131 + 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 1.10132 + <quote>true</quote>. When you do so, Mercurial will print a 1.10133 + message before it calls each hook. 1.10134 + </para> 1.10135 + 1.10136 + <sect2 id="sec:hook:lang"> 1.10137 + <title>Choosing how your hook should run</title> 1.10138 + 1.10139 + <para id="x_21f">You can write a hook either as a normal 1.10140 + program—typically a shell script—or as a Python 1.10141 + function that is executed within the Mercurial process. 1.10142 + </para> 1.10143 + 1.10144 + <para id="x_220">Writing a hook as an external program has the advantage 1.10145 + that it requires no knowledge of Mercurial's internals. You 1.10146 + can call normal Mercurial commands to get any added 1.10147 + information you need. The trade-off is that external hooks 1.10148 + are slower than in-process hooks. 1.10149 + </para> 1.10150 + 1.10151 + <para id="x_221">An in-process Python hook has complete access to the 1.10152 + Mercurial API, and does not <quote>shell out</quote> to 1.10153 + another process, so it is inherently faster than an external 1.10154 + hook. It is also easier to obtain much of the information 1.10155 + that a hook requires by using the Mercurial API than by 1.10156 + running Mercurial commands. 1.10157 + </para> 1.10158 + 1.10159 + <para id="x_222">If you are comfortable with Python, or require high 1.10160 + performance, writing your hooks in Python may be a good 1.10161 + choice. However, when you have a straightforward hook to 1.10162 + write and you don't need to care about performance (probably 1.10163 + the majority of hooks), a shell script is perfectly fine. 1.10164 + </para> 1.10165 + 1.10166 + </sect2> 1.10167 + <sect2 id="sec:hook:param"> 1.10168 + <title>Hook parameters</title> 1.10169 + 1.10170 + <para id="x_223">Mercurial calls each hook with a set of well-defined 1.10171 + parameters. In Python, a parameter is passed as a keyword 1.10172 + argument to your hook function. For an external program, a 1.10173 + parameter is passed as an environment variable. 1.10174 + </para> 1.10175 + 1.10176 + <para id="x_224">Whether your hook is written in Python or as a shell 1.10177 + script, the hook-specific parameter names and values will be 1.10178 + the same. A boolean parameter will be represented as a 1.10179 + boolean value in Python, but as the number 1 (for 1.10180 + <quote>true</quote>) or 0 (for <quote>false</quote>) as an 1.10181 + environment variable for an external hook. If a hook 1.10182 + parameter is named <literal moreinfo="none">foo</literal>, the keyword 1.10183 + argument for a Python hook will also be named 1.10184 + <literal moreinfo="none">foo</literal>, while the environment variable for an 1.10185 + external hook will be named <literal moreinfo="none">HG_FOO</literal>. 1.10186 + </para> 1.10187 + </sect2> 1.10188 + 1.10189 + <sect2> 1.10190 + <title>Hook return values and activity control</title> 1.10191 + 1.10192 + <para id="x_225">A hook that executes successfully must exit with a status 1.10193 + of zero if external, or return boolean <quote>false</quote> if 1.10194 + in-process. Failure is indicated with a non-zero exit status 1.10195 + from an external hook, or an in-process hook returning boolean 1.10196 + <quote>true</quote>. If an in-process hook raises an 1.10197 + exception, the hook is considered to have failed. 1.10198 + </para> 1.10199 + 1.10200 + <para id="x_226">For a hook that controls whether an activity can proceed, 1.10201 + zero/false means <quote>allow</quote>, while 1.10202 + non-zero/true/exception means <quote>deny</quote>. 1.10203 + </para> 1.10204 + </sect2> 1.10205 + 1.10206 + <sect2> 1.10207 + <title>Writing an external hook</title> 1.10208 + 1.10209 + <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 1.10210 + value is passed to your shell, which interprets it. This 1.10211 + means that you can use normal shell constructs in the body of 1.10212 + the hook. 1.10213 + </para> 1.10214 + 1.10215 + <para id="x_228">An executable hook is always run with its current 1.10216 + directory set to a repository's root directory. 1.10217 + </para> 1.10218 + 1.10219 + <para id="x_229">Each hook parameter is passed in as an environment 1.10220 + variable; the name is upper-cased, and prefixed with the 1.10221 + string <quote><literal moreinfo="none">HG_</literal></quote>. 1.10222 + </para> 1.10223 + 1.10224 + <para id="x_22a">With the exception of hook parameters, Mercurial does not 1.10225 + set or modify any environment variables when running a hook. 1.10226 + This is useful to remember if you are writing a site-wide hook 1.10227 + that may be run by a number of different users with differing 1.10228 + environment variables set. In multi-user situations, you 1.10229 + should not rely on environment variables being set to the 1.10230 + values you have in your environment when testing the hook. 1.10231 + </para> 1.10232 + </sect2> 1.10233 + 1.10234 + <sect2> 1.10235 + <title>Telling Mercurial to use an in-process hook</title> 1.10236 + 1.10237 + <para id="x_22b">The <filename role="special" moreinfo="none">~/.hgrc</filename> syntax 1.10238 + for defining an in-process hook is slightly different than for 1.10239 + an executable hook. The value of the hook must start with the 1.10240 + text <quote><literal moreinfo="none">python:</literal></quote>, and continue 1.10241 + with the fully-qualified name of a callable object to use as 1.10242 + the hook's value. 1.10243 + </para> 1.10244 + 1.10245 + <para id="x_22c">The module in which a hook lives is automatically imported 1.10246 + when a hook is run. So long as you have the module name and 1.10247 + <envar>PYTHONPATH</envar> right, it should <quote>just 1.10248 + work</quote>. 1.10249 + </para> 1.10250 + 1.10251 + <para id="x_22d">The following <filename role="special" moreinfo="none">~/.hgrc</filename> 1.10252 + example snippet illustrates the syntax and meaning of the 1.10253 + notions we just described. 1.10254 + </para> 1.10255 + <programlisting format="linespecific">[hooks] 1.10256 +commit.example = python:mymodule.submodule.myhook</programlisting> 1.10257 + <para id="x_22e">When Mercurial runs the <literal moreinfo="none">commit.example</literal> 1.10258 + hook, it imports <literal moreinfo="none">mymodule.submodule</literal>, looks 1.10259 + for the callable object named <literal moreinfo="none">myhook</literal>, and 1.10260 + calls it. 1.10261 + </para> 1.10262 + </sect2> 1.10263 + 1.10264 + <sect2> 1.10265 + <title>Writing an in-process hook</title> 1.10266 + 1.10267 + <para id="x_22f">The simplest in-process hook does nothing, but illustrates 1.10268 + the basic shape of the hook API: 1.10269 + </para> 1.10270 + <programlisting format="linespecific">def myhook(ui, repo, **kwargs): 1.10271 + pass</programlisting> 1.10272 + <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 1.10273 + is a repository object; at the moment, it is always an 1.10274 + instance of <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal>. 1.10275 + Following these two arguments are other keyword arguments. 1.10276 + Which ones are passed in depends on the hook being called, but 1.10277 + a hook can ignore arguments it doesn't care about by dropping 1.10278 + them into a keyword argument dict, as with 1.10279 + <literal moreinfo="none">**kwargs</literal> above. 1.10280 + </para> 1.10281 + 1.10282 + </sect2> 1.10283 + </sect1> 1.10284 + <sect1> 1.10285 + <title>Some hook examples</title> 1.10286 + 1.10287 + <sect2> 1.10288 + <title>Writing meaningful commit messages</title> 1.10289 + 1.10290 + <para id="x_231">It's hard to imagine a useful commit message being very 1.10291 + short. The simple <literal role="hook" moreinfo="none">pretxncommit</literal> 1.10292 + hook of the example below will prevent you from committing a 1.10293 + changeset with a message that is less than ten bytes long. 1.10294 + </para> 1.10295 + 1.10296 +<!-- BEGIN hook.msglen.go --> 1.10297 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> 1.10298 +[hooks] 1.10299 +pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10 1.10300 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.10301 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> 1.10302 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'too short'</userinput> 1.10303 +transaction abort! 1.10304 +rollback completed 1.10305 +abort: pretxncommit.msglen hook exited with status 1 1.10306 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'long enough'</userinput> 1.10307 +</screen> 1.10308 +<!-- END hook.msglen.go --> 1.10309 + 1.10310 + </sect2> 1.10311 + 1.10312 + <sect2> 1.10313 + <title>Checking for trailing whitespace</title> 1.10314 + 1.10315 + <para id="x_232">An interesting use of a commit-related hook is to help you 1.10316 + to write cleaner code. A simple example of <quote>cleaner 1.10317 + code</quote> is the dictum that a change should not add any 1.10318 + new lines of text that contain <quote>trailing 1.10319 + whitespace</quote>. Trailing whitespace is a series of 1.10320 + space and tab characters at the end of a line of text. In 1.10321 + most cases, trailing whitespace is unnecessary, invisible 1.10322 + noise, but it is occasionally problematic, and people often 1.10323 + prefer to get rid of it. 1.10324 + </para> 1.10325 + 1.10326 + <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 1.10327 + have a trailing whitespace problem. If you use the <literal role="hook" moreinfo="none">precommit</literal> hook, the hook will not know 1.10328 + which files you are committing, so it will have to check every 1.10329 + modified file in the repository for trailing white space. If 1.10330 + you want to commit a change to just the file 1.10331 + <filename moreinfo="none">foo</filename>, but the file 1.10332 + <filename moreinfo="none">bar</filename> contains trailing whitespace, doing a 1.10333 + check in the <literal role="hook" moreinfo="none">precommit</literal> hook 1.10334 + will prevent you from committing <filename moreinfo="none">foo</filename> due 1.10335 + to the problem with <filename moreinfo="none">bar</filename>. This doesn't 1.10336 + seem right. 1.10337 + </para> 1.10338 + 1.10339 + <para id="x_234">Should you choose the <literal role="hook" moreinfo="none">pretxncommit</literal> hook, the check won't 1.10340 + occur until just before the transaction for the commit 1.10341 + completes. This will allow you to check for problems only the 1.10342 + exact files that are being committed. However, if you entered 1.10343 + the commit message interactively and the hook fails, the 1.10344 + transaction will roll back; you'll have to re-enter the commit 1.10345 + message after you fix the trailing whitespace and run <command role="hg-cmd" moreinfo="none">hg commit</command> again. 1.10346 + </para> 1.10347 + 1.10348 + <!-- BEGIN ch09/hook.ws.simple --> 1.10349 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> 1.10350 +[hooks] 1.10351 +pretxncommit.whitespace = hg export tip | (! egrep -q '^\+.*[ \t]$') 1.10352 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' > a</userinput> 1.10353 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'test with trailing whitespace'</userinput> 1.10354 +adding a 1.10355 +transaction abort! 1.10356 +rollback completed 1.10357 +abort: pretxncommit.whitespace hook exited with status 1 1.10358 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a' > a</userinput> 1.10359 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'drop trailing whitespace and try again'</userinput> 1.10360 +</screen> 1.10361 +<!-- END ch09/hook.ws.simple --> 1.10362 + 1.10363 + 1.10364 + <para id="x_235">In this example, we introduce a simple <literal role="hook" moreinfo="none">pretxncommit</literal> hook that checks for 1.10365 + trailing whitespace. This hook is short, but not very 1.10366 + helpful. It exits with an error status if a change adds a 1.10367 + line with trailing whitespace to any file, but does not print 1.10368 + any information that might help us to identify the offending 1.10369 + file or line. It also has the nice property of not paying 1.10370 + attention to unmodified lines; only lines that introduce new 1.10371 + trailing whitespace cause problems. 1.10372 + </para> 1.10373 + 1.10374 + <!-- BEGIN ch09/check_whitespace.py.lst --> 1.10375 +<programlisting format="linespecific">#!/usr/bin/env python 1.10376 +# 1.10377 +# save as .hg/check_whitespace.py and make executable 1.10378 + 1.10379 +import re 1.10380 + 1.10381 +def trailing_whitespace(difflines): 1.10382 + # 1.10383 + linenum, header = 0, False 1.10384 + 1.10385 + for line in difflines: 1.10386 + if header: 1.10387 + # remember the name of the file that this diff affects 1.10388 + m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line) 1.10389 + if m and m.group(1) != '/dev/null': 1.10390 + filename = m.group(1).split('/', 1)[-1] 1.10391 + if line.startswith('+++ '): 1.10392 + header = False 1.10393 + continue 1.10394 + if line.startswith('diff '): 1.10395 + header = True 1.10396 + continue 1.10397 + # hunk header - save the line number 1.10398 + m = re.match(r'@@ -\d+,\d+ \+(\d+),', line) 1.10399 + if m: 1.10400 + linenum = int(m.group(1)) 1.10401 + continue 1.10402 + # hunk body - check for an added line with trailing whitespace 1.10403 + m = re.match(r'\+.*\s$', line) 1.10404 + if m: 1.10405 + yield filename, linenum 1.10406 + if line and line[0] in ' +': 1.10407 + linenum += 1 1.10408 + 1.10409 +if __name__ == '__main__': 1.10410 + import os, sys 1.10411 + 1.10412 + added = 0 1.10413 + for filename, linenum in trailing_whitespace(os.popen('hg export tip')): 1.10414 + print >> sys.stderr, ('%s, line %d: trailing whitespace added' % 1.10415 + (filename, linenum)) 1.10416 + added += 1 1.10417 + if added: 1.10418 + # save the commit message so we don't need to retype it 1.10419 + os.system('hg tip --template "{desc}" > .hg/commit.save') 1.10420 + print >> sys.stderr, 'commit message saved to .hg/commit.save' 1.10421 + sys.exit(1)</programlisting> 1.10422 +<!-- END ch09/check_whitespace.py.lst --> 1.10423 + 1.10424 + 1.10425 + <para id="x_236">The above version is much more complex, but also more 1.10426 + useful. It parses a unified diff to see if any lines add 1.10427 + trailing whitespace, and prints the name of the file and the 1.10428 + line number of each such occurrence. Even better, if the 1.10429 + change adds trailing whitespace, this hook saves the commit 1.10430 + comment and prints the name of the save file before exiting 1.10431 + and telling Mercurial to roll the transaction back, so you can 1.10432 + use the <option role="hg-opt-commit">-l filename</option> 1.10433 + option to <command role="hg-cmd" moreinfo="none">hg commit</command> to reuse 1.10434 + the saved commit message once you've corrected the problem. 1.10435 + </para> 1.10436 + 1.10437 + <!-- BEGIN ch09/hook.ws.better --> 1.10438 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> 1.10439 +[hooks] 1.10440 +pretxncommit.whitespace = .hg/check_whitespace.py 1.10441 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' >> a</userinput> 1.10442 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'add new line with trailing whitespace'</userinput> 1.10443 +a, line 2: trailing whitespace added 1.10444 +commit message saved to .hg/commit.save 1.10445 +transaction abort! 1.10446 +rollback completed 1.10447 +abort: pretxncommit.whitespace hook exited with status 1 1.10448 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">sed -i 's, *$,,' a</userinput> 1.10449 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'trimmed trailing whitespace'</userinput> 1.10450 +a, line 2: trailing whitespace added 1.10451 +commit message saved to .hg/commit.save 1.10452 +transaction abort! 1.10453 +rollback completed 1.10454 +abort: pretxncommit.whitespace hook exited with status 1 1.10455 +</screen> 1.10456 +<!-- END ch09/hook.ws.better --> 1.10457 + 1.10458 + 1.10459 + <para id="x_237">As a final aside, note in the example above the 1.10460 + use of <command moreinfo="none">sed</command>'s in-place editing feature to 1.10461 + get rid of trailing whitespace from a file. This is concise 1.10462 + and useful enough that I will reproduce it here (using 1.10463 + <command moreinfo="none">perl</command> for good measure).</para> 1.10464 + <programlisting format="linespecific">perl -pi -e 's,\s+$,,' filename</programlisting> 1.10465 + 1.10466 + </sect2> 1.10467 + </sect1> 1.10468 + <sect1> 1.10469 + <title>Bundled hooks</title> 1.10470 + 1.10471 + <para id="x_238">Mercurial ships with several bundled hooks. You can find 1.10472 + them in the <filename class="directory" moreinfo="none">hgext</filename> 1.10473 + directory of a Mercurial source tree. If you are using a 1.10474 + Mercurial binary package, the hooks will be located in the 1.10475 + <filename class="directory" moreinfo="none">hgext</filename> directory of 1.10476 + wherever your package installer put Mercurial. 1.10477 + </para> 1.10478 + 1.10479 + <sect2> 1.10480 + <title><literal role="hg-ext" moreinfo="none">acl</literal>—access 1.10481 + control for parts of a repository</title> 1.10482 + 1.10483 + <para id="x_239">The <literal role="hg-ext" moreinfo="none">acl</literal> extension lets 1.10484 + you control which remote users are allowed to push changesets 1.10485 + to a networked server. You can protect any portion of a 1.10486 + repository (including the entire repo), so that a specific 1.10487 + remote user can push changes that do not affect the protected 1.10488 + portion. 1.10489 + </para> 1.10490 + 1.10491 + <para id="x_23a">This extension implements access control based on the 1.10492 + identity of the user performing a push, 1.10493 + <emphasis>not</emphasis> on who committed the changesets 1.10494 + they're pushing. It makes sense to use this hook only if you 1.10495 + have a locked-down server environment that authenticates 1.10496 + remote users, and you want to be sure that only specific users 1.10497 + are allowed to push changes to that server. 1.10498 + </para> 1.10499 + 1.10500 + <sect3> 1.10501 + <title>Configuring the <literal role="hook" moreinfo="none">acl</literal> 1.10502 + hook</title> 1.10503 + 1.10504 + <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 1.10505 + <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook. This 1.10506 + lets it see which files are modified by each incoming 1.10507 + changeset, and roll back a group of changesets if they 1.10508 + modify <quote>forbidden</quote> files. Example: 1.10509 + </para> 1.10510 + <programlisting format="linespecific">[hooks] 1.10511 +pretxnchangegroup.acl = python:hgext.acl.hook</programlisting> 1.10512 + 1.10513 + <para id="x_23c">The <literal role="hg-ext" moreinfo="none">acl</literal> extension is 1.10514 + configured using three sections. 1.10515 + </para> 1.10516 + 1.10517 + <para id="x_23d">The <literal role="rc-acl" moreinfo="none">acl</literal> section has 1.10518 + only one entry, <envar role="rc-item-acl">sources</envar>, 1.10519 + which lists the sources of incoming changesets that the hook 1.10520 + should pay attention to. You don't normally need to 1.10521 + configure this section. 1.10522 + </para> 1.10523 + <itemizedlist> 1.10524 + <listitem><para id="x_23e"><envar role="rc-item-acl">serve</envar>: 1.10525 + Control incoming changesets that are arriving from a 1.10526 + remote repository over http or ssh. This is the default 1.10527 + value of <envar role="rc-item-acl">sources</envar>, and 1.10528 + usually the only setting you'll need for this 1.10529 + configuration item. 1.10530 + </para> 1.10531 + </listitem> 1.10532 + <listitem><para id="x_23f"><envar role="rc-item-acl">pull</envar>: 1.10533 + Control incoming changesets that are arriving via a pull 1.10534 + from a local repository. 1.10535 + </para> 1.10536 + </listitem> 1.10537 + <listitem><para id="x_240"><envar role="rc-item-acl">push</envar>: 1.10538 + Control incoming changesets that are arriving via a push 1.10539 + from a local repository. 1.10540 + </para> 1.10541 + </listitem> 1.10542 + <listitem><para id="x_241"><envar role="rc-item-acl">bundle</envar>: 1.10543 + Control incoming changesets that are arriving from 1.10544 + another repository via a bundle. 1.10545 + </para> 1.10546 + </listitem></itemizedlist> 1.10547 + 1.10548 + <para id="x_242">The <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal> 1.10549 + section controls the users that are allowed to add 1.10550 + changesets to the repository. If this section is not 1.10551 + present, all users that are not explicitly denied are 1.10552 + allowed. If this section is present, all users that are not 1.10553 + explicitly allowed are denied (so an empty section means 1.10554 + that all users are denied). 1.10555 + </para> 1.10556 + 1.10557 + <para id="x_243">The <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal> 1.10558 + section determines which users are denied from adding 1.10559 + changesets to the repository. If this section is not 1.10560 + present or is empty, no users are denied. 1.10561 + </para> 1.10562 + 1.10563 + <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 1.10564 + identical. On the left of each entry is a glob pattern that 1.10565 + matches files or directories, relative to the root of the 1.10566 + repository; on the right, a user name. 1.10567 + </para> 1.10568 + 1.10569 + <para id="x_245">In the following example, the user 1.10570 + <literal moreinfo="none">docwriter</literal> can only push changes to the 1.10571 + <filename class="directory" moreinfo="none">docs</filename> subtree of the 1.10572 + repository, while <literal moreinfo="none">intern</literal> can push changes 1.10573 + to any file or directory except <filename class="directory" moreinfo="none">source/sensitive</filename>. 1.10574 + </para> 1.10575 + <programlisting format="linespecific">[acl.allow] 1.10576 +docs/** = docwriter 1.10577 +[acl.deny] 1.10578 +source/sensitive/** = intern</programlisting> 1.10579 + 1.10580 + </sect3> 1.10581 + <sect3> 1.10582 + <title>Testing and troubleshooting</title> 1.10583 + 1.10584 + <para id="x_246">If you want to test the <literal role="hg-ext" moreinfo="none">acl</literal> hook, run it with Mercurial's 1.10585 + debugging output enabled. Since you'll probably be running 1.10586 + it on a server where it's not convenient (or sometimes 1.10587 + possible) to pass in the <option role="hg-opt-global">--debug</option> option, don't forget 1.10588 + that you can enable debugging output in your <filename role="special" moreinfo="none">~/.hgrc</filename>: 1.10589 + </para> 1.10590 + <programlisting format="linespecific">[ui] 1.10591 +debug = true</programlisting> 1.10592 + <para id="x_247">With this enabled, the <literal role="hg-ext" moreinfo="none">acl</literal> hook will print enough 1.10593 + information to let you figure out why it is allowing or 1.10594 + forbidding pushes from specific users. 1.10595 + </para> 1.10596 + 1.10597 + </sect3> </sect2> 1.10598 + 1.10599 + <sect2> 1.10600 + <title><literal role="hg-ext" moreinfo="none">bugzilla</literal>—integration with 1.10601 + Bugzilla</title> 1.10602 + 1.10603 + <para id="x_248">The <literal role="hg-ext" moreinfo="none">bugzilla</literal> extension 1.10604 + adds a comment to a Bugzilla bug whenever it finds a reference 1.10605 + to that bug ID in a commit comment. You can install this hook 1.10606 + on a shared server, so that any time a remote user pushes 1.10607 + changes to this server, the hook gets run. 1.10608 + </para> 1.10609 + 1.10610 + <para id="x_249">It adds a comment to the bug that looks like this (you can 1.10611 + configure the contents of the comment—see below): 1.10612 + </para> 1.10613 + <programlisting format="linespecific">Changeset aad8b264143a, made by Joe User 1.10614 + <joe.user@domain.com> in the frobnitz repository, refers 1.10615 + to this bug. For complete details, see 1.10616 + http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 1.10617 + Changeset description: Fix bug 10483 by guarding against some 1.10618 + NULL pointers</programlisting> 1.10619 + <para id="x_24a">The value of this hook is that it automates the process of 1.10620 + updating a bug any time a changeset refers to it. If you 1.10621 + configure the hook properly, it makes it easy for people to 1.10622 + browse straight from a Bugzilla bug to a changeset that refers 1.10623 + to that bug. 1.10624 + </para> 1.10625 + 1.10626 + <para id="x_24b">You can use the code in this hook as a starting point for 1.10627 + some more exotic Bugzilla integration recipes. Here are a few 1.10628 + possibilities: 1.10629 + </para> 1.10630 + <itemizedlist> 1.10631 + <listitem><para id="x_24c">Require that every changeset pushed to the 1.10632 + server have a valid bug ID in its commit comment. In this 1.10633 + case, you'd want to configure the hook as a <literal role="hook" moreinfo="none">pretxncommit</literal> hook. This would 1.10634 + allow the hook to reject changes that didn't contain bug 1.10635 + IDs. 1.10636 + </para> 1.10637 + </listitem> 1.10638 + <listitem><para id="x_24d">Allow incoming changesets to automatically 1.10639 + modify the <emphasis>state</emphasis> of a bug, as well as 1.10640 + simply adding a comment. For example, the hook could 1.10641 + recognise the string <quote>fixed bug 31337</quote> as 1.10642 + indicating that it should update the state of bug 31337 to 1.10643 + <quote>requires testing</quote>. 1.10644 + </para> 1.10645 + </listitem></itemizedlist> 1.10646 + 1.10647 + <sect3 id="sec:hook:bugzilla:config"> 1.10648 + <title>Configuring the <literal role="hook" moreinfo="none">bugzilla</literal> 1.10649 + hook</title> 1.10650 + 1.10651 + <para id="x_24e">You should configure this hook in your server's 1.10652 + <filename role="special" moreinfo="none">~/.hgrc</filename> as an <literal role="hook" moreinfo="none">incoming</literal> hook, for example as 1.10653 + follows: 1.10654 + </para> 1.10655 + <programlisting format="linespecific">[hooks] 1.10656 +incoming.bugzilla = python:hgext.bugzilla.hook</programlisting> 1.10657 + 1.10658 + <para id="x_24f">Because of the specialised nature of this hook, and 1.10659 + because Bugzilla was not written with this kind of 1.10660 + integration in mind, configuring this hook is a somewhat 1.10661 + involved process. 1.10662 + </para> 1.10663 + 1.10664 + <para id="x_250">Before you begin, you must install the MySQL bindings 1.10665 + for Python on the host(s) where you'll be running the hook. 1.10666 + If this is not available as a binary package for your 1.10667 + system, you can download it from 1.10668 + <citation>web:mysql-python</citation>. 1.10669 + </para> 1.10670 + 1.10671 + <para id="x_251">Configuration information for this hook lives in the 1.10672 + <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal> section of 1.10673 + your <filename role="special" moreinfo="none">~/.hgrc</filename>. 1.10674 + </para> 1.10675 + <itemizedlist> 1.10676 + <listitem><para id="x_252"><envar role="rc-item-bugzilla">version</envar>: The version 1.10677 + of Bugzilla installed on the server. The database 1.10678 + schema that Bugzilla uses changes occasionally, so this 1.10679 + hook has to know exactly which schema to use.</para> 1.10680 + </listitem> 1.10681 + <listitem><para id="x_253"><envar role="rc-item-bugzilla">host</envar>: 1.10682 + The hostname of the MySQL server that stores your 1.10683 + Bugzilla data. The database must be configured to allow 1.10684 + connections from whatever host you are running the 1.10685 + <literal role="hook" moreinfo="none">bugzilla</literal> hook on. 1.10686 + </para> 1.10687 + </listitem> 1.10688 + <listitem><para id="x_254"><envar role="rc-item-bugzilla">user</envar>: 1.10689 + The username with which to connect to the MySQL server. 1.10690 + The database must be configured to allow this user to 1.10691 + connect from whatever host you are running the <literal role="hook" moreinfo="none">bugzilla</literal> hook on. This user 1.10692 + must be able to access and modify Bugzilla tables. The 1.10693 + default value of this item is <literal moreinfo="none">bugs</literal>, 1.10694 + which is the standard name of the Bugzilla user in a 1.10695 + MySQL database. 1.10696 + </para> 1.10697 + </listitem> 1.10698 + <listitem><para id="x_255"><envar role="rc-item-bugzilla">password</envar>: The MySQL 1.10699 + password for the user you configured above. This is 1.10700 + stored as plain text, so you should make sure that 1.10701 + unauthorised users cannot read the <filename role="special" moreinfo="none">~/.hgrc</filename> file where you 1.10702 + store this information. 1.10703 + </para> 1.10704 + </listitem> 1.10705 + <listitem><para id="x_256"><envar role="rc-item-bugzilla">db</envar>: 1.10706 + The name of the Bugzilla database on the MySQL server. 1.10707 + The default value of this item is 1.10708 + <literal moreinfo="none">bugs</literal>, which is the standard name of 1.10709 + the MySQL database where Bugzilla stores its data. 1.10710 + </para> 1.10711 + </listitem> 1.10712 + <listitem><para id="x_257"><envar role="rc-item-bugzilla">notify</envar>: If you want 1.10713 + Bugzilla to send out a notification email to subscribers 1.10714 + after this hook has added a comment to a bug, you will 1.10715 + need this hook to run a command whenever it updates the 1.10716 + database. The command to run depends on where you have 1.10717 + installed Bugzilla, but it will typically look something 1.10718 + like this, if you have Bugzilla installed in <filename class="directory" moreinfo="none">/var/www/html/bugzilla</filename>: 1.10719 + </para> 1.10720 + <programlisting format="linespecific">cd /var/www/html/bugzilla && 1.10721 + ./processmail %s nobody@nowhere.com</programlisting> 1.10722 + </listitem> 1.10723 + <listitem><para id="x_258"> The Bugzilla 1.10724 + <literal moreinfo="none">processmail</literal> program expects to be 1.10725 + given a bug ID (the hook replaces 1.10726 + <quote><literal moreinfo="none">%s</literal></quote> with the bug ID) 1.10727 + and an email address. It also expects to be able to 1.10728 + write to some files in the directory that it runs in. 1.10729 + If Bugzilla and this hook are not installed on the same 1.10730 + machine, you will need to find a way to run 1.10731 + <literal moreinfo="none">processmail</literal> on the server where 1.10732 + Bugzilla is installed. 1.10733 + </para> 1.10734 + </listitem></itemizedlist> 1.10735 + 1.10736 + </sect3> 1.10737 + <sect3> 1.10738 + <title>Mapping committer names to Bugzilla user names</title> 1.10739 + 1.10740 + <para id="x_259">By default, the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook tries to use the 1.10741 + email address of a changeset's committer as the Bugzilla 1.10742 + user name with which to update a bug. If this does not suit 1.10743 + your needs, you can map committer email addresses to 1.10744 + Bugzilla user names using a <literal role="rc-usermap" moreinfo="none">usermap</literal> section. 1.10745 + </para> 1.10746 + 1.10747 + <para id="x_25a">Each item in the <literal role="rc-usermap" moreinfo="none">usermap</literal> section contains an 1.10748 + email address on the left, and a Bugzilla user name on the 1.10749 + right. 1.10750 + </para> 1.10751 + <programlisting format="linespecific">[usermap] 1.10752 +jane.user@example.com = jane</programlisting> 1.10753 + <para id="x_25b">You can either keep the <literal role="rc-usermap" moreinfo="none">usermap</literal> data in a normal 1.10754 + <filename role="special" moreinfo="none">~/.hgrc</filename>, or tell the 1.10755 + <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook to read the 1.10756 + information from an external <filename moreinfo="none">usermap</filename> 1.10757 + file. In the latter case, you can store 1.10758 + <filename moreinfo="none">usermap</filename> data by itself in (for example) 1.10759 + a user-modifiable repository. This makes it possible to let 1.10760 + your users maintain their own <envar role="rc-item-bugzilla">usermap</envar> entries. The main 1.10761 + <filename role="special" moreinfo="none">~/.hgrc</filename> file might look 1.10762 + like this: 1.10763 + </para> 1.10764 + <programlisting format="linespecific"># regular hgrc file refers to external usermap file 1.10765 +[bugzilla] 1.10766 +usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting> 1.10767 + <para id="x_25c">While the <filename moreinfo="none">usermap</filename> file that it 1.10768 + refers to might look like this: 1.10769 + </para> 1.10770 + <programlisting format="linespecific"># bugzilla-usermap.conf - inside a hg repository 1.10771 +[usermap] stephanie@example.com = steph</programlisting> 1.10772 + 1.10773 + </sect3> 1.10774 + <sect3> 1.10775 + <title>Configuring the text that gets added to a bug</title> 1.10776 + 1.10777 + <para id="x_25d">You can configure the text that this hook adds as a 1.10778 + comment; you specify it in the form of a Mercurial template. 1.10779 + Several <filename role="special" moreinfo="none">~/.hgrc</filename> entries 1.10780 + (still in the <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal> 1.10781 + section) control this behavior. 1.10782 + </para> 1.10783 + <itemizedlist> 1.10784 + <listitem><para id="x_25e"><literal moreinfo="none">strip</literal>: The number of 1.10785 + leading path elements to strip from a repository's path 1.10786 + name to construct a partial path for a URL. For example, 1.10787 + if the repositories on your server live under <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and you 1.10788 + have a repository whose path is <filename class="directory" moreinfo="none">/home/hg/repos/app/tests</filename>, 1.10789 + then setting <literal moreinfo="none">strip</literal> to 1.10790 + <literal moreinfo="none">4</literal> will give a partial path of 1.10791 + <filename class="directory" moreinfo="none">app/tests</filename>. The 1.10792 + hook will make this partial path available when 1.10793 + expanding a template, as <literal moreinfo="none">webroot</literal>. 1.10794 + </para> 1.10795 + </listitem> 1.10796 + <listitem><para id="x_25f"><literal moreinfo="none">template</literal>: The text of the 1.10797 + template to use. In addition to the usual 1.10798 + changeset-related variables, this template can use 1.10799 + <literal moreinfo="none">hgweb</literal> (the value of the 1.10800 + <literal moreinfo="none">hgweb</literal> configuration item above) and 1.10801 + <literal moreinfo="none">webroot</literal> (the path constructed using 1.10802 + <literal moreinfo="none">strip</literal> above). 1.10803 + </para> 1.10804 + </listitem></itemizedlist> 1.10805 + 1.10806 + <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 1.10807 + available when expanding a template, as the base string to 1.10808 + use when constructing a URL that will let users browse from 1.10809 + a Bugzilla comment to view a changeset. Example: 1.10810 + </para> 1.10811 + <programlisting format="linespecific">[web] 1.10812 +baseurl = http://hg.domain.com/</programlisting> 1.10813 + 1.10814 + <para id="x_261">Here is an example set of <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook config information. 1.10815 + </para> 1.10816 + 1.10817 + <!-- BEGIN ch10/bugzilla-config.lst --> 1.10818 +<programlisting format="linespecific">[bugzilla] 1.10819 +host = bugzilla.example.com 1.10820 +password = mypassword version = 2.16 1.10821 +# server-side repos live in /home/hg/repos, so strip 4 leading 1.10822 +# separators 1.10823 +strip = 4 1.10824 +hgweb = http://hg.example.com/ 1.10825 +usermap = /home/hg/repos/notify/bugzilla.conf 1.10826 +template = Changeset {node|short}, made by {author} in the {webroot} 1.10827 + repo, refers to this bug.\n 1.10828 + For complete details, see 1.10829 + {hgweb}{webroot}?cmd=changeset;node={node|short}\n 1.10830 + Changeset description:\n 1.10831 + \t{desc|tabindent}</programlisting> 1.10832 +<!-- END ch10/bugzilla-config.lst --> 1.10833 + 1.10834 + 1.10835 + </sect3> 1.10836 + <sect3> 1.10837 + <title>Testing and troubleshooting</title> 1.10838 + 1.10839 + <para id="x_262">The most common problems with configuring the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook relate to running 1.10840 + Bugzilla's <filename moreinfo="none">processmail</filename> script and 1.10841 + mapping committer names to user names. 1.10842 + </para> 1.10843 + 1.10844 + <para id="x_263">Recall from <xref linkend="sec:hook:bugzilla:config"/> above that the user 1.10845 + that runs the Mercurial process on the server is also the 1.10846 + one that will run the <filename moreinfo="none">processmail</filename> 1.10847 + script. The <filename moreinfo="none">processmail</filename> script 1.10848 + sometimes causes Bugzilla to write to files in its 1.10849 + configuration directory, and Bugzilla's configuration files 1.10850 + are usually owned by the user that your web server runs 1.10851 + under. 1.10852 + </para> 1.10853 + 1.10854 + <para id="x_264">You can cause <filename moreinfo="none">processmail</filename> to be run 1.10855 + with the suitable user's identity using the 1.10856 + <command moreinfo="none">sudo</command> command. Here is an example entry 1.10857 + for a <filename moreinfo="none">sudoers</filename> file. 1.10858 + </para> 1.10859 + <programlisting format="linespecific">hg_user = (httpd_user) 1.10860 +NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting> 1.10861 + <para id="x_265">This allows the <literal moreinfo="none">hg_user</literal> user to run a 1.10862 + <filename moreinfo="none">processmail-wrapper</filename> program under the 1.10863 + identity of <literal moreinfo="none">httpd_user</literal>. 1.10864 + </para> 1.10865 + 1.10866 + <para id="x_266">This indirection through a wrapper script is necessary, 1.10867 + because <filename moreinfo="none">processmail</filename> expects to be run 1.10868 + with its current directory set to wherever you installed 1.10869 + Bugzilla; you can't specify that kind of constraint in a 1.10870 + <filename moreinfo="none">sudoers</filename> file. The contents of the 1.10871 + wrapper script are simple: 1.10872 + </para> 1.10873 + <programlisting format="linespecific">#!/bin/sh 1.10874 +cd `dirname $0` && ./processmail "$1" nobody@example.com</programlisting> 1.10875 + <para id="x_267">It doesn't seem to matter what email address you pass to 1.10876 + <filename moreinfo="none">processmail</filename>. 1.10877 + </para> 1.10878 + 1.10879 + <para id="x_268">If your <literal role="rc-usermap" moreinfo="none">usermap</literal> is 1.10880 + not set up correctly, users will see an error message from 1.10881 + the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook when they 1.10882 + push changes to the server. The error message will look 1.10883 + like this: 1.10884 + </para> 1.10885 + <programlisting format="linespecific">cannot find bugzilla user id for john.q.public@example.com</programlisting> 1.10886 + <para id="x_269">What this means is that the committer's address, 1.10887 + <literal moreinfo="none">john.q.public@example.com</literal>, is not a valid 1.10888 + Bugzilla user name, nor does it have an entry in your 1.10889 + <literal role="rc-usermap" moreinfo="none">usermap</literal> that maps it to 1.10890 + a valid Bugzilla user name. 1.10891 + </para> 1.10892 + 1.10893 + </sect3> </sect2> 1.10894 + 1.10895 + <sect2> 1.10896 + <title><literal role="hg-ext" moreinfo="none">notify</literal>—send email 1.10897 + notifications</title> 1.10898 + 1.10899 + <para id="x_26a">Although Mercurial's built-in web server provides RSS 1.10900 + feeds of changes in every repository, many people prefer to 1.10901 + receive change notifications via email. The <literal role="hg-ext" moreinfo="none">notify</literal> hook lets you send out 1.10902 + notifications to a set of email addresses whenever changesets 1.10903 + arrive that those subscribers are interested in. 1.10904 + </para> 1.10905 + 1.10906 + <para id="x_26b">As with the <literal role="hg-ext" moreinfo="none">bugzilla</literal> 1.10907 + hook, the <literal role="hg-ext" moreinfo="none">notify</literal> hook is 1.10908 + template-driven, so you can customise the contents of the 1.10909 + notification messages that it sends. 1.10910 + </para> 1.10911 + 1.10912 + <para id="x_26c">By default, the <literal role="hg-ext" moreinfo="none">notify</literal> 1.10913 + hook includes a diff of every changeset that it sends out; you 1.10914 + can limit the size of the diff, or turn this feature off 1.10915 + entirely. It is useful for letting subscribers review changes 1.10916 + immediately, rather than clicking to follow a URL. 1.10917 + </para> 1.10918 + 1.10919 + <sect3> 1.10920 + <title>Configuring the <literal role="hg-ext" moreinfo="none">notify</literal> 1.10921 + hook</title> 1.10922 + 1.10923 + <para id="x_26d">You can set up the <literal role="hg-ext" moreinfo="none">notify</literal> hook to send one email 1.10924 + message per incoming changeset, or one per incoming group of 1.10925 + changesets (all those that arrived in a single pull or 1.10926 + push). 1.10927 + </para> 1.10928 + <programlisting format="linespecific">[hooks] 1.10929 +# send one email per group of changes 1.10930 +changegroup.notify = python:hgext.notify.hook 1.10931 +# send one email per change 1.10932 +incoming.notify = python:hgext.notify.hook</programlisting> 1.10933 + 1.10934 + <para id="x_26e">Configuration information for this hook lives in the 1.10935 + <literal role="rc-notify" moreinfo="none">notify</literal> section of a 1.10936 + <filename role="special" moreinfo="none">~/.hgrc</filename> file. 1.10937 + </para> 1.10938 + <itemizedlist> 1.10939 + <listitem><para id="x_26f"><envar role="rc-item-notify">test</envar>: 1.10940 + By default, this hook does not send out email at all; 1.10941 + instead, it prints the message that it 1.10942 + <emphasis>would</emphasis> send. Set this item to 1.10943 + <literal moreinfo="none">false</literal> to allow email to be sent. The 1.10944 + reason that sending of email is turned off by default is 1.10945 + that it takes several tries to configure this extension 1.10946 + exactly as you would like, and it would be bad form to 1.10947 + spam subscribers with a number of <quote>broken</quote> 1.10948 + notifications while you debug your configuration. 1.10949 + </para> 1.10950 + </listitem> 1.10951 + <listitem><para id="x_270"><envar role="rc-item-notify">config</envar>: 1.10952 + The path to a configuration file that contains 1.10953 + subscription information. This is kept separate from 1.10954 + the main <filename role="special" moreinfo="none">~/.hgrc</filename> so 1.10955 + that you can maintain it in a repository of its own. 1.10956 + People can then clone that repository, update their 1.10957 + subscriptions, and push the changes back to your server. 1.10958 + </para> 1.10959 + </listitem> 1.10960 + <listitem><para id="x_271"><envar role="rc-item-notify">strip</envar>: 1.10961 + The number of leading path separator characters to strip 1.10962 + from a repository's path, when deciding whether a 1.10963 + repository has subscribers. For example, if the 1.10964 + repositories on your server live in <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and 1.10965 + <literal role="hg-ext" moreinfo="none">notify</literal> is considering a 1.10966 + repository named <filename class="directory" moreinfo="none">/home/hg/repos/shared/test</filename>, 1.10967 + setting <envar role="rc-item-notify">strip</envar> to 1.10968 + <literal moreinfo="none">4</literal> will cause <literal role="hg-ext" moreinfo="none">notify</literal> to trim the path it 1.10969 + considers down to <filename class="directory" moreinfo="none">shared/test</filename>, and it will 1.10970 + match subscribers against that. 1.10971 + </para> 1.10972 + </listitem> 1.10973 + <listitem><para id="x_272"><envar role="rc-item-notify">template</envar>: The template 1.10974 + text to use when sending messages. This specifies both 1.10975 + the contents of the message header and its body. 1.10976 + </para> 1.10977 + </listitem> 1.10978 + <listitem><para id="x_273"><envar role="rc-item-notify">maxdiff</envar>: The maximum 1.10979 + number of lines of diff data to append to the end of a 1.10980 + message. If a diff is longer than this, it is 1.10981 + truncated. By default, this is set to 300. Set this to 1.10982 + <literal moreinfo="none">0</literal> to omit diffs from notification 1.10983 + emails. 1.10984 + </para> 1.10985 + </listitem> 1.10986 + <listitem><para id="x_274"><envar role="rc-item-notify">sources</envar>: A list of 1.10987 + sources of changesets to consider. This lets you limit 1.10988 + <literal role="hg-ext" moreinfo="none">notify</literal> to only sending 1.10989 + out email about changes that remote users pushed into 1.10990 + this repository via a server, for example. See 1.10991 + <xref linkend="sec:hook:sources"/> for the sources you 1.10992 + can specify here. 1.10993 + </para> 1.10994 + </listitem></itemizedlist> 1.10995 + 1.10996 + <para id="x_275">If you set the <envar role="rc-item-web">baseurl</envar> 1.10997 + item in the <literal role="rc-web" moreinfo="none">web</literal> section, 1.10998 + you can use it in a template; it will be available as 1.10999 + <literal moreinfo="none">webroot</literal>. 1.11000 + </para> 1.11001 + 1.11002 + <para id="x_276">Here is an example set of <literal role="hg-ext" moreinfo="none">notify</literal> configuration information. 1.11003 + </para> 1.11004 + 1.11005 + <!-- BEGIN ch10/notify-config.lst --> 1.11006 +<programlisting format="linespecific">[notify] 1.11007 +# really send email 1.11008 +test = false 1.11009 +# subscriber data lives in the notify repo 1.11010 +config = /home/hg/repos/notify/notify.conf 1.11011 +# repos live in /home/hg/repos on server, so strip 4 "/" chars 1.11012 +strip = 4 1.11013 +template = X-Hg-Repo: {webroot}\n 1.11014 + Subject: {webroot}: {desc|firstline|strip}\n 1.11015 + From: {author} 1.11016 + \n\n 1.11017 + changeset {node|short} in {root} 1.11018 + \n\ndetails: 1.11019 + {baseurl}{webroot}?cmd=changeset;node={node|short} 1.11020 + description: {desc|tabindent|strip} 1.11021 + 1.11022 +[web] 1.11023 +baseurl = 1.11024 +http://hg.example.com/</programlisting> 1.11025 +<!-- END ch10/notify-config.lst --> 1.11026 + 1.11027 + 1.11028 + <para id="x_277">This will produce a message that looks like the 1.11029 + following: 1.11030 + </para> 1.11031 + 1.11032 + <!-- BEGIN ch10/notify-config-mail.lst --> 1.11033 +<programlisting format="linespecific">X-Hg-Repo: tests/slave 1.11034 +Subject: tests/slave: Handle error case when slave has no buffers 1.11035 +Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT) 1.11036 + 1.11037 +changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave 1.11038 + 1.11039 +details: 1.11040 +http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 1.11041 + 1.11042 +description: Handle error case when slave has no buffers 1.11043 + 1.11044 +diffs (54 lines): 1.11045 +diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h 1.11046 +--- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 1.11047 ++++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700 1.11048 +@@ -212,6 +212,15 @@ static __inline__ 1.11049 +void test_headers(void *h) 1.11050 +[...snip...]</programlisting> 1.11051 +<!-- END ch10/notify-config-mail.lst --> 1.11052 + 1.11053 + 1.11054 + </sect3> 1.11055 + <sect3> 1.11056 + <title>Testing and troubleshooting</title> 1.11057 + 1.11058 + <para id="x_278">Do not forget that by default, the <literal role="hg-ext" moreinfo="none">notify</literal> extension <emphasis>will not 1.11059 + send any mail</emphasis> until you explicitly configure it to do so, 1.11060 + by setting <envar role="rc-item-notify">test</envar> to 1.11061 + <literal moreinfo="none">false</literal>. Until you do that, it simply 1.11062 + prints the message it <emphasis>would</emphasis> send. 1.11063 + </para> 1.11064 + 1.11065 + </sect3> 1.11066 + </sect2> 1.11067 + </sect1> 1.11068 + <sect1 id="sec:hook:ref"> 1.11069 + <title>Information for writers of hooks</title> 1.11070 + 1.11071 + <sect2> 1.11072 + <title>In-process hook execution</title> 1.11073 + 1.11074 + <para id="x_279">An in-process hook is called with arguments of the 1.11075 + following form: 1.11076 + </para> 1.11077 + <programlisting format="linespecific">def myhook(ui, repo, **kwargs): pass</programlisting> 1.11078 + <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 1.11079 + <literal moreinfo="none">repo</literal> parameter is a <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal> 1.11080 + object. The names and values of the 1.11081 + <literal moreinfo="none">**kwargs</literal> parameters depend on the hook 1.11082 + being invoked, with the following common features: 1.11083 + </para> 1.11084 + <itemizedlist> 1.11085 + <listitem><para id="x_27b">If a parameter is named 1.11086 + <literal moreinfo="none">node</literal> or <literal moreinfo="none">parentN</literal>, it 1.11087 + will contain a hexadecimal changeset ID. The empty string 1.11088 + is used to represent <quote>null changeset ID</quote> 1.11089 + instead of a string of zeroes. 1.11090 + </para> 1.11091 + </listitem> 1.11092 + <listitem><para id="x_27c">If a parameter is named 1.11093 + <literal moreinfo="none">url</literal>, it will contain the URL of a 1.11094 + remote repository, if that can be determined. 1.11095 + </para> 1.11096 + </listitem> 1.11097 + <listitem><para id="x_27d">Boolean-valued parameters are represented as 1.11098 + Python <literal moreinfo="none">bool</literal> objects. 1.11099 + </para> 1.11100 + </listitem></itemizedlist> 1.11101 + 1.11102 + <para id="x_27e">An in-process hook is called without a change to the 1.11103 + process's working directory (unlike external hooks, which are 1.11104 + run in the root of the repository). It must not change the 1.11105 + process's working directory, or it will cause any calls it 1.11106 + makes into the Mercurial API to fail. 1.11107 + </para> 1.11108 + 1.11109 + <para id="x_27f">If a hook returns a boolean <quote>false</quote> value, it 1.11110 + is considered to have succeeded. If it returns a boolean 1.11111 + <quote>true</quote> value or raises an exception, it is 1.11112 + considered to have failed. A useful way to think of the 1.11113 + calling convention is <quote>tell me if you fail</quote>. 1.11114 + </para> 1.11115 + 1.11116 + <para id="x_280">Note that changeset IDs are passed into Python hooks as 1.11117 + hexadecimal strings, not the binary hashes that Mercurial's 1.11118 + APIs normally use. To convert a hash from hex to binary, use 1.11119 + the <literal moreinfo="none">bin</literal> function. 1.11120 + </para> 1.11121 + </sect2> 1.11122 + 1.11123 + <sect2> 1.11124 + <title>External hook execution</title> 1.11125 + 1.11126 + <para id="x_281">An external hook is passed to the shell of the user 1.11127 + running Mercurial. Features of that shell, such as variable 1.11128 + substitution and command redirection, are available. The hook 1.11129 + is run in the root directory of the repository (unlike 1.11130 + in-process hooks, which are run in the same directory that 1.11131 + Mercurial was run in). 1.11132 + </para> 1.11133 + 1.11134 + <para id="x_282">Hook parameters are passed to the hook as environment 1.11135 + variables. Each environment variable's name is converted in 1.11136 + upper case and prefixed with the string 1.11137 + <quote><literal moreinfo="none">HG_</literal></quote>. For example, if the 1.11138 + name of a parameter is <quote><literal moreinfo="none">node</literal></quote>, 1.11139 + the name of the environment variable representing that 1.11140 + parameter will be <quote><literal moreinfo="none">HG_NODE</literal></quote>. 1.11141 + </para> 1.11142 + 1.11143 + <para id="x_283">A boolean parameter is represented as the string 1.11144 + <quote><literal moreinfo="none">1</literal></quote> for <quote>true</quote>, 1.11145 + <quote><literal moreinfo="none">0</literal></quote> for <quote>false</quote>. 1.11146 + If an environment variable is named <envar>HG_NODE</envar>, 1.11147 + <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it 1.11148 + contains a changeset ID represented as a hexadecimal string. 1.11149 + The empty string is used to represent <quote>null changeset 1.11150 + ID</quote> instead of a string of zeroes. If an environment 1.11151 + variable is named <envar>HG_URL</envar>, it will contain the 1.11152 + URL of a remote repository, if that can be determined. 1.11153 + </para> 1.11154 + 1.11155 + <para id="x_284">If a hook exits with a status of zero, it is considered to 1.11156 + have succeeded. If it exits with a non-zero status, it is 1.11157 + considered to have failed. 1.11158 + </para> 1.11159 + </sect2> 1.11160 + 1.11161 + <sect2> 1.11162 + <title>Finding out where changesets come from</title> 1.11163 + 1.11164 + <para id="x_285">A hook that involves the transfer of changesets between a 1.11165 + local repository and another may be able to find out 1.11166 + information about the <quote>far side</quote>. Mercurial 1.11167 + knows <emphasis>how</emphasis> changes are being transferred, 1.11168 + and in many cases <emphasis>where</emphasis> they are being 1.11169 + transferred to or from. 1.11170 + </para> 1.11171 + 1.11172 + <sect3 id="sec:hook:sources"> 1.11173 + <title>Sources of changesets</title> 1.11174 + 1.11175 + <para id="x_286">Mercurial will tell a hook what means are, or were, used 1.11176 + to transfer changesets between repositories. This is 1.11177 + provided by Mercurial in a Python parameter named 1.11178 + <literal moreinfo="none">source</literal>, or an environment variable named 1.11179 + <envar>HG_SOURCE</envar>. 1.11180 + </para> 1.11181 + 1.11182 + <itemizedlist> 1.11183 + <listitem><para id="x_287"><literal moreinfo="none">serve</literal>: Changesets are 1.11184 + transferred to or from a remote repository over http or 1.11185 + ssh. 1.11186 + </para> 1.11187 + </listitem> 1.11188 + <listitem><para id="x_288"><literal moreinfo="none">pull</literal>: Changesets are 1.11189 + being transferred via a pull from one repository into 1.11190 + another. 1.11191 + </para> 1.11192 + </listitem> 1.11193 + <listitem><para id="x_289"><literal moreinfo="none">push</literal>: Changesets are 1.11194 + being transferred via a push from one repository into 1.11195 + another. 1.11196 + </para> 1.11197 + </listitem> 1.11198 + <listitem><para id="x_28a"><literal moreinfo="none">bundle</literal>: Changesets are 1.11199 + being transferred to or from a bundle. 1.11200 + </para> 1.11201 + </listitem></itemizedlist> 1.11202 + </sect3> 1.11203 + 1.11204 + <sect3 id="sec:hook:url"> 1.11205 + <title>Where changes are going—remote repository 1.11206 + URLs</title> 1.11207 + 1.11208 + <para id="x_28b">When possible, Mercurial will tell a hook the location 1.11209 + of the <quote>far side</quote> of an activity that transfers 1.11210 + changeset data between repositories. This is provided by 1.11211 + Mercurial in a Python parameter named 1.11212 + <literal moreinfo="none">url</literal>, or an environment variable named 1.11213 + <envar>HG_URL</envar>. 1.11214 + </para> 1.11215 + 1.11216 + <para id="x_28c">This information is not always known. If a hook is 1.11217 + invoked in a repository that is being served via http or 1.11218 + ssh, Mercurial cannot tell where the remote repository is, 1.11219 + but it may know where the client is connecting from. In 1.11220 + such cases, the URL will take one of the following forms: 1.11221 + </para> 1.11222 + <itemizedlist> 1.11223 + <listitem><para id="x_28d"><literal moreinfo="none">remote:ssh:1.2.3.4</literal>—remote 1.11224 + ssh client, at the IP address 1.11225 + <literal moreinfo="none">1.2.3.4</literal>. 1.11226 + </para> 1.11227 + </listitem> 1.11228 + <listitem><para id="x_28e"><literal moreinfo="none">remote:http:1.2.3.4</literal>—remote 1.11229 + http client, at the IP address 1.11230 + <literal moreinfo="none">1.2.3.4</literal>. If the client is using SSL, 1.11231 + this will be of the form 1.11232 + <literal moreinfo="none">remote:https:1.2.3.4</literal>. 1.11233 + </para> 1.11234 + </listitem> 1.11235 + <listitem><para id="x_28f">Empty—no information could be 1.11236 + discovered about the remote client. 1.11237 + </para> 1.11238 + </listitem></itemizedlist> 1.11239 + </sect3> 1.11240 + </sect2> 1.11241 + </sect1> 1.11242 + <sect1> 1.11243 + <title>Hook reference</title> 1.11244 + 1.11245 + <sect2 id="sec:hook:changegroup"> 1.11246 + <title><literal role="hook" moreinfo="none">changegroup</literal>—after 1.11247 + remote changesets added</title> 1.11248 + 1.11249 + <para id="x_290">This hook is run after a group of pre-existing changesets 1.11250 + 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 1.11251 + unbundle</command>. This hook is run once per operation 1.11252 + that added one or more changesets. This is in contrast to the 1.11253 + <literal role="hook" moreinfo="none">incoming</literal> hook, which is run 1.11254 + once per changeset, regardless of whether the changesets 1.11255 + arrive in a group. 1.11256 + </para> 1.11257 + 1.11258 + <para id="x_291">Some possible uses for this hook include kicking off an 1.11259 + automated build or test of the added changesets, updating a 1.11260 + bug database, or notifying subscribers that a repository 1.11261 + contains new changes. 1.11262 + </para> 1.11263 + 1.11264 + <para id="x_292">Parameters to this hook: 1.11265 + </para> 1.11266 + <itemizedlist> 1.11267 + <listitem><para id="x_293"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11268 + changeset ID of the first changeset in the group that was 1.11269 + added. All changesets between this and 1.11270 + <literal role="tag" moreinfo="none">tip</literal>, inclusive, were added by a single 1.11271 + <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>. 1.11272 + </para> 1.11273 + </listitem> 1.11274 + <listitem><para id="x_294"><literal moreinfo="none">source</literal>: A 1.11275 + string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details. 1.11276 + </para> 1.11277 + </listitem> 1.11278 + <listitem><para id="x_295"><literal moreinfo="none">url</literal>: A URL. The 1.11279 + location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. 1.11280 + </para> 1.11281 + </listitem></itemizedlist> 1.11282 + 1.11283 + <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"/>) 1.11284 + </para> 1.11285 + </sect2> 1.11286 + 1.11287 + <sect2 id="sec:hook:commit"> 1.11288 + <title><literal role="hook" moreinfo="none">commit</literal>—after a new 1.11289 + changeset is created</title> 1.11290 + 1.11291 + <para id="x_297">This hook is run after a new changeset has been created. 1.11292 + </para> 1.11293 + 1.11294 + <para id="x_298">Parameters to this hook: 1.11295 + </para> 1.11296 + <itemizedlist> 1.11297 + <listitem><para id="x_299"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11298 + changeset ID of the newly committed changeset. 1.11299 + </para> 1.11300 + </listitem> 1.11301 + <listitem><para id="x_29a"><literal moreinfo="none">parent1</literal>: A changeset ID. 1.11302 + The changeset ID of the first parent of the newly 1.11303 + committed changeset. 1.11304 + </para> 1.11305 + </listitem> 1.11306 + <listitem><para id="x_29b"><literal moreinfo="none">parent2</literal>: A changeset ID. 1.11307 + The changeset ID of the second parent of the newly 1.11308 + committed changeset. 1.11309 + </para> 1.11310 + </listitem></itemizedlist> 1.11311 + 1.11312 + <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"/>) 1.11313 + </para> 1.11314 + </sect2> 1.11315 + 1.11316 + <sect2 id="sec:hook:incoming"> 1.11317 + <title><literal role="hook" moreinfo="none">incoming</literal>—after one 1.11318 + remote changeset is added</title> 1.11319 + 1.11320 + <para id="x_29d">This hook is run after a pre-existing changeset has been 1.11321 + added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg push</command>. If a group of changesets 1.11322 + was added in a single operation, this hook is called once for 1.11323 + each added changeset. 1.11324 + </para> 1.11325 + 1.11326 + <para id="x_29e">You can use this hook for the same purposes as 1.11327 + the <literal role="hook" moreinfo="none">changegroup</literal> hook (<xref linkend="sec:hook:changegroup"/>); it's simply more 1.11328 + convenient sometimes to run a hook once per group of 1.11329 + changesets, while other times it's handier once per changeset. 1.11330 + </para> 1.11331 + 1.11332 + <para id="x_29f">Parameters to this hook: 1.11333 + </para> 1.11334 + <itemizedlist> 1.11335 + <listitem><para id="x_2a0"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11336 + ID of the newly added changeset. 1.11337 + </para> 1.11338 + </listitem> 1.11339 + <listitem><para id="x_2a1"><literal moreinfo="none">source</literal>: A 1.11340 + string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details. 1.11341 + </para> 1.11342 + </listitem> 1.11343 + <listitem><para id="x_2a2"><literal moreinfo="none">url</literal>: A URL. The 1.11344 + location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. 1.11345 + </para> 1.11346 + </listitem></itemizedlist> 1.11347 + 1.11348 + <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"/>) 1.11349 + </para> 1.11350 + </sect2> 1.11351 + 1.11352 + <sect2 id="sec:hook:outgoing"> 1.11353 + <title><literal role="hook" moreinfo="none">outgoing</literal>—after 1.11354 + changesets are propagated</title> 1.11355 + 1.11356 + <para id="x_2a4">This hook is run after a group of changesets has been 1.11357 + 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 1.11358 + bundle</command> command. 1.11359 + </para> 1.11360 + 1.11361 + <para id="x_2a5">One possible use for this hook is to notify administrators 1.11362 + that changes have been pulled. 1.11363 + </para> 1.11364 + 1.11365 + <para id="x_2a6">Parameters to this hook: 1.11366 + </para> 1.11367 + <itemizedlist> 1.11368 + <listitem><para id="x_2a7"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11369 + changeset ID of the first changeset of the group that was 1.11370 + sent. 1.11371 + </para> 1.11372 + </listitem> 1.11373 + <listitem><para id="x_2a8"><literal moreinfo="none">source</literal>: A string. The 1.11374 + source of the of the operation (see <xref linkend="sec:hook:sources"/>). If a remote 1.11375 + client pulled changes from this repository, 1.11376 + <literal moreinfo="none">source</literal> will be 1.11377 + <literal moreinfo="none">serve</literal>. If the client that obtained 1.11378 + changes from this repository was local, 1.11379 + <literal moreinfo="none">source</literal> will be 1.11380 + <literal moreinfo="none">bundle</literal>, <literal moreinfo="none">pull</literal>, or 1.11381 + <literal moreinfo="none">push</literal>, depending on the operation the 1.11382 + client performed. 1.11383 + </para> 1.11384 + </listitem> 1.11385 + <listitem><para id="x_2a9"><literal moreinfo="none">url</literal>: A URL. The 1.11386 + location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. 1.11387 + </para> 1.11388 + </listitem></itemizedlist> 1.11389 + 1.11390 + <para id="x_2aa">See also: <literal role="hook" moreinfo="none">preoutgoing</literal> (<xref linkend="sec:hook:preoutgoing"/>) 1.11391 + </para> 1.11392 + </sect2> 1.11393 + 1.11394 + <sect2 id="sec:hook:prechangegroup"> 1.11395 + <title><literal role="hook" moreinfo="none">prechangegroup</literal>—before starting 1.11396 + to add remote changesets</title> 1.11397 + 1.11398 + <para id="x_2ab">This controlling hook is run before Mercurial begins to 1.11399 + add a group of changesets from another repository. 1.11400 + </para> 1.11401 + 1.11402 + <para id="x_2ac">This hook does not have any information about the 1.11403 + changesets to be added, because it is run before transmission 1.11404 + of those changesets is allowed to begin. If this hook fails, 1.11405 + the changesets will not be transmitted. 1.11406 + </para> 1.11407 + 1.11408 + <para id="x_2ad">One use for this hook is to prevent external changes from 1.11409 + being added to a repository. For example, you could use this 1.11410 + to <quote>freeze</quote> a server-hosted branch temporarily or 1.11411 + permanently so that users cannot push to it, while still 1.11412 + allowing a local administrator to modify the repository. 1.11413 + </para> 1.11414 + 1.11415 + <para id="x_2ae">Parameters to this hook: 1.11416 + </para> 1.11417 + <itemizedlist> 1.11418 + <listitem><para id="x_2af"><literal moreinfo="none">source</literal>: A string. The 1.11419 + source of these changes. See <xref linkend="sec:hook:sources"/> for details. 1.11420 + </para> 1.11421 + </listitem> 1.11422 + <listitem><para id="x_2b0"><literal moreinfo="none">url</literal>: A URL. The 1.11423 + location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. 1.11424 + </para> 1.11425 + </listitem></itemizedlist> 1.11426 + 1.11427 + <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"/>) 1.11428 + </para> 1.11429 + </sect2> 1.11430 + 1.11431 + <sect2 id="sec:hook:precommit"> 1.11432 + <title><literal role="hook" moreinfo="none">precommit</literal>—before 1.11433 + starting to commit a changeset</title> 1.11434 + 1.11435 + <para id="x_2b2">This hook is run before Mercurial begins to commit a new 1.11436 + changeset. It is run before Mercurial has any of the metadata 1.11437 + for the commit, such as the files to be committed, the commit 1.11438 + message, or the commit date. 1.11439 + </para> 1.11440 + 1.11441 + <para id="x_2b3">One use for this hook is to disable the ability to commit 1.11442 + new changesets, while still allowing incoming changesets. 1.11443 + Another is to run a build or test, and only allow the commit 1.11444 + to begin if the build or test succeeds. 1.11445 + </para> 1.11446 + 1.11447 + <para id="x_2b4">Parameters to this hook: 1.11448 + </para> 1.11449 + <itemizedlist> 1.11450 + <listitem><para id="x_2b5"><literal moreinfo="none">parent1</literal>: A changeset ID. 1.11451 + The changeset ID of the first parent of the working 1.11452 + directory. 1.11453 + </para> 1.11454 + </listitem> 1.11455 + <listitem><para id="x_2b6"><literal moreinfo="none">parent2</literal>: A changeset ID. 1.11456 + The changeset ID of the second parent of the working 1.11457 + directory. 1.11458 + </para> 1.11459 + </listitem></itemizedlist> 1.11460 + <para id="x_2b7">If the commit proceeds, the parents of the working 1.11461 + directory will become the parents of the new changeset. 1.11462 + </para> 1.11463 + 1.11464 + <para id="x_2b8">See also: <literal role="hook" moreinfo="none">commit</literal> 1.11465 + (<xref linkend="sec:hook:commit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>) 1.11466 + </para> 1.11467 + </sect2> 1.11468 + 1.11469 + <sect2 id="sec:hook:preoutgoing"> 1.11470 + <title><literal role="hook" moreinfo="none">preoutgoing</literal>—before 1.11471 + starting to propagate changesets</title> 1.11472 + 1.11473 + <para id="x_2b9">This hook is invoked before Mercurial knows the identities 1.11474 + of the changesets to be transmitted. 1.11475 + </para> 1.11476 + 1.11477 + <para id="x_2ba">One use for this hook is to prevent changes from being 1.11478 + transmitted to another repository. 1.11479 + </para> 1.11480 + 1.11481 + <para id="x_2bb">Parameters to this hook: 1.11482 + </para> 1.11483 + <itemizedlist> 1.11484 + <listitem><para id="x_2bc"><literal moreinfo="none">source</literal>: A 1.11485 + string. The source of the operation that is attempting to 1.11486 + obtain changes from this repository (see <xref linkend="sec:hook:sources"/>). See the documentation 1.11487 + for the <literal moreinfo="none">source</literal> parameter to the 1.11488 + <literal role="hook" moreinfo="none">outgoing</literal> hook, in 1.11489 + <xref linkend="sec:hook:outgoing"/>, for possible values 1.11490 + of this parameter. 1.11491 + </para> 1.11492 + </listitem> 1.11493 + <listitem><para id="x_2bd"><literal moreinfo="none">url</literal>: A URL. The 1.11494 + location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. 1.11495 + </para> 1.11496 + </listitem></itemizedlist> 1.11497 + 1.11498 + <para id="x_2be">See also: <literal role="hook" moreinfo="none">outgoing</literal> (<xref linkend="sec:hook:outgoing"/>) 1.11499 + </para> 1.11500 + </sect2> 1.11501 + 1.11502 + <sect2 id="sec:hook:pretag"> 1.11503 + <title><literal role="hook" moreinfo="none">pretag</literal>—before 1.11504 + tagging a changeset</title> 1.11505 + 1.11506 + <para id="x_2bf">This controlling hook is run before a tag is created. If 1.11507 + the hook succeeds, creation of the tag proceeds. If the hook 1.11508 + fails, the tag is not created. 1.11509 + </para> 1.11510 + 1.11511 + <para id="x_2c0">Parameters to this hook: 1.11512 + </para> 1.11513 + <itemizedlist> 1.11514 + <listitem><para id="x_2c1"><literal moreinfo="none">local</literal>: A boolean. Whether 1.11515 + the tag is local to this repository instance (i.e. stored 1.11516 + in <filename role="special" moreinfo="none">.hg/localtags</filename>) or 1.11517 + managed by Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>). 1.11518 + </para> 1.11519 + </listitem> 1.11520 + <listitem><para id="x_2c2"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11521 + ID of the changeset to be tagged. 1.11522 + </para> 1.11523 + </listitem> 1.11524 + <listitem><para id="x_2c3"><literal moreinfo="none">tag</literal>: A string. The name of 1.11525 + the tag to be created. 1.11526 + </para> 1.11527 + </listitem></itemizedlist> 1.11528 + 1.11529 + <para id="x_2c4">If the tag to be created is 1.11530 + 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. 1.11531 + </para> 1.11532 + 1.11533 + <para id="x_2c5">See also: <literal role="hook" moreinfo="none">tag</literal> 1.11534 + (<xref linkend="sec:hook:tag"/>) 1.11535 + </para> 1.11536 + </sect2> 1.11537 + 1.11538 + <sect2 id="sec:hook:pretxnchangegroup"> 1.11539 + <title><literal role="hook" moreinfo="none">pretxnchangegroup</literal>—before 1.11540 + completing addition of remote changesets</title> 1.11541 + 1.11542 + <para id="x_2c6">This controlling hook is run before a 1.11543 + transaction—that manages the addition of a group of new 1.11544 + changesets from outside the repository—completes. If 1.11545 + the hook succeeds, the transaction completes, and all of the 1.11546 + changesets become permanent within this repository. If the 1.11547 + hook fails, the transaction is rolled back, and the data for 1.11548 + the changesets is erased. 1.11549 + </para> 1.11550 + 1.11551 + <para id="x_2c7">This hook can access the metadata associated with the 1.11552 + almost-added changesets, but it should not do anything 1.11553 + permanent with this data. It must also not modify the working 1.11554 + directory. 1.11555 + </para> 1.11556 + 1.11557 + <para id="x_2c8">While this hook is running, if other Mercurial processes 1.11558 + access this repository, they will be able to see the 1.11559 + almost-added changesets as if they are permanent. This may 1.11560 + lead to race conditions if you do not take steps to avoid 1.11561 + them. 1.11562 + </para> 1.11563 + 1.11564 + <para id="x_2c9">This hook can be used to automatically vet a group of 1.11565 + changesets. If the hook fails, all of the changesets are 1.11566 + <quote>rejected</quote> when the transaction rolls back. 1.11567 + </para> 1.11568 + 1.11569 + <para id="x_2ca">Parameters to this hook: 1.11570 + </para> 1.11571 + <itemizedlist> 1.11572 + <listitem><para id="x_2cb"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11573 + changeset ID of the first changeset in the group that was 1.11574 + added. All changesets between this and 1.11575 + <literal role="tag" moreinfo="none">tip</literal>, 1.11576 + 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>. 1.11577 + </para> 1.11578 + </listitem> 1.11579 + <listitem><para id="x_2cc"><literal moreinfo="none">source</literal>: A 1.11580 + string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details. 1.11581 + </para> 1.11582 + </listitem> 1.11583 + <listitem><para id="x_2cd"><literal moreinfo="none">url</literal>: A URL. The 1.11584 + location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. 1.11585 + </para> 1.11586 + </listitem></itemizedlist> 1.11587 + 1.11588 + <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"/>) 1.11589 + </para> 1.11590 + </sect2> 1.11591 + 1.11592 + <sect2 id="sec:hook:pretxncommit"> 1.11593 + <title><literal role="hook" moreinfo="none">pretxncommit</literal>—before 1.11594 + completing commit of new changeset</title> 1.11595 + 1.11596 + <para id="x_2cf">This controlling hook is run before a 1.11597 + transaction—that manages a new commit—completes. 1.11598 + If the hook succeeds, the transaction completes and the 1.11599 + changeset becomes permanent within this repository. If the 1.11600 + hook fails, the transaction is rolled back, and the commit 1.11601 + data is erased. 1.11602 + </para> 1.11603 + 1.11604 + <para id="x_2d0">This hook can access the metadata associated with the 1.11605 + almost-new changeset, but it should not do anything permanent 1.11606 + with this data. It must also not modify the working 1.11607 + directory. 1.11608 + </para> 1.11609 + 1.11610 + <para id="x_2d1">While this hook is running, if other Mercurial processes 1.11611 + access this repository, they will be able to see the 1.11612 + almost-new changeset as if it is permanent. This may lead to 1.11613 + race conditions if you do not take steps to avoid them. 1.11614 + </para> 1.11615 + 1.11616 + <para id="x_2d2">Parameters to this hook:</para> 1.11617 + 1.11618 + <itemizedlist> 1.11619 + <listitem><para id="x_2d3"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11620 + changeset ID of the newly committed changeset. 1.11621 + </para> 1.11622 + </listitem> 1.11623 + <listitem><para id="x_2d4"><literal moreinfo="none">parent1</literal>: A changeset ID. 1.11624 + The changeset ID of the first parent of the newly 1.11625 + committed changeset. 1.11626 + </para> 1.11627 + </listitem> 1.11628 + <listitem><para id="x_2d5"><literal moreinfo="none">parent2</literal>: A changeset ID. 1.11629 + The changeset ID of the second parent of the newly 1.11630 + committed changeset. 1.11631 + </para> 1.11632 + </listitem></itemizedlist> 1.11633 + 1.11634 + <para id="x_2d6">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>) 1.11635 + </para> 1.11636 + </sect2> 1.11637 + 1.11638 + <sect2 id="sec:hook:preupdate"> 1.11639 + <title><literal role="hook" moreinfo="none">preupdate</literal>—before 1.11640 + updating or merging working directory</title> 1.11641 + 1.11642 + <para id="x_2d7">This controlling hook is run before an update 1.11643 + or merge of the working directory begins. It is run only if 1.11644 + Mercurial's normal pre-update checks determine that the update 1.11645 + or merge can proceed. If the hook succeeds, the update or 1.11646 + merge may proceed; if it fails, the update or merge does not 1.11647 + start. 1.11648 + </para> 1.11649 + 1.11650 + <para id="x_2d8">Parameters to this hook: 1.11651 + </para> 1.11652 + <itemizedlist> 1.11653 + <listitem><para id="x_2d9"><literal moreinfo="none">parent1</literal>: A 1.11654 + changeset ID. The ID of the parent that the working 1.11655 + directory is to be updated to. If the working directory 1.11656 + is being merged, it will not change this parent. 1.11657 + </para> 1.11658 + </listitem> 1.11659 + <listitem><para id="x_2da"><literal moreinfo="none">parent2</literal>: A 1.11660 + changeset ID. Only set if the working directory is being 1.11661 + merged. The ID of the revision that the working directory 1.11662 + is being merged with. 1.11663 + </para> 1.11664 + </listitem></itemizedlist> 1.11665 + 1.11666 + <para id="x_2db">See also: <literal role="hook" moreinfo="none">update</literal> 1.11667 + (<xref linkend="sec:hook:update"/>)</para> 1.11668 + </sect2> 1.11669 + 1.11670 + <sect2 id="sec:hook:tag"> 1.11671 + <title><literal role="hook" moreinfo="none">tag</literal>—after tagging a 1.11672 + changeset</title> 1.11673 + 1.11674 + <para id="x_2dc">This hook is run after a tag has been created. 1.11675 + </para> 1.11676 + 1.11677 + <para id="x_2dd">Parameters to this hook: 1.11678 + </para> 1.11679 + <itemizedlist> 1.11680 + <listitem><para id="x_2de"><literal moreinfo="none">local</literal>: A boolean. Whether 1.11681 + the new tag is local to this repository instance (i.e. 1.11682 + stored in <filename role="special" moreinfo="none">.hg/localtags</filename>) or managed by 1.11683 + Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>). 1.11684 + </para> 1.11685 + </listitem> 1.11686 + <listitem><para id="x_2df"><literal moreinfo="none">node</literal>: A changeset ID. The 1.11687 + ID of the changeset that was tagged. 1.11688 + </para> 1.11689 + </listitem> 1.11690 + <listitem><para id="x_2e0"><literal moreinfo="none">tag</literal>: A string. The name of 1.11691 + the tag that was created. 1.11692 + </para> 1.11693 + </listitem></itemizedlist> 1.11694 + 1.11695 + <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. 1.11696 + </para> 1.11697 + 1.11698 + <para id="x_2e2">See also: <literal role="hook" moreinfo="none">pretag</literal> 1.11699 + (<xref linkend="sec:hook:pretag"/>) 1.11700 + </para> 1.11701 + </sect2> 1.11702 + 1.11703 + <sect2 id="sec:hook:update"> 1.11704 + <title><literal role="hook" moreinfo="none">update</literal>—after 1.11705 + updating or merging working directory</title> 1.11706 + 1.11707 + <para id="x_2e3">This hook is run after an update or merge of the working 1.11708 + directory completes. Since a merge can fail (if the external 1.11709 + <command moreinfo="none">hgmerge</command> command fails to resolve conflicts 1.11710 + in a file), this hook communicates whether the update or merge 1.11711 + completed cleanly. 1.11712 + </para> 1.11713 + 1.11714 + <itemizedlist> 1.11715 + <listitem><para id="x_2e4"><literal moreinfo="none">error</literal>: A boolean. 1.11716 + Indicates whether the update or merge completed 1.11717 + successfully. 1.11718 + </para> 1.11719 + </listitem> 1.11720 + <listitem><para id="x_2e5"><literal moreinfo="none">parent1</literal>: A changeset ID. 1.11721 + The ID of the parent that the working directory was 1.11722 + updated to. If the working directory was merged, it will 1.11723 + not have changed this parent. 1.11724 + </para> 1.11725 + </listitem> 1.11726 + <listitem><para id="x_2e6"><literal moreinfo="none">parent2</literal>: A changeset ID. 1.11727 + Only set if the working directory was merged. The ID of 1.11728 + the revision that the working directory was merged with. 1.11729 + </para> 1.11730 + </listitem></itemizedlist> 1.11731 + 1.11732 + <para id="x_2e7">See also: <literal role="hook" moreinfo="none">preupdate</literal> 1.11733 + (<xref linkend="sec:hook:preupdate"/>) 1.11734 + </para> 1.11735 + 1.11736 + </sect2> 1.11737 + </sect1> 1.11738 +</chapter> 1.11739 + 1.11740 +<!-- 1.11741 +local variables: 1.11742 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.11743 +end: 1.11744 +--> 1.11745 + 1.11746 + <!-- BEGIN ch11 --> 1.11747 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.11748 + 1.11749 +<chapter id="chap:template"> 1.11750 + <?dbhtml filename="customizing-the-output-of-mercurial.html"?> 1.11751 + <title>Customizing the output of Mercurial</title> 1.11752 + 1.11753 + <para id="x_578">Mercurial provides a powerful mechanism to let you control how 1.11754 + it displays information. The mechanism is based on templates. 1.11755 + You can use templates to generate specific output for a single 1.11756 + command, or to customize the entire appearance of the built-in web 1.11757 + interface.</para> 1.11758 + 1.11759 + <sect1 id="sec:style"> 1.11760 + <title>Using precanned output styles</title> 1.11761 + 1.11762 + <para id="x_579">Packaged with Mercurial are some output styles that you can 1.11763 + use immediately. A style is simply a precanned template that 1.11764 + someone wrote and installed somewhere that Mercurial can 1.11765 + find.</para> 1.11766 + 1.11767 + <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's 1.11768 + review its normal output.</para> 1.11769 + 1.11770 + <!-- BEGIN template.simple.normal --> 1.11771 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput> 1.11772 +changeset: 1:e3d2468ca47c 1.11773 +tag: mytag 1.11774 +user: Bryan O'Sullivan <bos@serpentine.com> 1.11775 +date: Sun Aug 16 14:05:17 2009 +0000 1.11776 +summary: added line to end of <<hello>> file. 1.11777 + 1.11778 +</screen> 1.11779 +<!-- END template.simple.normal --> 1.11780 + 1.11781 + 1.11782 + <para id="x_57b">This is somewhat informative, but it takes up a lot of 1.11783 + space—five lines of output per changeset. The 1.11784 + <literal moreinfo="none">compact</literal> style reduces this to three lines, 1.11785 + presented in a sparse manner.</para> 1.11786 + 1.11787 + <!-- BEGIN template.simple.compact --> 1.11788 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput> 1.11789 +3[tip] d3cc7424d32c 2009-08-16 14:05 +0000 bos 1.11790 + Added tag v0.1 for changeset a5dd5392119b 1.11791 + 1.11792 +2[v0.1] a5dd5392119b 2009-08-16 14:05 +0000 bos 1.11793 + Added tag mytag for changeset e3d2468ca47c 1.11794 + 1.11795 +1[mytag] e3d2468ca47c 2009-08-16 14:05 +0000 bos 1.11796 + added line to end of <<hello>> file. 1.11797 + 1.11798 +0 1cf727e9fc61 2009-08-16 14:05 +0000 bos 1.11799 + added hello 1.11800 + 1.11801 +</screen> 1.11802 +<!-- END template.simple.compact --> 1.11803 + 1.11804 + 1.11805 + <para id="x_57c">The <literal moreinfo="none">changelog</literal> style hints at the 1.11806 + expressive power of Mercurial's templating engine. This style 1.11807 + attempts to follow the GNU Project's changelog 1.11808 + guidelines<citation>web:changelog</citation>.</para> 1.11809 + 1.11810 + <!-- BEGIN template.simple.changelog --> 1.11811 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style changelog</userinput> 1.11812 +2009-08-16 Bryan O'Sullivan <bos@serpentine.com> 1.11813 + 1.11814 + * .hgtags: 1.11815 + Added tag v0.1 for changeset a5dd5392119b 1.11816 + [d3cc7424d32c] [tip] 1.11817 + 1.11818 + * .hgtags: 1.11819 + Added tag mytag for changeset e3d2468ca47c 1.11820 + [a5dd5392119b] [v0.1] 1.11821 + 1.11822 + * goodbye, hello: 1.11823 + added line to end of <<hello>> file. 1.11824 + 1.11825 + in addition, added a file with the helpful name (at least i hope 1.11826 + that some might consider it so) of goodbye. 1.11827 + [e3d2468ca47c] [mytag] 1.11828 + 1.11829 + * hello: 1.11830 + added hello 1.11831 + [1cf727e9fc61] 1.11832 + 1.11833 +</screen> 1.11834 +<!-- END template.simple.changelog --> 1.11835 + 1.11836 + 1.11837 + <para id="x_57d">You will not be shocked to learn that Mercurial's default 1.11838 + output style is named <literal moreinfo="none">default</literal>.</para> 1.11839 + 1.11840 + <sect2> 1.11841 + <title>Setting a default style</title> 1.11842 + 1.11843 + <para id="x_57e">You can modify the output style that Mercurial will use 1.11844 + for every command by editing your <filename role="special" moreinfo="none">~/.hgrc</filename> file, naming the style 1.11845 + you would prefer to use.</para> 1.11846 + 1.11847 + <programlisting format="linespecific">[ui] 1.11848 +style = compact</programlisting> 1.11849 + 1.11850 + <para id="x_57f">If you write a style of your own, you can use it by either 1.11851 + providing the path to your style file, or copying your style 1.11852 + file into a location where Mercurial can find it (typically 1.11853 + the <literal moreinfo="none">templates</literal> subdirectory of your 1.11854 + Mercurial install directory).</para> 1.11855 + </sect2> 1.11856 + </sect1> 1.11857 + 1.11858 + <sect1> 1.11859 + <title>Commands that support styles and templates</title> 1.11860 + 1.11861 + <para id="x_580">All of Mercurial's 1.11862 + <quote><literal moreinfo="none">log</literal>-like</quote> commands let you use 1.11863 + styles and templates: <command role="hg-cmd" moreinfo="none">hg 1.11864 + incoming</command>, <command role="hg-cmd" moreinfo="none">hg log</command>, 1.11865 + <command role="hg-cmd" moreinfo="none">hg outgoing</command>, and <command role="hg-cmd" moreinfo="none">hg tip</command>.</para> 1.11866 + 1.11867 + <para id="x_581">As I write this manual, these are so far the only commands 1.11868 + that support styles and templates. Since these are the most 1.11869 + important commands that need customizable output, there has been 1.11870 + little pressure from the Mercurial user community to add style 1.11871 + and template support to other commands.</para> 1.11872 + </sect1> 1.11873 + 1.11874 + <sect1> 1.11875 + <title>The basics of templating</title> 1.11876 + 1.11877 + <para id="x_582">At its simplest, a Mercurial template is a piece of text. 1.11878 + Some of the text never changes, while other parts are 1.11879 + <emphasis>expanded</emphasis>, or replaced with new text, when 1.11880 + necessary.</para> 1.11881 + 1.11882 + <para id="x_583">Before we continue, let's look again at a simple example of 1.11883 + Mercurial's normal output.</para> 1.11884 + 1.11885 + <!-- BEGIN template.simple.normal --> 1.11886 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput> 1.11887 +changeset: 1:e3d2468ca47c 1.11888 +tag: mytag 1.11889 +user: Bryan O'Sullivan <bos@serpentine.com> 1.11890 +date: Sun Aug 16 14:05:17 2009 +0000 1.11891 +summary: added line to end of <<hello>> file. 1.11892 + 1.11893 +</screen> 1.11894 +<!-- END template.simple.normal --> 1.11895 + 1.11896 + 1.11897 + <para id="x_584">Now, let's run the same command, but using a template to 1.11898 + change its output.</para> 1.11899 + 1.11900 + <!-- BEGIN template.simple.simplest --> 1.11901 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'i saw a changeset\n'</userinput> 1.11902 +i saw a changeset 1.11903 +</screen> 1.11904 +<!-- END template.simple.simplest --> 1.11905 + 1.11906 + 1.11907 + <para id="x_585">The example above illustrates the simplest possible 1.11908 + template; it's just a piece of static text, printed once for 1.11909 + 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 1.11910 + the given text as the template when printing each 1.11911 + changeset.</para> 1.11912 + 1.11913 + <para id="x_586">Notice that the template string above ends with the text 1.11914 + <quote><literal moreinfo="none">\n</literal></quote>. This is an 1.11915 + <emphasis>escape sequence</emphasis>, telling Mercurial to print 1.11916 + a newline at the end of each template item. If you omit this 1.11917 + newline, Mercurial will run each piece of output together. See 1.11918 + <xref linkend="sec:template:escape"/> for more details 1.11919 + of escape sequences.</para> 1.11920 + 1.11921 + <para id="x_587">A template that prints a fixed string of text all the time 1.11922 + isn't very useful; let's try something a bit more 1.11923 + complex.</para> 1.11924 + 1.11925 + <!-- BEGIN template.simple.simplesub --> 1.11926 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --template 'i saw a changeset: {desc}\n'</userinput> 1.11927 +i saw a changeset: Added tag v0.1 for changeset a5dd5392119b 1.11928 +i saw a changeset: Added tag mytag for changeset e3d2468ca47c 1.11929 +i saw a changeset: added line to end of <<hello>> file. 1.11930 + 1.11931 +in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye. 1.11932 +i saw a changeset: added hello 1.11933 +</screen> 1.11934 +<!-- END template.simple.simplesub --> 1.11935 + 1.11936 + 1.11937 + <para id="x_588">As you can see, the string 1.11938 + <quote><literal moreinfo="none">{desc}</literal></quote> in the template has 1.11939 + been replaced in the output with the description of each 1.11940 + changeset. Every time Mercurial finds text enclosed in curly 1.11941 + braces (<quote><literal moreinfo="none">{</literal></quote> and 1.11942 + <quote><literal moreinfo="none">}</literal></quote>), it will try to replace the 1.11943 + braces and text with the expansion of whatever is inside. To 1.11944 + print a literal curly brace, you must escape it, as described in 1.11945 + <xref linkend="sec:template:escape"/>.</para> 1.11946 + </sect1> 1.11947 + 1.11948 + <sect1 id="sec:template:keyword"> 1.11949 + <title>Common template keywords</title> 1.11950 + 1.11951 + <para id="x_589">You can start writing simple templates immediately using the 1.11952 + keywords below.</para> 1.11953 + 1.11954 + <itemizedlist> 1.11955 + <listitem><para id="x_58a"><literal role="template-keyword" moreinfo="none">author</literal>: String. The 1.11956 + unmodified author of the changeset.</para> 1.11957 + </listitem> 1.11958 + <listitem><para id="x_58b"><literal role="template-keyword" moreinfo="none">branches</literal>: String. The 1.11959 + name of the branch on which the changeset was committed. 1.11960 + Will be empty if the branch name was 1.11961 + <literal moreinfo="none">default</literal>.</para> 1.11962 + </listitem> 1.11963 + <listitem><para id="x_58c"><literal role="template-keyword" moreinfo="none">date</literal>: 1.11964 + Date information. The date when the changeset was 1.11965 + committed. This is <emphasis>not</emphasis> human-readable; 1.11966 + you must pass it through a filter that will render it 1.11967 + appropriately. See <xref linkend="sec:template:filter"/> for more information 1.11968 + on filters. The date is expressed as a pair of numbers. The 1.11969 + first number is a Unix UTC timestamp (seconds since January 1.11970 + 1, 1970); the second is the offset of the committer's 1.11971 + timezone from UTC, in seconds.</para> 1.11972 + </listitem> 1.11973 + <listitem><para id="x_58d"><literal role="template-keyword" moreinfo="none">desc</literal>: 1.11974 + String. The text of the changeset description.</para> 1.11975 + </listitem> 1.11976 + <listitem><para id="x_58e"><literal role="template-keyword" moreinfo="none">files</literal>: List of strings. 1.11977 + All files modified, added, or removed by this 1.11978 + changeset.</para> 1.11979 + </listitem> 1.11980 + <listitem><para id="x_58f"><literal role="template-keyword" moreinfo="none">file_adds</literal>: List of 1.11981 + strings. Files added by this changeset.</para> 1.11982 + </listitem> 1.11983 + <listitem><para id="x_590"><literal role="template-keyword" moreinfo="none">file_dels</literal>: List of 1.11984 + strings. Files removed by this changeset.</para> 1.11985 + </listitem> 1.11986 + <listitem><para id="x_591"><literal role="template-keyword" moreinfo="none">node</literal>: 1.11987 + String. The changeset identification hash, as a 1.11988 + 40-character hexadecimal string.</para> 1.11989 + </listitem> 1.11990 + <listitem><para id="x_592"><literal role="template-keyword" moreinfo="none">parents</literal>: List of 1.11991 + strings. The parents of the changeset.</para> 1.11992 + </listitem> 1.11993 + <listitem><para id="x_593"><literal role="template-keyword" moreinfo="none">rev</literal>: 1.11994 + Integer. The repository-local changeset revision 1.11995 + number.</para> 1.11996 + </listitem> 1.11997 + <listitem><para id="x_594"><literal role="template-keyword" moreinfo="none">tags</literal>: 1.11998 + List of strings. Any tags associated with the 1.11999 + changeset.</para> 1.12000 + </listitem> 1.12001 + </itemizedlist> 1.12002 + 1.12003 + <para id="x_595">A few simple experiments will show us what to expect when we 1.12004 + use these keywords; you can see the results below.</para> 1.12005 + 1.12006 + <!-- BEGIN template.simple.keywords --> 1.12007 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'author: {author}\n'</userinput> 1.12008 +author: Bryan O'Sullivan <bos@serpentine.com> 1.12009 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'desc:\n{desc}\n'</userinput> 1.12010 +desc: 1.12011 +added line to end of <<hello>> file. 1.12012 + 1.12013 +in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye. 1.12014 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'files: {files}\n'</userinput> 1.12015 +files: goodbye hello 1.12016 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_adds: {file_adds}\n'</userinput> 1.12017 +file_adds: goodbye 1.12018 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_dels: {file_dels}\n'</userinput> 1.12019 +file_dels: 1.12020 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'node: {node}\n'</userinput> 1.12021 +node: e3d2468ca47c10bdfbbb41b367a0c84509862197 1.12022 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'parents: {parents}\n'</userinput> 1.12023 +parents: 1.12024 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'rev: {rev}\n'</userinput> 1.12025 +rev: 1 1.12026 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'tags: {tags}\n'</userinput> 1.12027 +tags: mytag 1.12028 +</screen> 1.12029 +<!-- END template.simple.keywords --> 1.12030 + 1.12031 + 1.12032 + <para id="x_596">As we noted above, the date keyword does not produce 1.12033 + human-readable output, so we must treat it specially. This 1.12034 + involves using a <emphasis>filter</emphasis>, about which more 1.12035 + in <xref linkend="sec:template:filter"/>.</para> 1.12036 + 1.12037 + <!-- BEGIN template.simple.datekeyword --> 1.12038 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date}\n'</userinput> 1.12039 +date: 1250431517.00 1.12040 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date|isodate}\n'</userinput> 1.12041 +date: 2009-08-16 14:05 +0000 1.12042 +</screen> 1.12043 +<!-- END template.simple.datekeyword --> 1.12044 + 1.12045 + </sect1> 1.12046 + 1.12047 + <sect1 id="sec:template:escape"> 1.12048 + <title>Escape sequences</title> 1.12049 + 1.12050 + <para id="x_597">Mercurial's templating engine recognises the most commonly 1.12051 + used escape sequences in strings. When it sees a backslash 1.12052 + (<quote><literal moreinfo="none">\</literal></quote>) character, it looks at the 1.12053 + following character and substitutes the two characters with a 1.12054 + single replacement, as described below.</para> 1.12055 + 1.12056 + <itemizedlist> 1.12057 + <listitem><para id="x_598"><literal moreinfo="none">\</literal>: 1.12058 + Backslash, <quote><literal moreinfo="none">\</literal></quote>, ASCII 1.12059 + 134.</para> 1.12060 + </listitem> 1.12061 + <listitem><para id="x_599"><literal moreinfo="none">\n</literal>: Newline, 1.12062 + ASCII 12.</para> 1.12063 + </listitem> 1.12064 + <listitem><para id="x_59a"><literal moreinfo="none">\r</literal>: Carriage 1.12065 + return, ASCII 15.</para> 1.12066 + </listitem> 1.12067 + <listitem><para id="x_59b"><literal moreinfo="none">\t</literal>: Tab, ASCII 1.12068 + 11.</para> 1.12069 + </listitem> 1.12070 + <listitem><para id="x_59c"><literal moreinfo="none">\v</literal>: Vertical 1.12071 + tab, ASCII 13.</para> 1.12072 + </listitem> 1.12073 + <listitem><para id="x_59d"><literal moreinfo="none">\{</literal>: Open curly 1.12074 + brace, <quote><literal moreinfo="none">{</literal></quote>, ASCII 1.12075 + 173.</para> 1.12076 + </listitem> 1.12077 + <listitem><para id="x_59e"><literal moreinfo="none">\}</literal>: Close curly 1.12078 + brace, <quote><literal moreinfo="none">}</literal></quote>, ASCII 1.12079 + 175.</para> 1.12080 + </listitem></itemizedlist> 1.12081 + 1.12082 + <para id="x_59f">As indicated above, if you want the expansion of a template 1.12083 + to contain a literal <quote><literal moreinfo="none">\</literal></quote>, 1.12084 + <quote><literal moreinfo="none">{</literal></quote>, or 1.12085 + <quote><literal moreinfo="none">{</literal></quote> character, you must escape 1.12086 + it.</para> 1.12087 + </sect1> 1.12088 + 1.12089 + <sect1 id="sec:template:filter"> 1.12090 + <title>Filtering keywords to change their results</title> 1.12091 + 1.12092 + <para id="x_5a0">Some of the results of template expansion are not 1.12093 + immediately easy to use. Mercurial lets you specify an optional 1.12094 + chain of <emphasis>filters</emphasis> to modify the result of 1.12095 + expanding a keyword. You have already seen a common filter, 1.12096 + <literal role="template-kw-filt-date" moreinfo="none">isodate</literal>, in 1.12097 + action above, to make a date readable.</para> 1.12098 + 1.12099 + <para id="x_5a1">Below is a list of the most commonly used filters that 1.12100 + Mercurial supports. While some filters can be applied to any 1.12101 + text, others can only be used in specific circumstances. The 1.12102 + name of each filter is followed first by an indication of where 1.12103 + it can be used, then a description of its effect.</para> 1.12104 + 1.12105 + <itemizedlist> 1.12106 + <listitem><para id="x_5a2"><literal role="template-filter" moreinfo="none">addbreaks</literal>: Any text. Add 1.12107 + an XHTML <quote><literal moreinfo="none"><br/></literal></quote> tag 1.12108 + before the end of every line except the last. For example, 1.12109 + <quote><literal moreinfo="none">foo\nbar</literal></quote> becomes 1.12110 + <quote><literal moreinfo="none">foo<br/>\nbar</literal></quote>.</para> 1.12111 + </listitem> 1.12112 + <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 1.12113 + the age of the date, relative to the current time. Yields a 1.12114 + string like <quote><literal moreinfo="none">10 1.12115 + minutes</literal></quote>.</para> 1.12116 + </listitem> 1.12117 + <listitem><para id="x_5a4"><literal role="template-filter" moreinfo="none">basename</literal>: Any text, but 1.12118 + most useful for the <literal role="template-keyword" moreinfo="none">files</literal> keyword and its 1.12119 + relatives. Treat the text as a path, and return the 1.12120 + basename. For example, 1.12121 + <quote><literal moreinfo="none">foo/bar/baz</literal></quote> becomes 1.12122 + <quote><literal moreinfo="none">baz</literal></quote>.</para> 1.12123 + </listitem> 1.12124 + <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 1.12125 + date in a similar format to the Unix <literal role="template-keyword" moreinfo="none">date</literal> command, but with 1.12126 + timezone included. Yields a string like <quote><literal moreinfo="none">Mon 1.12127 + Sep 04 15:13:13 2006 -0700</literal></quote>.</para> 1.12128 + </listitem> 1.12129 + <listitem><para id="x_5a6"><literal role="template-kw-filt-author" moreinfo="none">domain</literal>: Any text, 1.12130 + but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Finds 1.12131 + the first string that looks like an email address, and 1.12132 + extract just the domain component. For example, 1.12133 + <quote><literal moreinfo="none">Bryan O'Sullivan 1.12134 + <bos@serpentine.com></literal></quote> becomes 1.12135 + <quote><literal moreinfo="none">serpentine.com</literal></quote>.</para> 1.12136 + </listitem> 1.12137 + <listitem><para id="x_5a7"><literal role="template-kw-filt-author" moreinfo="none">email</literal>: Any text, 1.12138 + but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Extract 1.12139 + the first string that looks like an email address. For 1.12140 + example, <quote><literal moreinfo="none">Bryan O'Sullivan 1.12141 + <bos@serpentine.com></literal></quote> becomes 1.12142 + <quote><literal moreinfo="none">bos@serpentine.com</literal></quote>.</para> 1.12143 + </listitem> 1.12144 + <listitem><para id="x_5a8"><literal role="template-filter" moreinfo="none">escape</literal>: Any text. 1.12145 + Replace the special XML/XHTML characters 1.12146 + <quote><literal moreinfo="none">&</literal></quote>, 1.12147 + <quote><literal moreinfo="none"><</literal></quote> and 1.12148 + <quote><literal moreinfo="none">></literal></quote> with XML 1.12149 + entities.</para> 1.12150 + </listitem> 1.12151 + <listitem><para id="x_5a9"><literal role="template-filter" moreinfo="none">fill68</literal>: Any text. Wrap 1.12152 + the text to fit in 68 columns. This is useful before you 1.12153 + pass text through the <literal role="template-filter" moreinfo="none">tabindent</literal> filter, and 1.12154 + still want it to fit in an 80-column fixed-font 1.12155 + window.</para> 1.12156 + </listitem> 1.12157 + <listitem><para id="x_5aa"><literal role="template-filter" moreinfo="none">fill76</literal>: Any text. Wrap 1.12158 + the text to fit in 76 columns.</para> 1.12159 + </listitem> 1.12160 + <listitem><para id="x_5ab"><literal role="template-filter" moreinfo="none">firstline</literal>: Any text. 1.12161 + Yield the first line of text, without any trailing 1.12162 + newlines.</para> 1.12163 + </listitem> 1.12164 + <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 1.12165 + the date as a pair of readable numbers. Yields a string 1.12166 + like <quote><literal moreinfo="none">1157407993 1.12167 + 25200</literal></quote>.</para> 1.12168 + </listitem> 1.12169 + <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 1.12170 + the date as a text string in ISO 8601 format. Yields a 1.12171 + string like <quote><literal moreinfo="none">2006-09-04 15:13:13 1.12172 + -0700</literal></quote>.</para> 1.12173 + </listitem> 1.12174 + <listitem><para id="x_5ae"><literal role="template-filter" moreinfo="none">obfuscate</literal>: Any text, but 1.12175 + most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Yield 1.12176 + the input text rendered as a sequence of XML entities. This 1.12177 + helps to defeat some particularly stupid screen-scraping 1.12178 + email harvesting spambots.</para> 1.12179 + </listitem> 1.12180 + <listitem><para id="x_5af"><literal role="template-kw-filt-author" moreinfo="none">person</literal>: Any text, 1.12181 + but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Yield 1.12182 + the text before an email address. For example, 1.12183 + <quote><literal moreinfo="none">Bryan O'Sullivan 1.12184 + <bos@serpentine.com></literal></quote> becomes 1.12185 + <quote><literal moreinfo="none">Bryan O'Sullivan</literal></quote>.</para> 1.12186 + </listitem> 1.12187 + <listitem><para id="x_5b0"><literal role="template-kw-filt-date" moreinfo="none">rfc822date</literal>: 1.12188 + <literal role="template-keyword" moreinfo="none">date</literal> keyword. 1.12189 + Render a date using the same format used in email headers. 1.12190 + Yields a string like <quote><literal moreinfo="none">Mon, 04 Sep 2006 1.12191 + 15:13:13 -0700</literal></quote>.</para> 1.12192 + </listitem> 1.12193 + <listitem><para id="x_5b1"><literal role="template-kw-filt-node" moreinfo="none">short</literal>: Changeset 1.12194 + hash. Yield the short form of a changeset hash, i.e. a 1.12195 + 12-character hexadecimal string.</para> 1.12196 + </listitem> 1.12197 + <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 1.12198 + the year, month, and day of the date. Yields a string like 1.12199 + <quote><literal moreinfo="none">2006-09-04</literal></quote>.</para> 1.12200 + </listitem> 1.12201 + <listitem><para id="x_5b3"><literal role="template-filter" moreinfo="none">strip</literal>: 1.12202 + Any text. Strip all leading and trailing whitespace from 1.12203 + the string.</para> 1.12204 + </listitem> 1.12205 + <listitem><para id="x_5b4"><literal role="template-filter" moreinfo="none">tabindent</literal>: Any text. 1.12206 + Yield the text, with every line except the first starting 1.12207 + with a tab character.</para> 1.12208 + </listitem> 1.12209 + <listitem><para id="x_5b5"><literal role="template-filter" moreinfo="none">urlescape</literal>: Any text. 1.12210 + Escape all characters that are considered 1.12211 + <quote>special</quote> by URL parsers. For example, 1.12212 + <literal moreinfo="none">foo bar</literal> becomes 1.12213 + <literal moreinfo="none">foo%20bar</literal>.</para> 1.12214 + </listitem> 1.12215 + <listitem><para id="x_5b6"><literal role="template-kw-filt-author" moreinfo="none">user</literal>: Any text, 1.12216 + but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Return 1.12217 + the <quote>user</quote> portion of an email address. For 1.12218 + example, <quote><literal moreinfo="none">Bryan O'Sullivan 1.12219 + <bos@serpentine.com></literal></quote> becomes 1.12220 + <quote><literal moreinfo="none">bos</literal></quote>.</para> 1.12221 + </listitem> 1.12222 + </itemizedlist> 1.12223 + 1.12224 + <!-- BEGIN template.simple.manyfilters --> 1.12225 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author}\n'</userinput> 1.12226 +Bryan O'Sullivan <bos@serpentine.com> 1.12227 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|domain}\n'</userinput> 1.12228 +serpentine.com 1.12229 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|email}\n'</userinput> 1.12230 +bos@serpentine.com 1.12231 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|obfuscate}\n' | cut -c-76</userinput> 1.12232 +&#66;&#114;&#121;&#97;&#110;&#32;&#79;&#39;&#83;&#117;&#108;&#108;&#105;&#11 1.12233 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|person}\n'</userinput> 1.12234 +Bryan O'Sullivan 1.12235 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|user}\n'</userinput> 1.12236 +bos 1.12237 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'</userinput> 1.12238 +looks almost right, but actually garbage: 1250431517.00 1.12239 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|age}\n'</userinput> 1.12240 +3 seconds 1.12241 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|date}\n'</userinput> 1.12242 +Sun Aug 16 14:05:17 2009 +0000 1.12243 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|hgdate}\n'</userinput> 1.12244 +1250431517 0 1.12245 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|isodate}\n'</userinput> 1.12246 +2009-08-16 14:05 +0000 1.12247 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|rfc822date}\n'</userinput> 1.12248 +Sun, 16 Aug 2009 14:05:17 +0000 1.12249 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|shortdate}\n'</userinput> 1.12250 +2009-08-16 1.12251 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc}\n' | cut -c-76</userinput> 1.12252 +added line to end of <<hello>> file. 1.12253 + 1.12254 +in addition, added a file with the helpful name (at least i hope that some m 1.12255 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76</userinput> 1.12256 +added line to end of <<hello>> file.<br/> 1.12257 +<br/> 1.12258 +in addition, added a file with the helpful name (at least i hope that some m 1.12259 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|escape}\n' | cut -c-76</userinput> 1.12260 +added line to end of &lt;&lt;hello&gt;&gt; file. 1.12261 + 1.12262 +in addition, added a file with the helpful name (at least i hope that some m 1.12263 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill68}\n'</userinput> 1.12264 +added line to end of <<hello>> file. 1.12265 + 1.12266 +in addition, added a file with the helpful name (at least i hope 1.12267 +that some might consider it so) of goodbye. 1.12268 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill76}\n'</userinput> 1.12269 +added line to end of <<hello>> file. 1.12270 + 1.12271 +in addition, added a file with the helpful name (at least i hope that some 1.12272 +might consider it so) of goodbye. 1.12273 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|firstline}\n'</userinput> 1.12274 +added line to end of <<hello>> file. 1.12275 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|strip}\n' | cut -c-76</userinput> 1.12276 +added line to end of <<hello>> file. 1.12277 + 1.12278 +in addition, added a file with the helpful name (at least i hope that some m 1.12279 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76</userinput> 1.12280 +added line to end of <<hello>> file. 1.12281 + 1.12282 + in addition, added a file with the helpful name (at least i hope tha 1.12283 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node}\n'</userinput> 1.12284 +e3d2468ca47c10bdfbbb41b367a0c84509862197 1.12285 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node|short}\n'</userinput> 1.12286 +e3d2468ca47c 1.12287 +</screen> 1.12288 +<!-- END template.simple.manyfilters --> 1.12289 + 1.12290 + 1.12291 + <note> 1.12292 + <para id="x_5b7"> If you try to apply a filter to a piece of data that it 1.12293 + cannot process, Mercurial will fail and print a Python 1.12294 + exception. For example, trying to run the output of the 1.12295 + <literal role="template-keyword" moreinfo="none">desc</literal> keyword into 1.12296 + the <literal role="template-kw-filt-date" moreinfo="none">isodate</literal> 1.12297 + filter is not a good idea.</para> 1.12298 + </note> 1.12299 + 1.12300 + <sect2> 1.12301 + <title>Combining filters</title> 1.12302 + 1.12303 + <para id="x_5b8">It is easy to combine filters to yield output in the form 1.12304 + you would like. The following chain of filters tidies up a 1.12305 + description, then makes sure that it fits cleanly into 68 1.12306 + columns, then indents it by a further 8 characters (at least 1.12307 + on Unix-like systems, where a tab is conventionally 8 1.12308 + characters wide).</para> 1.12309 + 1.12310 + <!-- BEGIN template.simple.combine --> 1.12311 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'</userinput> 1.12312 +description: 1.12313 + added line to end of <<hello>> file. 1.12314 + 1.12315 + in addition, added a file with the helpful name (at least i hope 1.12316 + that some might consider it so) of goodbye. 1.12317 +</screen> 1.12318 +<!-- END template.simple.combine --> 1.12319 + 1.12320 + 1.12321 + <para id="x_5b9">Note the use of <quote><literal moreinfo="none">\t</literal></quote> (a 1.12322 + tab character) in the template to force the first line to be 1.12323 + indented; this is necessary since <literal role="template-keyword" moreinfo="none">tabindent</literal> indents all 1.12324 + lines <emphasis>except</emphasis> the first.</para> 1.12325 + 1.12326 + <para id="x_5ba">Keep in mind that the order of filters in a chain is 1.12327 + significant. The first filter is applied to the result of the 1.12328 + keyword; the second to the result of the first filter; and so 1.12329 + on. For example, using <literal moreinfo="none">fill68|tabindent</literal> 1.12330 + gives very different results from 1.12331 + <literal moreinfo="none">tabindent|fill68</literal>.</para> 1.12332 + </sect2> 1.12333 + </sect1> 1.12334 + 1.12335 + <sect1> 1.12336 + <title>From templates to styles</title> 1.12337 + 1.12338 + <para id="x_5bb">A command line template provides a quick and simple way to 1.12339 + format some output. Templates can become verbose, though, and 1.12340 + it's useful to be able to give a template a name. A style file 1.12341 + is a template with a name, stored in a file.</para> 1.12342 + 1.12343 + <para id="x_5bc">More than that, using a style file unlocks the power of 1.12344 + Mercurial's templating engine in ways that are not possible 1.12345 + using the command line <option role="hg-opt-log">--template</option> option.</para> 1.12346 + 1.12347 + <sect2> 1.12348 + <title>The simplest of style files</title> 1.12349 + 1.12350 + <para id="x_5bd">Our simple style file contains just one line:</para> 1.12351 + 1.12352 + <!-- BEGIN template.simple.rev --> 1.12353 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'changeset = "rev: {rev}\n"' > rev</userinput> 1.12354 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -l1 --style ./rev</userinput> 1.12355 +rev: 3 1.12356 +</screen> 1.12357 +<!-- END template.simple.rev --> 1.12358 + 1.12359 + 1.12360 + <para id="x_5be">This tells Mercurial, <quote>if you're printing a 1.12361 + changeset, use the text on the right as the 1.12362 + template</quote>.</para> 1.12363 + </sect2> 1.12364 + 1.12365 + <sect2> 1.12366 + <title>Style file syntax</title> 1.12367 + 1.12368 + <para id="x_5bf">The syntax rules for a style file are simple.</para> 1.12369 + 1.12370 + <itemizedlist> 1.12371 + <listitem><para id="x_5c0">The file is processed one line at a 1.12372 + time.</para> 1.12373 + </listitem> 1.12374 + <listitem><para id="x_5c1">Leading and trailing white space are 1.12375 + ignored.</para> 1.12376 + </listitem> 1.12377 + <listitem><para id="x_5c2">Empty lines are skipped.</para> 1.12378 + </listitem> 1.12379 + <listitem><para id="x_5c3">If a line starts with either of the characters 1.12380 + <quote><literal moreinfo="none">#</literal></quote> or 1.12381 + <quote><literal moreinfo="none">;</literal></quote>, the entire line is 1.12382 + treated as a comment, and skipped as if empty.</para> 1.12383 + </listitem> 1.12384 + <listitem><para id="x_5c4">A line starts with a keyword. This must start 1.12385 + with an alphabetic character or underscore, and can 1.12386 + subsequently contain any alphanumeric character or 1.12387 + underscore. (In regexp notation, a keyword must match 1.12388 + <literal moreinfo="none">[A-Za-z_][A-Za-z0-9_]*</literal>.)</para> 1.12389 + </listitem> 1.12390 + <listitem><para id="x_5c5">The next element must be an 1.12391 + <quote><literal moreinfo="none">=</literal></quote> character, which can 1.12392 + be preceded or followed by an arbitrary amount of white 1.12393 + space.</para> 1.12394 + </listitem> 1.12395 + <listitem><para id="x_5c6">If the rest of the line starts and ends with 1.12396 + matching quote characters (either single or double quote), 1.12397 + it is treated as a template body.</para> 1.12398 + </listitem> 1.12399 + <listitem><para id="x_5c7">If the rest of the line <emphasis>does 1.12400 + not</emphasis> start with a quote character, it is 1.12401 + treated as the name of a file; the contents of this file 1.12402 + will be read and used as a template body.</para> 1.12403 + </listitem></itemizedlist> 1.12404 + </sect2> 1.12405 + </sect1> 1.12406 + 1.12407 + <sect1> 1.12408 + <title>Style files by example</title> 1.12409 + 1.12410 + <para id="x_5c8">To illustrate how to write a style file, we will construct a 1.12411 + few by example. Rather than provide a complete style file and 1.12412 + walk through it, we'll mirror the usual process of developing a 1.12413 + style file by starting with something very simple, and walking 1.12414 + through a series of successively more complete examples.</para> 1.12415 + 1.12416 + <sect2> 1.12417 + <title>Identifying mistakes in style files</title> 1.12418 + 1.12419 + <para id="x_5c9">If Mercurial encounters a problem in a style file you are 1.12420 + working on, it prints a terse error message that, once you 1.12421 + figure out what it means, is actually quite useful.</para> 1.12422 + 1.12423 +<!-- BEGIN template.svnstyle.syntax.input --> 1.12424 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat broken.style</userinput> 1.12425 +changeset = 1.12426 +</screen> 1.12427 +<!-- END template.svnstyle.syntax.input --> 1.12428 + 1.12429 + 1.12430 + <para id="x_5ca">Notice that <filename moreinfo="none">broken.style</filename> attempts to 1.12431 + define a <literal moreinfo="none">changeset</literal> keyword, but forgets to 1.12432 + give any content for it. When instructed to use this style 1.12433 + file, Mercurial promptly complains.</para> 1.12434 + 1.12435 + <!-- BEGIN template.svnstyle.syntax.error --> 1.12436 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --style broken.style</userinput> 1.12437 +abort: broken.style:1: parse error 1.12438 +</screen> 1.12439 +<!-- END template.svnstyle.syntax.error --> 1.12440 + 1.12441 + 1.12442 + <para id="x_5cb">This error message looks intimidating, but it is not too 1.12443 + hard to follow.</para> 1.12444 + 1.12445 + <itemizedlist> 1.12446 + <listitem><para id="x_5cc">The first component is simply Mercurial's way 1.12447 + of saying <quote>I am giving up</quote>.</para> 1.12448 + <programlisting format="linespecific">___abort___: broken.style:1: parse error</programlisting> 1.12449 + </listitem> 1.12450 + <listitem><para id="x_5cd">Next comes the name of the style file that 1.12451 + contains the error.</para> 1.12452 + <programlisting format="linespecific">abort: ___broken.style___:1: parse error</programlisting> 1.12453 + </listitem> 1.12454 + <listitem><para id="x_5ce">Following the file name is the line number 1.12455 + where the error was encountered.</para> 1.12456 + <programlisting format="linespecific">abort: broken.style:___1___: parse error</programlisting> 1.12457 + </listitem> 1.12458 + <listitem><para id="x_5cf">Finally, a description of what went 1.12459 + wrong.</para> 1.12460 + <programlisting format="linespecific">abort: broken.style:1: ___parse error___</programlisting> 1.12461 + </listitem> 1.12462 + <listitem><para id="x_5d0">The description of the problem is not always 1.12463 + clear (as in this case), but even when it is cryptic, it 1.12464 + is almost always trivial to visually inspect the offending 1.12465 + line in the style file and see what is wrong.</para> 1.12466 + </listitem> 1.12467 + </itemizedlist> 1.12468 + </sect2> 1.12469 + 1.12470 + <sect2> 1.12471 + <title>Uniquely identifying a repository</title> 1.12472 + 1.12473 + <para id="x_5d1">If you would like to be able to identify a Mercurial 1.12474 + repository <quote>fairly uniquely</quote> using a short string 1.12475 + as an identifier, you can use the first revision in the 1.12476 + repository.</para> 1.12477 + 1.12478 + <!-- BEGIN template.svnstyle.id --> 1.12479 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r0 --template '{node}'</userinput> 1.12480 +02b4f9d8a52a6da645e20fa7df0accc8aa33b650</screen> 1.12481 +<!-- END template.svnstyle.id --> 1.12482 + 1.12483 + 1.12484 + <para id="x_5d2">This is likely to be unique, and so it is 1.12485 + useful in many cases. There are a few caveats.</para> 1.12486 + <itemizedlist> 1.12487 + <listitem><para id="x_5d3">It will not work in a completely empty 1.12488 + repository, because such a repository does not have a 1.12489 + revision zero.</para> 1.12490 + </listitem> 1.12491 + <listitem><para id="x_5d4">Neither will it work in the (extremely rare) 1.12492 + case where a repository is a merge of two or more formerly 1.12493 + independent repositories, and you still have those 1.12494 + repositories around.</para> 1.12495 + </listitem></itemizedlist> 1.12496 + <para id="x_5d5">Here are some uses to which you could put this 1.12497 + identifier:</para> 1.12498 + <itemizedlist> 1.12499 + <listitem><para id="x_5d6">As a key into a table for a database that 1.12500 + manages repositories on a server.</para> 1.12501 + </listitem> 1.12502 + <listitem><para id="x_5d7">As half of a {<emphasis>repository 1.12503 + ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. 1.12504 + Save this information away when you run an automated build 1.12505 + or other activity, so that you can <quote>replay</quote> 1.12506 + the build later if necessary.</para> 1.12507 + </listitem> 1.12508 + </itemizedlist> 1.12509 + </sect2> 1.12510 + 1.12511 + <sect2> 1.12512 + <title>Listing files on multiple lines</title> 1.12513 + 1.12514 + <para id="x_714">Suppose we want to list the files changed by a changeset, 1.12515 + one per line, with a little indentation before each file 1.12516 + name.</para> 1.12517 + 1.12518 + <!-- BEGIN ch10/multiline.go --> 1.12519 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > multiline << EOF</userinput> 1.12520 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">changeset = "Changed in {node|short}:\n{files}"</userinput> 1.12521 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">file = " {file}\n"</userinput> 1.12522 +<prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> 1.12523 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style multiline</userinput> 1.12524 +Changed in badb58085712: 1.12525 + .bashrc 1.12526 + .hgrc 1.12527 + test.c 1.12528 +</screen> 1.12529 +<!-- END ch10/multiline.go --> 1.12530 + 1.12531 + </sect2> 1.12532 + 1.12533 + <sect2> 1.12534 + <title>Mimicking Subversion's output</title> 1.12535 + 1.12536 + <para id="x_5d8">Let's try to emulate the default output format used by 1.12537 + another revision control tool, Subversion.</para> 1.12538 + 1.12539 + <!-- BEGIN template.svnstyle.short --> 1.12540 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svn log -r9653</userinput> 1.12541 +------------------------------------------------------------------------ 1.12542 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines 1.12543 + 1.12544 +On reporting a route error, also include the status for the error, 1.12545 +rather than indicating a status of 0 when an error has occurred. 1.12546 + 1.12547 +Signed-off-by: Sean Hefty <sean.hefty@intel.com> 1.12548 + 1.12549 +------------------------------------------------------------------------ 1.12550 +</screen> 1.12551 +<!-- END template.svnstyle.short --> 1.12552 + 1.12553 + 1.12554 + <para id="x_5d9">Since Subversion's output style is fairly simple, it is 1.12555 + easy to copy-and-paste a hunk of its output into a file, and 1.12556 + replace the text produced above by Subversion with the 1.12557 + template values we'd like to see expanded.</para> 1.12558 + 1.12559 + <!-- BEGIN template.svnstyle.template --> 1.12560 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.template</userinput> 1.12561 +r{rev} | {author|user} | {date|isodate} ({date|rfc822date}) 1.12562 + 1.12563 +{desc|strip|fill76} 1.12564 + 1.12565 +------------------------------------------------------------------------ 1.12566 +</screen> 1.12567 +<!-- END template.svnstyle.template --> 1.12568 + 1.12569 + 1.12570 + <para id="x_5da">There are a few small ways in which this template deviates 1.12571 + from the output produced by Subversion.</para> 1.12572 + <itemizedlist> 1.12573 + <listitem><para id="x_5db">Subversion prints a <quote>readable</quote> 1.12574 + date (the <quote><literal moreinfo="none">Wed, 27 Sep 2006</literal></quote> in the 1.12575 + example output above) in parentheses. Mercurial's 1.12576 + templating engine does not provide a way to display a date 1.12577 + in this format without also printing the time and time 1.12578 + zone.</para> 1.12579 + </listitem> 1.12580 + <listitem><para id="x_5dc">We emulate Subversion's printing of 1.12581 + <quote>separator</quote> lines full of 1.12582 + <quote><literal moreinfo="none">-</literal></quote> characters by ending 1.12583 + the template with such a line. We use the templating 1.12584 + engine's <literal role="template-keyword" moreinfo="none">header</literal> 1.12585 + keyword to print a separator line as the first line of 1.12586 + output (see below), thus achieving similar output to 1.12587 + Subversion.</para> 1.12588 + </listitem> 1.12589 + <listitem><para id="x_5dd">Subversion's output includes a count in the 1.12590 + header of the number of lines in the commit message. We 1.12591 + cannot replicate this in Mercurial; the templating engine 1.12592 + does not currently provide a filter that counts the number 1.12593 + of lines the template generates.</para> 1.12594 + </listitem></itemizedlist> 1.12595 + <para id="x_5de">It took me no more than a minute or two of work to replace 1.12596 + literal text from an example of Subversion's output with some 1.12597 + keywords and filters to give the template above. The style 1.12598 + file simply refers to the template.</para> 1.12599 + 1.12600 + <!-- BEGIN template.svnstyle.style --> 1.12601 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.style</userinput> 1.12602 +header = '------------------------------------------------------------------------\n\n' 1.12603 +changeset = svn.template 1.12604 +</screen> 1.12605 +<!-- END template.svnstyle.style --> 1.12606 + 1.12607 + 1.12608 + <para id="x_5df">We could have included the text of the template file 1.12609 + directly in the style file by enclosing it in quotes and 1.12610 + replacing the newlines with 1.12611 + <quote><literal moreinfo="none">\n</literal></quote> sequences, but it would 1.12612 + have made the style file too difficult to read. Readability 1.12613 + is a good guide when you're trying to decide whether some text 1.12614 + belongs in a style file, or in a template file that the style 1.12615 + file points to. If the style file will look too big or 1.12616 + cluttered if you insert a literal piece of text, drop it into 1.12617 + a template instead.</para> 1.12618 + </sect2> 1.12619 + </sect1> 1.12620 +</chapter> 1.12621 + 1.12622 +<!-- 1.12623 +local variables: 1.12624 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.12625 +end: 1.12626 +--> 1.12627 + 1.12628 + <!-- BEGIN ch12 --> 1.12629 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.12630 + 1.12631 +<chapter id="chap:mq"> 1.12632 + <?dbhtml filename="managing-change-with-mercurial-queues.html"?> 1.12633 + <title>Managing change with Mercurial Queues</title> 1.12634 + 1.12635 + <sect1 id="sec:mq:patch-mgmt"> 1.12636 + <title>The patch management problem</title> 1.12637 + 1.12638 + <para id="x_3ac">Here is a common scenario: you need to install a software 1.12639 + package from source, but you find a bug that you must fix in the 1.12640 + source before you can start using the package. You make your 1.12641 + changes, forget about the package for a while, and a few months 1.12642 + later you need to upgrade to a newer version of the package. If 1.12643 + the newer version of the package still has the bug, you must 1.12644 + extract your fix from the older source tree and apply it against 1.12645 + the newer version. This is a tedious task, and it's easy to 1.12646 + make mistakes.</para> 1.12647 + 1.12648 + <para id="x_3ad">This is a simple case of the <quote>patch management</quote> 1.12649 + problem. You have an <quote>upstream</quote> source tree that 1.12650 + you can't change; you need to make some local changes on top of 1.12651 + the upstream tree; and you'd like to be able to keep those 1.12652 + changes separate, so that you can apply them to newer versions 1.12653 + of the upstream source.</para> 1.12654 + 1.12655 + <para id="x_3ae">The patch management problem arises in many situations. 1.12656 + Probably the most visible is that a user of an open source 1.12657 + software project will contribute a bug fix or new feature to the 1.12658 + project's maintainers in the form of a patch.</para> 1.12659 + 1.12660 + <para id="x_3af">Distributors of operating systems that include open source 1.12661 + software often need to make changes to the packages they 1.12662 + distribute so that they will build properly in their 1.12663 + environments.</para> 1.12664 + 1.12665 + <para id="x_3b0">When you have few changes to maintain, it is easy to manage 1.12666 + a single patch using the standard <command moreinfo="none">diff</command> and 1.12667 + <command moreinfo="none">patch</command> programs (see <xref linkend="sec:mq:patch"/> for a discussion of these 1.12668 + tools). Once the number of changes grows, it starts to make 1.12669 + sense to maintain patches as discrete <quote>chunks of 1.12670 + work,</quote> so that for example a single patch will contain 1.12671 + only one bug fix (the patch might modify several files, but it's 1.12672 + doing <quote>only one thing</quote>), and you may have a number 1.12673 + of such patches for different bugs you need fixed and local 1.12674 + changes you require. In this situation, if you submit a bug fix 1.12675 + patch to the upstream maintainers of a package and they include 1.12676 + your fix in a subsequent release, you can simply drop that 1.12677 + single patch when you're updating to the newer release.</para> 1.12678 + 1.12679 + <para id="x_3b1">Maintaining a single patch against an upstream tree is a 1.12680 + little tedious and error-prone, but not difficult. However, the 1.12681 + complexity of the problem grows rapidly as the number of patches 1.12682 + you have to maintain increases. With more than a tiny number of 1.12683 + patches in hand, understanding which ones you have applied and 1.12684 + maintaining them moves from messy to overwhelming.</para> 1.12685 + 1.12686 + <para id="x_3b2">Fortunately, Mercurial includes a powerful extension, 1.12687 + Mercurial Queues (or simply <quote>MQ</quote>), that massively 1.12688 + simplifies the patch management problem.</para> 1.12689 + 1.12690 + </sect1> 1.12691 + <sect1 id="sec:mq:history"> 1.12692 + <title>The prehistory of Mercurial Queues</title> 1.12693 + 1.12694 + <para id="x_3b3">During the late 1990s, several Linux kernel developers 1.12695 + started to maintain <quote>patch series</quote> that modified 1.12696 + the behavior of the Linux kernel. Some of these series were 1.12697 + focused on stability, some on feature coverage, and others were 1.12698 + more speculative.</para> 1.12699 + 1.12700 + <para id="x_3b4">The sizes of these patch series grew rapidly. In 2002, 1.12701 + Andrew Morton published some shell scripts he had been using to 1.12702 + automate the task of managing his patch queues. Andrew was 1.12703 + successfully using these scripts to manage hundreds (sometimes 1.12704 + thousands) of patches on top of the Linux kernel.</para> 1.12705 + 1.12706 + <sect2 id="sec:mq:quilt"> 1.12707 + <title>A patchwork quilt</title> 1.12708 + 1.12709 + <para id="x_3b5">In early 2003, Andreas Gruenbacher and Martin Quinson 1.12710 + borrowed the approach of Andrew's scripts and published a tool 1.12711 + called <quote>patchwork quilt</quote> 1.12712 + <citation>web:quilt</citation>, or simply <quote>quilt</quote> 1.12713 + (see <citation>gruenbacher:2005</citation> for a paper 1.12714 + describing it). Because quilt substantially automated patch 1.12715 + management, it rapidly gained a large following among open 1.12716 + source software developers.</para> 1.12717 + 1.12718 + <para id="x_3b6">Quilt manages a <emphasis>stack of patches</emphasis> on 1.12719 + top of a directory tree. To begin, you tell quilt to manage a 1.12720 + directory tree, and tell it which files you want to manage; it 1.12721 + stores away the names and contents of those files. To fix a 1.12722 + bug, you create a new patch (using a single command), edit the 1.12723 + files you need to fix, then <quote>refresh</quote> the 1.12724 + patch.</para> 1.12725 + 1.12726 + <para id="x_3b7">The refresh step causes quilt to scan the directory tree; 1.12727 + it updates the patch with all of the changes you have made. 1.12728 + You can create another patch on top of the first, which will 1.12729 + track the changes required to modify the tree from <quote>tree 1.12730 + with one patch applied</quote> to <quote>tree with two 1.12731 + patches applied</quote>.</para> 1.12732 + 1.12733 + <para id="x_3b8">You can <emphasis>change</emphasis> which patches are 1.12734 + applied to the tree. If you <quote>pop</quote> a patch, the 1.12735 + changes made by that patch will vanish from the directory 1.12736 + tree. Quilt remembers which patches you have popped, though, 1.12737 + so you can <quote>push</quote> a popped patch again, and the 1.12738 + directory tree will be restored to contain the modifications 1.12739 + in the patch. Most importantly, you can run the 1.12740 + <quote>refresh</quote> command at any time, and the topmost 1.12741 + applied patch will be updated. This means that you can, at 1.12742 + any time, change both which patches are applied and what 1.12743 + modifications those patches make.</para> 1.12744 + 1.12745 + <para id="x_3b9">Quilt knows nothing about revision control tools, so it 1.12746 + works equally well on top of an unpacked tarball or a 1.12747 + Subversion working copy.</para> 1.12748 + </sect2> 1.12749 + 1.12750 + <sect2 id="sec:mq:quilt-mq"> 1.12751 + <title>From patchwork quilt to Mercurial Queues</title> 1.12752 + 1.12753 + <para id="x_3ba">In mid-2005, Chris Mason took the features of quilt and 1.12754 + wrote an extension that he called Mercurial Queues, which 1.12755 + added quilt-like behavior to Mercurial.</para> 1.12756 + 1.12757 + <para id="x_3bb">The key difference between quilt and MQ is that quilt 1.12758 + knows nothing about revision control systems, while MQ is 1.12759 + <emphasis>integrated</emphasis> into Mercurial. Each patch 1.12760 + that you push is represented as a Mercurial changeset. Pop a 1.12761 + patch, and the changeset goes away.</para> 1.12762 + 1.12763 + <para id="x_3bc">Because quilt does not care about revision control tools, 1.12764 + it is still a tremendously useful piece of software to know 1.12765 + about for situations where you cannot use Mercurial and 1.12766 + MQ.</para> 1.12767 + 1.12768 + </sect2> 1.12769 + </sect1> 1.12770 + <sect1> 1.12771 + <title>The huge advantage of MQ</title> 1.12772 + 1.12773 + <para id="x_3bd">I cannot overstate the value that MQ offers through the 1.12774 + unification of patches and revision control.</para> 1.12775 + 1.12776 + <para id="x_3be">A major reason that patches have persisted in the free 1.12777 + software and open source world—in spite of the 1.12778 + availability of increasingly capable revision control tools over 1.12779 + the years—is the <emphasis>agility</emphasis> they 1.12780 + offer.</para> 1.12781 + 1.12782 + <para id="x_3bf">Traditional revision control tools make a permanent, 1.12783 + irreversible record of everything that you do. While this has 1.12784 + great value, it's also somewhat stifling. If you want to 1.12785 + perform a wild-eyed experiment, you have to be careful in how 1.12786 + you go about it, or you risk leaving unneeded—or worse, 1.12787 + misleading or destabilising—traces of your missteps and 1.12788 + errors in the permanent revision record.</para> 1.12789 + 1.12790 + <para id="x_3c0">By contrast, MQ's marriage of distributed revision control 1.12791 + with patches makes it much easier to isolate your work. Your 1.12792 + patches live on top of normal revision history, and you can make 1.12793 + them disappear or reappear at will. If you don't like a patch, 1.12794 + you can drop it. If a patch isn't quite as you want it to be, 1.12795 + simply fix it—as many times as you need to, until you 1.12796 + have refined it into the form you desire.</para> 1.12797 + 1.12798 + <para id="x_3c1">As an example, the integration of patches with revision 1.12799 + control makes understanding patches and debugging their 1.12800 + effects—and their interplay with the code they're based 1.12801 + on—<emphasis>enormously</emphasis> easier. Since every 1.12802 + applied patch has an associated changeset, you can give <command role="hg-cmd" moreinfo="none">hg log</command> a file name to see which 1.12803 + changesets and patches affected the file. You can use the 1.12804 + <command role="hg-cmd" moreinfo="none">hg bisect</command> command to 1.12805 + binary-search through all changesets and applied patches to see 1.12806 + where a bug got introduced or fixed. You can use the <command role="hg-cmd" moreinfo="none">hg annotate</command> command to see which 1.12807 + changeset or patch modified a particular line of a source file. 1.12808 + And so on.</para> 1.12809 + </sect1> 1.12810 + 1.12811 + <sect1 id="sec:mq:patch"> 1.12812 + <title>Understanding patches</title> 1.12813 + 1.12814 + <para id="x_3c2">Because MQ doesn't hide its patch-oriented nature, it is 1.12815 + helpful to understand what patches are, and a little about the 1.12816 + tools that work with them.</para> 1.12817 + 1.12818 + <para id="x_3c3">The traditional Unix <command moreinfo="none">diff</command> command 1.12819 + compares two files, and prints a list of differences between 1.12820 + them. The <command moreinfo="none">patch</command> command understands these 1.12821 + differences as <emphasis>modifications</emphasis> to make to a 1.12822 + file. Take a look below for a simple example of these commands 1.12823 + in action.</para> 1.12824 + 1.12825 + <!-- BEGIN mq.dodiff.diff --> 1.12826 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'this is my original thought' > oldfile</userinput> 1.12827 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'i have changed my mind' > newfile</userinput> 1.12828 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diff -u oldfile newfile > tiny.patch</userinput> 1.12829 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat tiny.patch</userinput> 1.12830 +--- oldfile 2009-08-16 14:05:06.000000000 +0000 1.12831 ++++ newfile 2009-08-16 14:05:06.000000000 +0000 1.12832 +@@ -1 +1 @@ 1.12833 +-this is my original thought 1.12834 ++i have changed my mind 1.12835 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">patch < tiny.patch</userinput> 1.12836 +patching file oldfile 1.12837 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat oldfile</userinput> 1.12838 +i have changed my mind 1.12839 +</screen> 1.12840 +<!-- END mq.dodiff.diff --> 1.12841 + 1.12842 + 1.12843 + <para id="x_3c4">The type of file that <command moreinfo="none">diff</command> generates (and 1.12844 + <command moreinfo="none">patch</command> takes as input) is called a 1.12845 + <quote>patch</quote> or a <quote>diff</quote>; there is no 1.12846 + difference between a patch and a diff. (We'll use the term 1.12847 + <quote>patch</quote>, since it's more commonly used.)</para> 1.12848 + 1.12849 + <para id="x_3c5">A patch file can start with arbitrary text; the 1.12850 + <command moreinfo="none">patch</command> command ignores this text, but MQ uses 1.12851 + it as the commit message when creating changesets. To find the 1.12852 + beginning of the patch content, <command moreinfo="none">patch</command> 1.12853 + searches for the first line that starts with the string 1.12854 + <quote><literal moreinfo="none">diff -</literal></quote>.</para> 1.12855 + 1.12856 + <para id="x_3c6">MQ works with <emphasis>unified</emphasis> diffs 1.12857 + (<command moreinfo="none">patch</command> can accept several other diff formats, 1.12858 + but MQ doesn't). A unified diff contains two kinds of header. 1.12859 + The <emphasis>file header</emphasis> describes the file being 1.12860 + modified; it contains the name of the file to modify. When 1.12861 + <command moreinfo="none">patch</command> sees a new file header, it looks for a 1.12862 + file with that name to start modifying.</para> 1.12863 + 1.12864 + <para id="x_3c7">After the file header comes a series of 1.12865 + <emphasis>hunks</emphasis>. Each hunk starts with a header; 1.12866 + this identifies the range of line numbers within the file that 1.12867 + the hunk should modify. Following the header, a hunk starts and 1.12868 + ends with a few (usually three) lines of text from the 1.12869 + unmodified file; these are called the 1.12870 + <emphasis>context</emphasis> for the hunk. If there's only a 1.12871 + small amount of context between successive hunks, 1.12872 + <command moreinfo="none">diff</command> doesn't print a new hunk header; it just 1.12873 + runs the hunks together, with a few lines of context between 1.12874 + modifications.</para> 1.12875 + 1.12876 + <para id="x_3c8">Each line of context begins with a space character. Within 1.12877 + the hunk, a line that begins with 1.12878 + <quote><literal moreinfo="none">-</literal></quote> means <quote>remove this 1.12879 + line,</quote> while a line that begins with 1.12880 + <quote><literal moreinfo="none">+</literal></quote> means <quote>insert this 1.12881 + line.</quote> For example, a line that is modified is 1.12882 + represented by one deletion and one insertion.</para> 1.12883 + 1.12884 + <para id="x_3c9">We will return to some of the more subtle aspects of patches 1.12885 + later (in <xref linkend="sec:mq:adv-patch"/>), but you 1.12886 + should have 1.12887 + enough information now to use MQ.</para> 1.12888 + </sect1> 1.12889 + 1.12890 + <sect1 id="sec:mq:start"> 1.12891 + <title>Getting started with Mercurial Queues</title> 1.12892 + 1.12893 + <para id="x_3ca">Because MQ is implemented as an extension, you must 1.12894 + explicitly enable before you can use it. (You don't need to 1.12895 + download anything; MQ ships with the standard Mercurial 1.12896 + distribution.) To enable MQ, edit your <filename role="home" moreinfo="none">~/.hgrc</filename> file, and add the lines 1.12897 + below.</para> 1.12898 + 1.12899 + <programlisting format="linespecific">[extensions] 1.12900 +hgext.mq =</programlisting> 1.12901 + 1.12902 + <para id="x_3cb">Once the extension is enabled, it will make a number of new 1.12903 + commands available. To verify that the extension is working, 1.12904 + you can use <command role="hg-cmd" moreinfo="none">hg help</command> to see if 1.12905 + the <command role="hg-ext-mq" moreinfo="none">qinit</command> command is now 1.12906 + available.</para> 1.12907 + 1.12908 + <!-- BEGIN mq.qinit-help.help --> 1.12909 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help qinit</userinput> 1.12910 +hg qinit [-c] 1.12911 + 1.12912 +init a new queue repository 1.12913 + 1.12914 + The queue repository is unversioned by default. If -c is 1.12915 + specified, qinit will create a separate nested repository 1.12916 + for patches (qinit -c may also be run later to convert 1.12917 + an unversioned patch repository into a versioned one). 1.12918 + You can use qcommit to commit changes to this queue repository. 1.12919 + 1.12920 +options: 1.12921 + 1.12922 + -c --create-repo create queue repository 1.12923 + 1.12924 +use "hg -v help qinit" to show global options 1.12925 +</screen> 1.12926 +<!-- END mq.qinit-help.help --> 1.12927 + 1.12928 + 1.12929 + <para id="x_3cc">You can use MQ with <emphasis>any</emphasis> Mercurial 1.12930 + repository, and its commands only operate within that 1.12931 + repository. To get started, simply prepare the repository using 1.12932 + the <command role="hg-ext-mq" moreinfo="none">qinit</command> command.</para> 1.12933 + 1.12934 + <!-- BEGIN mq.tutorial.qinit --> 1.12935 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mq-sandbox</userinput> 1.12936 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mq-sandbox</userinput> 1.12937 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 1' > file1</userinput> 1.12938 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'another line 1' > file2</userinput> 1.12939 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file1 file2</userinput> 1.12940 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m'first change'</userinput> 1.12941 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> 1.12942 +</screen> 1.12943 +<!-- END mq.tutorial.qinit --> 1.12944 + 1.12945 + 1.12946 + <para id="x_3cd">This command creates an empty directory called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>, where 1.12947 + MQ will keep its metadata. As with many Mercurial commands, the 1.12948 + <command role="hg-ext-mq" moreinfo="none">qinit</command> command prints nothing 1.12949 + if it succeeds.</para> 1.12950 + 1.12951 + <sect2> 1.12952 + <title>Creating a new patch</title> 1.12953 + 1.12954 + <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 1.12955 + one argument, the name of the patch to create.</para> 1.12956 + 1.12957 + <para id="x_3cf">MQ will use this as the name of an actual file in the 1.12958 + <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory, as you 1.12959 + can see below.</para> 1.12960 + 1.12961 + <!-- BEGIN mq.tutorial.qnew --> 1.12962 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.12963 +changeset: 0:5d84c303994b 1.12964 +tag: tip 1.12965 +user: Bryan O'Sullivan <bos@serpentine.com> 1.12966 +date: Sun Aug 16 14:05:11 2009 +0000 1.12967 +summary: first change 1.12968 + 1.12969 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew first.patch</userinput> 1.12970 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> 1.12971 +changeset: 1:ba4d7a3f2149 1.12972 +tag: qtip 1.12973 +tag: first.patch 1.12974 +tag: tip 1.12975 +tag: qbase 1.12976 +user: Bryan O'Sullivan <bos@serpentine.com> 1.12977 +date: Sun Aug 16 14:05:11 2009 +0000 1.12978 +summary: [mq]: first.patch 1.12979 + 1.12980 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls .hg/patches</userinput> 1.12981 +first.patch series status 1.12982 +</screen> 1.12983 +<!-- END mq.tutorial.qnew --> 1.12984 + 1.12985 + 1.12986 + <para id="x_3d0">Also newly present in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory are two 1.12987 + other files, <filename role="special" moreinfo="none">series</filename> and 1.12988 + <filename role="special" moreinfo="none">status</filename>. The <filename role="special" moreinfo="none">series</filename> file lists all of the 1.12989 + patches that MQ knows about for this repository, with one 1.12990 + patch per line. Mercurial uses the <filename role="special" moreinfo="none">status</filename> file for internal 1.12991 + book-keeping; it tracks all of the patches that MQ has 1.12992 + <emphasis>applied</emphasis> in this repository.</para> 1.12993 + 1.12994 + <note> 1.12995 + <para id="x_3d1"> You may sometimes want to edit the <filename role="special" moreinfo="none">series</filename> file by hand; for 1.12996 + example, to change the sequence in which some patches are 1.12997 + applied. However, manually editing the <filename role="special" moreinfo="none">status</filename> file is almost always a 1.12998 + bad idea, as it's easy to corrupt MQ's idea of what is 1.12999 + happening.</para> 1.13000 + </note> 1.13001 + 1.13002 + <para id="x_3d2">Once you have created your new patch, you can edit files 1.13003 + in the working directory as you usually would. All of the 1.13004 + normal Mercurial commands, such as <command role="hg-cmd" moreinfo="none">hg 1.13005 + diff</command> and <command role="hg-cmd" moreinfo="none">hg 1.13006 + annotate</command>, work exactly as they did before.</para> 1.13007 + </sect2> 1.13008 + 1.13009 + <sect2> 1.13010 + <title>Refreshing a patch</title> 1.13011 + 1.13012 + <para id="x_3d3">When you reach a point where you want to save your work, 1.13013 + use the <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command 1.13014 + to update the patch you are working on.</para> 1.13015 + 1.13016 + <!-- BEGIN mq.tutorial.qrefresh --> 1.13017 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 2' >> file1</userinput> 1.13018 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> 1.13019 +diff -r ba4d7a3f2149 file1 1.13020 +--- a/file1 Sun Aug 16 14:05:11 2009 +0000 1.13021 ++++ b/file1 Sun Aug 16 14:05:11 2009 +0000 1.13022 +@@ -1,1 +1,2 @@ 1.13023 + line 1 1.13024 ++line 2 1.13025 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.13026 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> 1.13027 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput> 1.13028 +1[qtip,first.patch,tip,qbase] 1aa236e17e55 2009-08-16 14:05 +0000 bos 1.13029 + [mq]: first.patch 1.13030 + 1.13031 +diff -r 5d84c303994b -r 1aa236e17e55 file1 1.13032 +--- a/file1 Sun Aug 16 14:05:11 2009 +0000 1.13033 ++++ b/file1 Sun Aug 16 14:05:11 2009 +0000 1.13034 +@@ -1,1 +1,2 @@ 1.13035 + line 1 1.13036 ++line 2 1.13037 + 1.13038 +</screen> 1.13039 +<!-- END mq.tutorial.qrefresh --> 1.13040 + 1.13041 + 1.13042 + <para id="x_3d4">This command folds the changes you have made in the 1.13043 + working directory into your patch, and updates its 1.13044 + corresponding changeset to contain those changes.</para> 1.13045 + 1.13046 + <para id="x_3d5">You can run <command role="hg-ext-mq" moreinfo="none">qrefresh</command> 1.13047 + as often as you like, so it's a good way to 1.13048 + <quote>checkpoint</quote> your work. Refresh your patch at an 1.13049 + opportune time; try an experiment; and if the experiment 1.13050 + doesn't work out, <command role="hg-cmd" moreinfo="none">hg revert</command> 1.13051 + your modifications back to the last time you refreshed.</para> 1.13052 + 1.13053 + <!-- BEGIN mq.tutorial.qrefresh2 --> 1.13054 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 3' >> file1</userinput> 1.13055 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> 1.13056 +M file1 1.13057 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.13058 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput> 1.13059 +1[qtip,first.patch,tip,qbase] ebec7ce95e11 2009-08-16 14:05 +0000 bos 1.13060 + [mq]: first.patch 1.13061 + 1.13062 +diff -r 5d84c303994b -r ebec7ce95e11 file1 1.13063 +--- a/file1 Sun Aug 16 14:05:11 2009 +0000 1.13064 ++++ b/file1 Sun Aug 16 14:05:12 2009 +0000 1.13065 +@@ -1,1 +1,3 @@ 1.13066 + line 1 1.13067 ++line 2 1.13068 ++line 3 1.13069 + 1.13070 +</screen> 1.13071 +<!-- END mq.tutorial.qrefresh2 --> 1.13072 + 1.13073 + </sect2> 1.13074 + 1.13075 + <sect2> 1.13076 + <title>Stacking and tracking patches</title> 1.13077 + 1.13078 + <para id="x_3d6">Once you have finished working on a patch, or need to work 1.13079 + on another, you can use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command again to create a 1.13080 + new patch. Mercurial will apply this patch on top of your 1.13081 + existing patch.</para> 1.13082 + 1.13083 + <!-- BEGIN mq.tutorial.qnew2 --> 1.13084 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew second.patch</userinput> 1.13085 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style=compact --limit=2</userinput> 1.13086 +2[qtip,second.patch,tip] dffbc4265523 2009-08-16 14:05 +0000 bos 1.13087 + [mq]: second.patch 1.13088 + 1.13089 +1[first.patch,qbase] ebec7ce95e11 2009-08-16 14:05 +0000 bos 1.13090 + [mq]: first.patch 1.13091 + 1.13092 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 4' >> file1</userinput> 1.13093 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.13094 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput> 1.13095 +2[qtip,second.patch,tip] fdacb9b232ac 2009-08-16 14:05 +0000 bos 1.13096 + [mq]: second.patch 1.13097 + 1.13098 +diff -r ebec7ce95e11 -r fdacb9b232ac file1 1.13099 +--- a/file1 Sun Aug 16 14:05:12 2009 +0000 1.13100 ++++ b/file1 Sun Aug 16 14:05:12 2009 +0000 1.13101 +@@ -1,3 +1,4 @@ 1.13102 + line 1 1.13103 + line 2 1.13104 + line 3 1.13105 ++line 4 1.13106 + 1.13107 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg annotate file1</userinput> 1.13108 +0: line 1 1.13109 +1: line 2 1.13110 +1: line 3 1.13111 +2: line 4 1.13112 +</screen> 1.13113 +<!-- END mq.tutorial.qnew2 --> 1.13114 + 1.13115 + 1.13116 + <para id="x_3d7">Notice that the patch contains the changes in our prior 1.13117 + patch as part of its context (you can see this more clearly in 1.13118 + the output of <command role="hg-cmd" moreinfo="none">hg 1.13119 + annotate</command>).</para> 1.13120 + 1.13121 + <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 1.13122 + only use regular Mercurial commands. However, MQ provides 1.13123 + many commands that are easier to use when you are thinking 1.13124 + about patches, as illustrated below.</para> 1.13125 + 1.13126 + <!-- BEGIN mq.tutorial.qseries --> 1.13127 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput> 1.13128 +first.patch 1.13129 +second.patch 1.13130 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> 1.13131 +first.patch 1.13132 +second.patch 1.13133 +</screen> 1.13134 +<!-- END mq.tutorial.qseries --> 1.13135 + 1.13136 + 1.13137 + <itemizedlist> 1.13138 + <listitem><para id="x_3d9">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command lists every 1.13139 + patch that MQ knows about in this repository, from oldest 1.13140 + to newest (most recently 1.13141 + <emphasis>created</emphasis>).</para> 1.13142 + </listitem> 1.13143 + <listitem><para id="x_3da">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command lists every 1.13144 + patch that MQ has <emphasis>applied</emphasis> in this 1.13145 + repository, again from oldest to newest (most recently 1.13146 + applied).</para> 1.13147 + </listitem></itemizedlist> 1.13148 + </sect2> 1.13149 + 1.13150 + <sect2> 1.13151 + <title>Manipulating the patch stack</title> 1.13152 + 1.13153 + <para id="x_3db">The previous discussion implied that there must be a 1.13154 + difference between <quote>known</quote> and 1.13155 + <quote>applied</quote> patches, and there is. MQ can manage a 1.13156 + patch without it being applied in the repository.</para> 1.13157 + 1.13158 + <para id="x_3dc">An <emphasis>applied</emphasis> patch has a corresponding 1.13159 + changeset in the repository, and the effects of the patch and 1.13160 + changeset are visible in the working directory. You can undo 1.13161 + the application of a patch using the <command role="hg-ext-mq" moreinfo="none">qpop</command> command. MQ still 1.13162 + <emphasis>knows about</emphasis>, or manages, a popped patch, 1.13163 + but the patch no longer has a corresponding changeset in the 1.13164 + repository, and the working directory does not contain the 1.13165 + changes made by the patch. <xref linkend="fig:mq:stack"/> illustrates 1.13166 + the difference between applied and tracked patches.</para> 1.13167 + 1.13168 + <figure id="fig:mq:stack" float="0"> 1.13169 + <title>Applied and unapplied patches in the MQ patch 1.13170 + stack</title> 1.13171 + <mediaobject> 1.13172 + <imageobject><imagedata fileref="figs/mq-stack.png"/></imageobject> 1.13173 + <textobject><phrase>XXX add text</phrase></textobject> 1.13174 + </mediaobject> 1.13175 + </figure> 1.13176 + 1.13177 + <para id="x_3de">You can reapply an unapplied, or popped, patch using the 1.13178 + <command role="hg-ext-mq" moreinfo="none">qpush</command> command. This 1.13179 + creates a new changeset to correspond to the patch, and the 1.13180 + patch's changes once again become present in the working 1.13181 + 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> 1.13182 + 1.13183 + <!-- BEGIN mq.tutorial.qpop --> 1.13184 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> 1.13185 +first.patch 1.13186 +second.patch 1.13187 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput> 1.13188 +now at: first.patch 1.13189 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput> 1.13190 +first.patch 1.13191 +second.patch 1.13192 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> 1.13193 +first.patch 1.13194 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput> 1.13195 +line 1 1.13196 +line 2 1.13197 +line 3 1.13198 +</screen> 1.13199 +<!-- END mq.tutorial.qpop --> 1.13200 + 1.13201 + 1.13202 + <para id="x_3df">Notice that once we have popped a patch or two patches, 1.13203 + the output of <command role="hg-ext-mq" moreinfo="none">qseries</command> 1.13204 + remains the same, while that of <command role="hg-ext-mq" moreinfo="none">qapplied</command> has changed.</para> 1.13205 + 1.13206 + </sect2> 1.13207 + 1.13208 + <sect2> 1.13209 + <title>Pushing and popping many patches</title> 1.13210 + 1.13211 + <para id="x_3e0">While <command role="hg-ext-mq" moreinfo="none">qpush</command> and 1.13212 + <command role="hg-ext-mq" moreinfo="none">qpop</command> each operate on a 1.13213 + single patch at a time by default, you can push and pop many 1.13214 + patches in one go. The <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to 1.13215 + <command role="hg-ext-mq" moreinfo="none">qpush</command> causes it to push 1.13216 + 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 1.13217 + patches. (For some more ways to push and pop many patches, 1.13218 + see <xref linkend="sec:mq:perf"/> below.)</para> 1.13219 + 1.13220 + <!-- BEGIN mq.tutorial.qpush-a --> 1.13221 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> 1.13222 +applying second.patch 1.13223 +now at: second.patch 1.13224 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput> 1.13225 +line 1 1.13226 +line 2 1.13227 +line 3 1.13228 +line 4 1.13229 +</screen> 1.13230 +<!-- END mq.tutorial.qpush-a --> 1.13231 + 1.13232 + </sect2> 1.13233 + 1.13234 + <sect2> 1.13235 + <title>Safety checks, and overriding them</title> 1.13236 + 1.13237 + <para id="x_3e1">Several MQ commands check the working directory before 1.13238 + they do anything, and fail if they find any modifications. 1.13239 + They do this to ensure that you won't lose any changes that 1.13240 + you have made, but not yet incorporated into a patch. The 1.13241 + example below illustrates this; the <command role="hg-ext-mq" moreinfo="none">qnew</command> command will not create a 1.13242 + new patch if there are outstanding changes, caused in this 1.13243 + case by the <command role="hg-cmd" moreinfo="none">hg add</command> of 1.13244 + <filename moreinfo="none">file3</filename>.</para> 1.13245 + 1.13246 + <!-- BEGIN mq.tutorial.add --> 1.13247 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'file 3, line 1' >> file3</userinput> 1.13248 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew add-file3.patch</userinput> 1.13249 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -f add-file3.patch</userinput> 1.13250 +abort: patch "add-file3.patch" already exists 1.13251 +</screen> 1.13252 +<!-- END mq.tutorial.add --> 1.13253 + 1.13254 + 1.13255 + <para id="x_3e2">Commands that check the working directory all take an 1.13256 + <quote>I know what I'm doing</quote> option, which is always 1.13257 + named <option>-f</option>. The exact meaning of 1.13258 + <option>-f</option> depends on the command. For example, 1.13259 + <command role="hg-cmd" moreinfo="none">hg qnew <option role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command> 1.13260 + will incorporate any outstanding changes into the new patch it 1.13261 + creates, but <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command> 1.13262 + will revert modifications to any files affected by the patch 1.13263 + that it is popping. Be sure to read the documentation for a 1.13264 + command's <option>-f</option> option before you use it!</para> 1.13265 + </sect2> 1.13266 + 1.13267 + <sect2> 1.13268 + <title>Working on several patches at once</title> 1.13269 + 1.13270 + <para id="x_3e3">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command 1.13271 + always refreshes the <emphasis>topmost</emphasis> applied 1.13272 + patch. This means that you can suspend work on one patch (by 1.13273 + refreshing it), pop or push to make a different patch the top, 1.13274 + and work on <emphasis>that</emphasis> patch for a 1.13275 + while.</para> 1.13276 + 1.13277 + <para id="x_3e4">Here's an example that illustrates how you can use this 1.13278 + ability. Let's say you're developing a new feature as two 1.13279 + patches. The first is a change to the core of your software, 1.13280 + and the second—layered on top of the 1.13281 + first—changes the user interface to use the code you 1.13282 + just added to the core. If you notice a bug in the core while 1.13283 + you're working on the UI patch, it's easy to fix the core. 1.13284 + Simply <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the UI 1.13285 + patch to save your in-progress changes, and <command role="hg-ext-mq" moreinfo="none">qpop</command> down to the core patch. Fix 1.13286 + the core bug, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the 1.13287 + core patch, and <command role="hg-ext-mq" moreinfo="none">qpush</command> back 1.13288 + to the UI patch to continue where you left off.</para> 1.13289 + </sect2> 1.13290 + </sect1> 1.13291 + 1.13292 + <sect1 id="sec:mq:adv-patch"> 1.13293 + <title>More about patches</title> 1.13294 + 1.13295 + <para id="x_3e5">MQ uses the GNU <command moreinfo="none">patch</command> command to apply 1.13296 + patches, so it's helpful to know a few more detailed aspects of 1.13297 + how <command moreinfo="none">patch</command> works, and about patches 1.13298 + themselves.</para> 1.13299 + 1.13300 + <sect2> 1.13301 + <title>The strip count</title> 1.13302 + 1.13303 + <para id="x_3e6">If you look at the file headers in a patch, you will 1.13304 + notice that the pathnames usually have an extra component on 1.13305 + the front that isn't present in the actual path name. This is 1.13306 + a holdover from the way that people used to generate patches 1.13307 + (people still do this, but it's somewhat rare with modern 1.13308 + revision control tools).</para> 1.13309 + 1.13310 + <para id="x_3e7">Alice would unpack a tarball, edit her files, then decide 1.13311 + that she wanted to create a patch. So she'd rename her 1.13312 + working directory, unpack the tarball again (hence the need 1.13313 + for the rename), and use the <option role="cmd-opt-diff">-r</option> and <option role="cmd-opt-diff">-N</option> options to 1.13314 + <command moreinfo="none">diff</command> to recursively generate a patch 1.13315 + between the unmodified directory and the modified one. The 1.13316 + result would be that the name of the unmodified directory 1.13317 + would be at the front of the left-hand path in every file 1.13318 + header, and the name of the modified directory would be at the 1.13319 + front of the right-hand path.</para> 1.13320 + 1.13321 + <para id="x_3e8">Since someone receiving a patch from the Alices of the net 1.13322 + would be unlikely to have unmodified and modified directories 1.13323 + with exactly the same names, the <command moreinfo="none">patch</command> 1.13324 + command has a <option role="cmd-opt-patch">-p</option> option 1.13325 + that indicates the number of leading path name components to 1.13326 + strip when trying to apply a patch. This number is called the 1.13327 + <emphasis>strip count</emphasis>.</para> 1.13328 + 1.13329 + <para id="x_3e9">An option of <quote><literal moreinfo="none">-p1</literal></quote> means 1.13330 + <quote>use a strip count of one</quote>. If 1.13331 + <command moreinfo="none">patch</command> sees a file name 1.13332 + <filename moreinfo="none">foo/bar/baz</filename> in a file header, it will 1.13333 + strip <filename moreinfo="none">foo</filename> and try to patch a file named 1.13334 + <filename moreinfo="none">bar/baz</filename>. (Strictly speaking, the strip 1.13335 + count refers to the number of <emphasis>path 1.13336 + separators</emphasis> (and the components that go with them 1.13337 + ) to strip. A strip count of one will turn 1.13338 + <filename moreinfo="none">foo/bar</filename> into <filename moreinfo="none">bar</filename>, 1.13339 + but <filename moreinfo="none">/foo/bar</filename> (notice the extra leading 1.13340 + slash) into <filename moreinfo="none">foo/bar</filename>.)</para> 1.13341 + 1.13342 + <para id="x_3ea">The <quote>standard</quote> strip count for patches is 1.13343 + one; almost all patches contain one leading path name 1.13344 + component that needs to be stripped. Mercurial's <command role="hg-cmd" moreinfo="none">hg diff</command> command generates path names 1.13345 + in this form, and the <command role="hg-cmd" moreinfo="none">hg 1.13346 + import</command> command and MQ expect patches to have a 1.13347 + strip count of one.</para> 1.13348 + 1.13349 + <para id="x_3eb">If you receive a patch from someone that you want to add 1.13350 + to your patch queue, and the patch needs a strip count other 1.13351 + than one, you cannot just <command role="hg-ext-mq" moreinfo="none">qimport</command> the patch, because 1.13352 + <command role="hg-ext-mq" moreinfo="none">qimport</command> does not yet have 1.13353 + a <literal moreinfo="none">-p</literal> option (see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue 1.13354 + 311</ulink>). Your best bet is to <command role="hg-ext-mq" moreinfo="none">qnew</command> a patch of your own, then 1.13355 + use <command moreinfo="none">patch -pN</command> to apply their patch, 1.13356 + followed by <command role="hg-cmd" moreinfo="none">hg addremove</command> to 1.13357 + pick up any files added or removed by the patch, followed by 1.13358 + <command role="hg-ext-mq" moreinfo="none">hg qrefresh</command>. This 1.13359 + complexity may become unnecessary; see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue 1.13360 + 311</ulink> for details. 1.13361 + </para> 1.13362 + </sect2> 1.13363 + 1.13364 + <sect2> 1.13365 + <title>Strategies for applying a patch</title> 1.13366 + 1.13367 + <para id="x_3ec">When <command moreinfo="none">patch</command> applies a hunk, it tries a 1.13368 + handful of successively less accurate strategies to try to 1.13369 + make the hunk apply. This falling-back technique often makes 1.13370 + it possible to take a patch that was generated against an old 1.13371 + version of a file, and apply it against a newer version of 1.13372 + that file.</para> 1.13373 + 1.13374 + <para id="x_3ed">First, <command moreinfo="none">patch</command> tries an exact match, 1.13375 + where the line numbers, the context, and the text to be 1.13376 + modified must apply exactly. If it cannot make an exact 1.13377 + match, it tries to find an exact match for the context, 1.13378 + without honouring the line numbering information. If this 1.13379 + succeeds, it prints a line of output saying that the hunk was 1.13380 + applied, but at some <emphasis>offset</emphasis> from the 1.13381 + original line number.</para> 1.13382 + 1.13383 + <para id="x_3ee">If a context-only match fails, <command moreinfo="none">patch</command> 1.13384 + removes the first and last lines of the context, and tries a 1.13385 + <emphasis>reduced</emphasis> context-only match. If the hunk 1.13386 + with reduced context succeeds, it prints a message saying that 1.13387 + it applied the hunk with a <emphasis>fuzz factor</emphasis> 1.13388 + (the number after the fuzz factor indicates how many lines of 1.13389 + context <command moreinfo="none">patch</command> had to trim before the patch 1.13390 + applied).</para> 1.13391 + 1.13392 + <para id="x_3ef">When neither of these techniques works, 1.13393 + <command moreinfo="none">patch</command> prints a message saying that the hunk 1.13394 + in question was rejected. It saves rejected hunks (also 1.13395 + simply called <quote>rejects</quote>) to a file with the same 1.13396 + name, and an added <filename role="special" moreinfo="none">.rej</filename> 1.13397 + extension. It also saves an unmodified copy of the file with 1.13398 + a <filename role="special" moreinfo="none">.orig</filename> extension; the 1.13399 + copy of the file without any extensions will contain any 1.13400 + changes made by hunks that <emphasis>did</emphasis> apply 1.13401 + cleanly. If you have a patch that modifies 1.13402 + <filename moreinfo="none">foo</filename> with six hunks, and one of them fails 1.13403 + to apply, you will have: an unmodified 1.13404 + <filename moreinfo="none">foo.orig</filename>, a <filename moreinfo="none">foo.rej</filename> 1.13405 + containing one hunk, and <filename moreinfo="none">foo</filename>, containing 1.13406 + the changes made by the five successful hunks.</para> 1.13407 + </sect2> 1.13408 + 1.13409 + <sect2> 1.13410 + <title>Some quirks of patch representation</title> 1.13411 + 1.13412 + <para id="x_3f0">There are a few useful things to know about how 1.13413 + <command moreinfo="none">patch</command> works with files.</para> 1.13414 + <itemizedlist> 1.13415 + <listitem><para id="x_3f1">This should already be obvious, but 1.13416 + <command moreinfo="none">patch</command> cannot handle binary 1.13417 + files.</para> 1.13418 + </listitem> 1.13419 + <listitem><para id="x_3f2">Neither does it care about the executable bit; 1.13420 + it creates new files as readable, but not 1.13421 + executable.</para> 1.13422 + </listitem> 1.13423 + <listitem><para id="x_3f3"><command moreinfo="none">patch</command> treats the removal of 1.13424 + a file as a diff between the file to be removed and the 1.13425 + empty file. So your idea of <quote>I deleted this 1.13426 + file</quote> looks like <quote>every line of this file 1.13427 + was deleted</quote> in a patch.</para> 1.13428 + </listitem> 1.13429 + <listitem><para id="x_3f4">It treats the addition of a file as a diff 1.13430 + between the empty file and the file to be added. So in a 1.13431 + patch, your idea of <quote>I added this file</quote> looks 1.13432 + like <quote>every line of this file was 1.13433 + added</quote>.</para> 1.13434 + </listitem> 1.13435 + <listitem><para id="x_3f5">It treats a renamed file as the removal of the 1.13436 + old name, and the addition of the new name. This means 1.13437 + that renamed files have a big footprint in patches. (Note 1.13438 + also that Mercurial does not currently try to infer when 1.13439 + files have been renamed or copied in a patch.)</para> 1.13440 + </listitem> 1.13441 + <listitem><para id="x_3f6"><command moreinfo="none">patch</command> cannot represent 1.13442 + empty files, so you cannot use a patch to represent the 1.13443 + notion <quote>I added this empty file to the 1.13444 + tree</quote>.</para> 1.13445 + </listitem></itemizedlist> 1.13446 + </sect2> 1.13447 + 1.13448 + <sect2> 1.13449 + <title>Beware the fuzz</title> 1.13450 + 1.13451 + <para id="x_3f7">While applying a hunk at an offset, or with a fuzz factor, 1.13452 + will often be completely successful, these inexact techniques 1.13453 + naturally leave open the possibility of corrupting the patched 1.13454 + file. The most common cases typically involve applying a 1.13455 + patch twice, or at an incorrect location in the file. If 1.13456 + <command moreinfo="none">patch</command> or <command role="hg-ext-mq" moreinfo="none">qpush</command> ever mentions an offset or 1.13457 + fuzz factor, you should make sure that the modified files are 1.13458 + correct afterwards.</para> 1.13459 + 1.13460 + <para id="x_3f8">It's often a good idea to refresh a patch that has applied 1.13461 + with an offset or fuzz factor; refreshing the patch generates 1.13462 + new context information that will make it apply cleanly. I 1.13463 + say <quote>often,</quote> not <quote>always,</quote> because 1.13464 + sometimes refreshing a patch will make it fail to apply 1.13465 + against a different revision of the underlying files. In some 1.13466 + cases, such as when you're maintaining a patch that must sit 1.13467 + on top of multiple versions of a source tree, it's acceptable 1.13468 + to have a patch apply with some fuzz, provided you've verified 1.13469 + the results of the patching process in such cases.</para> 1.13470 + </sect2> 1.13471 + 1.13472 + <sect2> 1.13473 + <title>Handling rejection</title> 1.13474 + 1.13475 + <para id="x_3f9">If <command role="hg-ext-mq" moreinfo="none">qpush</command> fails to 1.13476 + apply a patch, it will print an error message and exit. If it 1.13477 + has left <filename role="special" moreinfo="none">.rej</filename> files 1.13478 + behind, it is usually best to fix up the rejected hunks before 1.13479 + you push more patches or do any further work.</para> 1.13480 + 1.13481 + <para id="x_3fa">If your patch <emphasis>used to</emphasis> apply cleanly, 1.13482 + and no longer does because you've changed the underlying code 1.13483 + that your patches are based on, Mercurial Queues can help; see 1.13484 + <xref linkend="sec:mq:merge"/> for details.</para> 1.13485 + 1.13486 + <para id="x_3fb">Unfortunately, there aren't any great techniques for 1.13487 + dealing with rejected hunks. Most often, you'll need to view 1.13488 + the <filename role="special" moreinfo="none">.rej</filename> file and edit the 1.13489 + target file, applying the rejected hunks by hand.</para> 1.13490 + 1.13491 + <para id="x_3fd">A Linux kernel hacker, Chris Mason (the author 1.13492 + of Mercurial Queues), wrote a tool called 1.13493 + <command moreinfo="none">mpatch</command> (<ulink url="http://oss.oracle.com/~mason/mpatch/">http://oss.oracle.com/~mason/mpatch/</ulink>), 1.13494 + which takes a simple approach to automating the application of 1.13495 + hunks rejected by <command moreinfo="none">patch</command>. The 1.13496 + <command moreinfo="none">mpatch</command> command can help with four common 1.13497 + reasons that a hunk may be rejected:</para> 1.13498 + 1.13499 + <itemizedlist> 1.13500 + <listitem><para id="x_3fe">The context in the middle of a hunk has 1.13501 + changed.</para> 1.13502 + </listitem> 1.13503 + <listitem><para id="x_3ff">A hunk is missing some context at the 1.13504 + beginning or end.</para> 1.13505 + </listitem> 1.13506 + <listitem><para id="x_400">A large hunk might apply better—either 1.13507 + entirely or in part—if it was broken up into 1.13508 + smaller hunks.</para> 1.13509 + </listitem> 1.13510 + <listitem><para id="x_401">A hunk removes lines with slightly different 1.13511 + content than those currently present in the file.</para> 1.13512 + </listitem></itemizedlist> 1.13513 + 1.13514 + <para id="x_402">If you use <command moreinfo="none">mpatch</command>, you 1.13515 + should be doubly careful to check your results when you're 1.13516 + done. In fact, <command moreinfo="none">mpatch</command> enforces this method 1.13517 + of double-checking the tool's output, by automatically 1.13518 + dropping you into a merge program when it has done its job, so 1.13519 + that you can verify its work and finish off any remaining 1.13520 + merges.</para> 1.13521 + </sect2> 1.13522 + </sect1> 1.13523 + 1.13524 + <sect1> 1.13525 + <title>More on patch management</title> 1.13526 + 1.13527 + <para id="x_6db">As you grow familiar with MQ, you will find yourself wanting 1.13528 + to perform other kinds of patch management operations.</para> 1.13529 + 1.13530 + <sect2> 1.13531 + <title>Deleting unwanted patches</title> 1.13532 + 1.13533 + <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 1.13534 + patch file and remove its entry from the patch series. If you 1.13535 + try to delete a patch that is still applied, <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> will refuse.</para> 1.13536 + 1.13537 + <!-- BEGIN ch11/qdelete.go --> 1.13538 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput> 1.13539 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput> 1.13540 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> 1.13541 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew bad.patch</userinput> 1.13542 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.13543 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> 1.13544 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.13545 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput> 1.13546 +abort: cannot delete applied patch bad.patch 1.13547 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput> 1.13548 +patch queue now empty 1.13549 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput> 1.13550 +</screen> 1.13551 +<!-- END ch11/qdelete.go --> 1.13552 + 1.13553 + </sect2> 1.13554 + 1.13555 + <sect2> 1.13556 + <title>Converting to and from permanent revisions</title> 1.13557 + 1.13558 + <para id="x_6dd">Once you're done working on a patch and want to 1.13559 + turn it into a permanent changeset, use the <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command. Pass a revision 1.13560 + to the command to identify the patch that you want to turn into 1.13561 + a regular changeset; this patch must already be applied.</para> 1.13562 + 1.13563 + <!-- BEGIN ch11/qdelete.convert --> 1.13564 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew good.patch</userinput> 1.13565 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> 1.13566 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> 1.13567 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh -m 'Good change'</userinput> 1.13568 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qfinish tip</userinput> 1.13569 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> 1.13570 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact</userinput> 1.13571 +0[tip] 32fc5ce6b092 2009-08-16 14:04 +0000 bos 1.13572 + Good change 1.13573 + 1.13574 +</screen> 1.13575 +<!-- END ch11/qdelete.convert --> 1.13576 + 1.13577 + 1.13578 + <para id="x_6e0">The <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command 1.13579 + accepts an <option>--all</option> or <option>-a</option> 1.13580 + option, which turns all applied patches into regular 1.13581 + changesets.</para> 1.13582 + 1.13583 + <para id="x_6de">It is also possible to turn an existing changeset into a 1.13584 + patch, by passing the <option>-r</option> option to <command role="hg-ext-mq" moreinfo="none">hg qimport</command>.</para> 1.13585 + 1.13586 + <!-- BEGIN ch11/qdelete.import --> 1.13587 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qimport -r tip</userinput> 1.13588 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> 1.13589 +0.diff 1.13590 +</screen> 1.13591 +<!-- END ch11/qdelete.import --> 1.13592 + 1.13593 + 1.13594 + <para id="x_6df">Note that it only makes sense to convert a changeset into 1.13595 + a patch if you have not propagated that changeset into any 1.13596 + other repositories. The imported changeset's ID will change 1.13597 + every time you refresh the patch, which will make Mercurial 1.13598 + treat it as unrelated to the original changeset if you have 1.13599 + pushed it somewhere else.</para> 1.13600 + </sect2> 1.13601 + </sect1> 1.13602 + 1.13603 + <sect1 id="sec:mq:perf"> 1.13604 + <title>Getting the best performance out of MQ</title> 1.13605 + 1.13606 + <para id="x_403">MQ is very efficient at handling a large number 1.13607 + of patches. I ran some performance experiments in mid-2006 for a 1.13608 + talk that I gave at the 2006 EuroPython conference (on modern 1.13609 + hardware, you should expect better performance than you'll see 1.13610 + below). I used as my data set the Linux 2.6.17-mm1 patch 1.13611 + series, which consists of 1,738 patches. I applied these on top 1.13612 + of a Linux kernel repository containing all 27,472 revisions 1.13613 + between Linux 2.6.12-rc2 and Linux 2.6.17.</para> 1.13614 + 1.13615 + <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 1.13616 + 1,738 patches in 3.5 minutes, and <command role="hg-cmd" moreinfo="none">hg qpop 1.13617 + <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> 1.13618 + them all in 30 seconds. (On a newer laptop, the time to push 1.13619 + all patches dropped to two minutes.) I could <command role="hg-ext-mq" moreinfo="none">qrefresh</command> one of the biggest patches 1.13620 + (which made 22,779 lines of changes to 287 files) in 6.6 1.13621 + seconds.</para> 1.13622 + 1.13623 + <para id="x_405">Clearly, MQ is well suited to working in large trees, but 1.13624 + there are a few tricks you can use to get the best performance 1.13625 + of it.</para> 1.13626 + 1.13627 + <para id="x_406">First of all, try to <quote>batch</quote> operations 1.13628 + 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 1.13629 + working directory once to make sure you haven't made some 1.13630 + changes and then forgotten to run <command role="hg-ext-mq" moreinfo="none">qrefresh</command>. On a small tree, the 1.13631 + time that this scan takes is unnoticeable. However, on a 1.13632 + medium-sized tree (containing tens of thousands of files), it 1.13633 + can take a second or more.</para> 1.13634 + 1.13635 + <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 1.13636 + pop multiple patches at a time. You can identify the 1.13637 + <quote>destination patch</quote> that you want to end up at. 1.13638 + When you <command role="hg-ext-mq" moreinfo="none">qpush</command> with a 1.13639 + destination specified, it will push patches until that patch is 1.13640 + at the top of the applied stack. When you <command role="hg-ext-mq" moreinfo="none">qpop</command> to a destination, MQ will pop 1.13641 + patches until the destination patch is at the top.</para> 1.13642 + 1.13643 + <para id="x_408">You can identify a destination patch using either the name 1.13644 + of the patch, or by number. If you use numeric addressing, 1.13645 + patches are counted from zero; this means that the first patch 1.13646 + is zero, the second is one, and so on.</para> 1.13647 + </sect1> 1.13648 + 1.13649 + <sect1 id="sec:mq:merge"> 1.13650 + <title>Updating your patches when the underlying code 1.13651 + changes</title> 1.13652 + 1.13653 + <para id="x_409">It's common to have a stack of patches on top of an 1.13654 + underlying repository that you don't modify directly. If you're 1.13655 + working on changes to third-party code, or on a feature that is 1.13656 + taking longer to develop than the rate of change of the code 1.13657 + beneath, you will often need to sync up with the underlying 1.13658 + code, and fix up any hunks in your patches that no longer apply. 1.13659 + This is called <emphasis>rebasing</emphasis> your patch 1.13660 + series.</para> 1.13661 + 1.13662 + <para id="x_40a">The simplest way to do this is to <command role="hg-cmd" moreinfo="none">hg 1.13663 + qpop <option role="hg-ext-mq-cmd-qpop-opt">hg 1.13664 + -a</option></command> your patches, then <command role="hg-cmd" moreinfo="none">hg pull</command> changes into the underlying 1.13665 + repository, and finally <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your 1.13666 + patches again. MQ will stop pushing any time it runs across a 1.13667 + patch that fails to apply during conflicts, allowing you to fix 1.13668 + your conflicts, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the 1.13669 + affected patch, and continue pushing until you have fixed your 1.13670 + entire stack.</para> 1.13671 + 1.13672 + <para id="x_40b">This approach is easy to use and works well if you don't 1.13673 + expect changes to the underlying code to affect how well your 1.13674 + patches apply. If your patch stack touches code that is modified 1.13675 + frequently or invasively in the underlying repository, however, 1.13676 + fixing up rejected hunks by hand quickly becomes 1.13677 + tiresome.</para> 1.13678 + 1.13679 + <para id="x_40c">It's possible to partially automate the rebasing process. 1.13680 + If your patches apply cleanly against some revision of the 1.13681 + underlying repo, MQ can use this information to help you to 1.13682 + resolve conflicts between your patches and a different 1.13683 + revision.</para> 1.13684 + 1.13685 + <para id="x_40d">The process is a little involved.</para> 1.13686 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.13687 + <listitem><para id="x_40e">To begin, <command role="hg-cmd" moreinfo="none">hg qpush 1.13688 + -a</command> all of your patches on top of the revision 1.13689 + where you know that they apply cleanly.</para> 1.13690 + </listitem> 1.13691 + <listitem><para id="x_40f">Save a backup copy of your patch directory using 1.13692 + <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>. 1.13693 + This prints the name of the directory that it has saved the 1.13694 + patches in. It will save the patches to a directory called 1.13695 + <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>, where 1.13696 + <literal moreinfo="none">N</literal> is a small integer. It also commits a 1.13697 + <quote>save changeset</quote> on top of your applied 1.13698 + patches; this is for internal book-keeping, and records the 1.13699 + states of the <filename role="special" moreinfo="none">series</filename> and 1.13700 + <filename role="special" moreinfo="none">status</filename> files.</para> 1.13701 + </listitem> 1.13702 + <listitem><para id="x_410">Use <command role="hg-cmd" moreinfo="none">hg pull</command> to 1.13703 + bring new changes into the underlying repository. (Don't 1.13704 + run <command role="hg-cmd" moreinfo="none">hg pull -u</command>; see below 1.13705 + for why.)</para> 1.13706 + </listitem> 1.13707 + <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 1.13708 + the patches you have pushed.</para> 1.13709 + </listitem> 1.13710 + <listitem><para id="x_412">Merge all patches using <command moreinfo="none">hg qpush -m 1.13711 + -a</command>. The <option role="hg-ext-mq-cmd-qpush-opt">-m</option> option to 1.13712 + <command role="hg-ext-mq" moreinfo="none">qpush</command> tells MQ to 1.13713 + perform a three-way merge if the patch fails to 1.13714 + apply.</para> 1.13715 + </listitem></orderedlist> 1.13716 + 1.13717 + <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>, 1.13718 + each patch in the <filename role="special" moreinfo="none">series</filename> 1.13719 + file is applied normally. If a patch applies with fuzz or 1.13720 + rejects, MQ looks at the queue you <command role="hg-ext-mq" moreinfo="none">qsave</command>d, and performs a three-way 1.13721 + merge with the corresponding changeset. This merge uses 1.13722 + Mercurial's normal merge machinery, so it may pop up a GUI merge 1.13723 + tool to help you to resolve problems.</para> 1.13724 + 1.13725 + <para id="x_414">When you finish resolving the effects of a patch, MQ 1.13726 + refreshes your patch based on the result of the merge.</para> 1.13727 + 1.13728 + <para id="x_415">At the end of this process, your repository will have one 1.13729 + extra head from the old patch queue, and a copy of the old patch 1.13730 + queue will be in <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>. You can remove the 1.13731 + extra head using <command role="hg-cmd" moreinfo="none">hg qpop -a -n 1.13732 + patches.N</command> or <command role="hg-cmd" moreinfo="none">hg 1.13733 + strip</command>. You can delete <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename> once you are sure 1.13734 + that you no longer need it as a backup.</para> 1.13735 + </sect1> 1.13736 + 1.13737 + <sect1> 1.13738 + <title>Identifying patches</title> 1.13739 + 1.13740 + <para id="x_416">MQ commands that work with patches let you refer to a patch 1.13741 + either by using its name or by a number. By name is obvious 1.13742 + 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 1.13743 + push patches until <filename moreinfo="none">foo.patch</filename> is 1.13744 + applied.</para> 1.13745 + 1.13746 + <para id="x_417">As a shortcut, you can refer to a patch using both a name 1.13747 + and a numeric offset; <literal moreinfo="none">foo.patch-2</literal> means 1.13748 + <quote>two patches before <literal moreinfo="none">foo.patch</literal></quote>, 1.13749 + while <literal moreinfo="none">bar.patch+4</literal> means <quote>four patches 1.13750 + after <literal moreinfo="none">bar.patch</literal></quote>.</para> 1.13751 + 1.13752 + <para id="x_418">Referring to a patch by index isn't much different. The 1.13753 + first patch printed in the output of <command role="hg-ext-mq" moreinfo="none">qseries</command> is patch zero (yes, it's 1.13754 + one of those start-at-zero counting systems); the second is 1.13755 + patch one; and so on.</para> 1.13756 + 1.13757 + <para id="x_419">MQ also makes it easy to work with patches when you are 1.13758 + using normal Mercurial commands. Every command that accepts a 1.13759 + changeset ID will also accept the name of an applied patch. MQ 1.13760 + augments the tags normally in the repository with an eponymous 1.13761 + one for each applied patch. In addition, the special tags 1.13762 + <literal role="tag" moreinfo="none">qbase</literal> and 1.13763 + <literal role="tag" moreinfo="none">qtip</literal> identify 1.13764 + the <quote>bottom-most</quote> and topmost applied patches, 1.13765 + respectively.</para> 1.13766 + 1.13767 + <para id="x_41a">These additions to Mercurial's normal tagging capabilities 1.13768 + make dealing with patches even more of a breeze.</para> 1.13769 + <itemizedlist> 1.13770 + <listitem><para id="x_41b">Want to patchbomb a mailing list with your 1.13771 + latest series of changes?</para> 1.13772 + <programlisting format="linespecific">hg email qbase:qtip</programlisting> 1.13773 + <para id="x_41c"> (Don't know what <quote>patchbombing</quote> is? See 1.13774 + <xref linkend="sec:hgext:patchbomb"/>.)</para> 1.13775 + </listitem> 1.13776 + <listitem><para id="x_41d">Need to see all of the patches since 1.13777 + <literal moreinfo="none">foo.patch</literal> that have touched files in a 1.13778 + subdirectory of your tree?</para> 1.13779 + <programlisting format="linespecific">hg log -r foo.patch:qtip subdir</programlisting> 1.13780 + </listitem> 1.13781 + </itemizedlist> 1.13782 + 1.13783 + <para id="x_41e">Because MQ makes the names of patches available to the rest 1.13784 + of Mercurial through its normal internal tag machinery, you 1.13785 + don't need to type in the entire name of a patch when you want 1.13786 + to identify it by name.</para> 1.13787 + 1.13788 + <para id="x_41f">Another nice consequence of representing patch names as tags 1.13789 + is that when you run the <command role="hg-cmd" moreinfo="none">hg log</command> 1.13790 + command, it will display a patch's name as a tag, simply as part 1.13791 + of its normal output. This makes it easy to visually 1.13792 + distinguish applied patches from underlying 1.13793 + <quote>normal</quote> revisions. The following example shows a 1.13794 + few normal Mercurial commands in use with applied 1.13795 + patches.</para> 1.13796 + 1.13797 + <!-- BEGIN mq.id.output --> 1.13798 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> 1.13799 +first.patch 1.13800 +second.patch 1.13801 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r qbase:qtip</userinput> 1.13802 +changeset: 1:c3bcf3b7335a 1.13803 +tag: first.patch 1.13804 +tag: qbase 1.13805 +user: Bryan O'Sullivan <bos@serpentine.com> 1.13806 +date: Sun Aug 16 14:05:08 2009 +0000 1.13807 +summary: [mq]: first.patch 1.13808 + 1.13809 +changeset: 2:d189ba63b5f7 1.13810 +tag: qtip 1.13811 +tag: second.patch 1.13812 +tag: tip 1.13813 +user: Bryan O'Sullivan <bos@serpentine.com> 1.13814 +date: Sun Aug 16 14:05:09 2009 +0000 1.13815 +summary: [mq]: second.patch 1.13816 + 1.13817 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg export second.patch</userinput> 1.13818 +# HG changeset patch 1.13819 +# User Bryan O'Sullivan <bos@serpentine.com> 1.13820 +# Date 1250431509 0 1.13821 +# Node ID d189ba63b5f7427f9644663c01fc16fe80399c65 1.13822 +# Parent c3bcf3b7335afc0a250e85c51a1266d35d43a545 1.13823 +[mq]: second.patch 1.13824 + 1.13825 +diff -r c3bcf3b7335a -r d189ba63b5f7 other.c 1.13826 +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.13827 ++++ b/other.c Sun Aug 16 14:05:09 2009 +0000 1.13828 +@@ -0,0 +1,1 @@ 1.13829 ++double u; 1.13830 +</screen> 1.13831 +<!-- END mq.id.output --> 1.13832 + 1.13833 + </sect1> 1.13834 + 1.13835 + <sect1> 1.13836 + <title>Useful things to know about</title> 1.13837 + 1.13838 + <para id="x_420">There are a number of aspects of MQ usage that don't fit 1.13839 + tidily into sections of their own, but that are good to know. 1.13840 + Here they are, in one place.</para> 1.13841 + 1.13842 + <itemizedlist> 1.13843 + <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 1.13844 + that represents the patch after the pop/push will have a 1.13845 + <emphasis>different identity</emphasis> than the changeset 1.13846 + that represented the hash beforehand. See <xref linkend="sec:mqref:cmd:qpush"/> for 1.13847 + information as to why this is.</para> 1.13848 + </listitem> 1.13849 + <listitem><para id="x_422">It's not a good idea to <command role="hg-cmd" moreinfo="none">hg merge</command> changes from another 1.13850 + branch with a patch changeset, at least if you want to 1.13851 + maintain the <quote>patchiness</quote> of that changeset and 1.13852 + changesets below it on the patch stack. If you try to do 1.13853 + this, it will appear to succeed, but MQ will become 1.13854 + confused.</para> 1.13855 + </listitem></itemizedlist> 1.13856 + </sect1> 1.13857 + 1.13858 + <sect1 id="sec:mq:repo"> 1.13859 + <title>Managing patches in a repository</title> 1.13860 + 1.13861 + <para id="x_423">Because MQ's <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory resides 1.13862 + outside a Mercurial repository's working directory, the 1.13863 + <quote>underlying</quote> Mercurial repository knows nothing 1.13864 + about the management or presence of patches.</para> 1.13865 + 1.13866 + <para id="x_424">This presents the interesting possibility of managing the 1.13867 + contents of the patch directory as a Mercurial repository in its 1.13868 + own right. This can be a useful way to work. For example, you 1.13869 + 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 1.13870 + patch. This lets you <quote>roll back</quote> to that version 1.13871 + of the patch later on.</para> 1.13872 + 1.13873 + <para id="x_425">You can then share different versions of the same patch 1.13874 + stack among multiple underlying repositories. I use this when I 1.13875 + am developing a Linux kernel feature. I have a pristine copy of 1.13876 + my kernel sources for each of several CPU architectures, and a 1.13877 + cloned repository under each that contains the patches I am 1.13878 + working on. When I want to test a change on a different 1.13879 + architecture, I push my current patches to the patch repository 1.13880 + associated with that kernel tree, pop and push all of my 1.13881 + patches, and build and test that kernel.</para> 1.13882 + 1.13883 + <para id="x_426">Managing patches in a repository makes it possible for 1.13884 + multiple developers to work on the same patch series without 1.13885 + colliding with each other, all on top of an underlying source 1.13886 + base that they may or may not control.</para> 1.13887 + 1.13888 + <sect2> 1.13889 + <title>MQ support for patch repositories</title> 1.13890 + 1.13891 + <para id="x_427">MQ helps you to work with the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a 1.13892 + repository; when you prepare a repository for working with 1.13893 + patches using <command role="hg-ext-mq" moreinfo="none">qinit</command>, you 1.13894 + can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg 1.13895 + -c</option> option to create the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a 1.13896 + Mercurial repository.</para> 1.13897 + 1.13898 + <note> 1.13899 + <para id="x_428"> If you forget to use the <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you 1.13900 + can simply go into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory at any 1.13901 + time and run <command role="hg-cmd" moreinfo="none">hg init</command>. 1.13902 + 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> 1.13903 + 1.13904 + <para id="x_429"> (<command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command> 1.13905 + does this for you automatically); you 1.13906 + <emphasis>really</emphasis> don't want to manage the 1.13907 + <filename role="special" moreinfo="none">status</filename> file.</para> 1.13908 + </note> 1.13909 + 1.13910 + <para id="x_42a">As a convenience, if MQ notices that the <filename class="directory" moreinfo="none">.hg/patches</filename> directory is a 1.13911 + repository, it will automatically <command role="hg-cmd" moreinfo="none">hg 1.13912 + add</command> every patch that you create and import.</para> 1.13913 + 1.13914 + <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> 1.13915 + directory. This saves some bothersome typing.</para> 1.13916 + 1.13917 + <para id="x_42c">Finally, as a convenience to manage the patch directory, 1.13918 + you can define the alias <command moreinfo="none">mq</command> on Unix 1.13919 + systems. For example, on Linux systems using the 1.13920 + <command moreinfo="none">bash</command> shell, you can include the following 1.13921 + snippet in your <filename role="home" moreinfo="none">~/.bashrc</filename>.</para> 1.13922 + 1.13923 + <programlisting format="linespecific">alias mq=`hg -R $(hg root)/.hg/patches'</programlisting> 1.13924 + 1.13925 + <para id="x_42d">You can then issue commands of the form <command moreinfo="none">mq 1.13926 + pull</command> from the main repository.</para> 1.13927 + </sect2> 1.13928 + 1.13929 + <sect2> 1.13930 + <title>A few things to watch out for</title> 1.13931 + 1.13932 + <para id="x_42e">MQ's support for working with a repository full of patches 1.13933 + is limited in a few small respects.</para> 1.13934 + 1.13935 + <para id="x_42f">MQ cannot automatically detect changes that you make to 1.13936 + the patch directory. If you <command role="hg-cmd" moreinfo="none">hg 1.13937 + pull</command>, manually edit, or <command role="hg-cmd" moreinfo="none">hg 1.13938 + update</command> changes to patches or the <filename role="special" moreinfo="none">series</filename> file, you will have to 1.13939 + <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and 1.13940 + then <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in 1.13941 + the underlying repository to see those changes show up there. 1.13942 + If you forget to do this, you can confuse MQ's idea of which 1.13943 + patches are applied.</para> 1.13944 + 1.13945 + </sect2> 1.13946 + </sect1> 1.13947 + <sect1 id="sec:mq:tools"> 1.13948 + <title>Third party tools for working with patches</title> 1.13949 + 1.13950 + <para id="x_430">Once you've been working with patches for a while, you'll 1.13951 + find yourself hungry for tools that will help you to understand 1.13952 + and manipulate the patches you're dealing with.</para> 1.13953 + 1.13954 + <para id="x_431">The <command moreinfo="none">diffstat</command> command 1.13955 + <citation>web:diffstat</citation> generates a histogram of the 1.13956 + modifications made to each file in a patch. It provides a good 1.13957 + way to <quote>get a sense of</quote> a patch—which files 1.13958 + it affects, and how much change it introduces to each file and 1.13959 + as a whole. (I find that it's a good idea to use 1.13960 + <command moreinfo="none">diffstat</command>'s <option role="cmd-opt-diffstat">-p</option> option as a matter of 1.13961 + course, as otherwise it will try to do clever things with 1.13962 + prefixes of file names that inevitably confuse at least 1.13963 + me.)</para> 1.13964 + 1.13965 +<!-- BEGIN mq.tools.tools --> 1.13966 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diffstat -p1 remove-redundant-null-checks.patch</userinput> 1.13967 + drivers/char/agp/sgi-agp.c | 5 ++--- 1.13968 + drivers/char/hvcs.c | 11 +++++------ 1.13969 + drivers/message/fusion/mptfc.c | 6 ++---- 1.13970 + drivers/message/fusion/mptsas.c | 3 +-- 1.13971 + drivers/net/fs_enet/fs_enet-mii.c | 3 +-- 1.13972 + drivers/net/wireless/ipw2200.c | 22 ++++++---------------- 1.13973 + drivers/scsi/libata-scsi.c | 4 +--- 1.13974 + drivers/video/au1100fb.c | 3 +-- 1.13975 + 8 files changed, 19 insertions(+), 38 deletions(-) 1.13976 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">filterdiff -i '*/video/*' remove-redundant-null-checks.patch</userinput> 1.13977 +--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers 1.13978 ++++ a/drivers/video/au1100fb.c 1.13979 +@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void) 1.13980 + { 1.13981 + driver_unregister(&au1100fb_driver); 1.13982 + 1.13983 +- if (drv_info.opt_mode) 1.13984 +- kfree(drv_info.opt_mode); 1.13985 ++ kfree(drv_info.opt_mode); 1.13986 + } 1.13987 + 1.13988 + module_init(au1100fb_init); 1.13989 +</screen> 1.13990 +<!-- END mq.tools.tools --> 1.13991 + 1.13992 + 1.13993 + <para id="x_432">The <literal role="package" moreinfo="none">patchutils</literal> package 1.13994 + <citation>web:patchutils</citation> is invaluable. It provides a 1.13995 + set of small utilities that follow the <quote>Unix 1.13996 + philosophy;</quote> each does one useful thing with a patch. 1.13997 + The <literal role="package" moreinfo="none">patchutils</literal> command I use 1.13998 + most is <command moreinfo="none">filterdiff</command>, which extracts subsets 1.13999 + from a patch file. For example, given a patch that modifies 1.14000 + hundreds of files across dozens of directories, a single 1.14001 + invocation of <command moreinfo="none">filterdiff</command> can generate a 1.14002 + smaller patch that only touches files whose names match a 1.14003 + particular glob pattern. See <xref linkend="mq-collab:tips:interdiff"/> for another 1.14004 + example.</para> 1.14005 + 1.14006 + </sect1> 1.14007 + <sect1> 1.14008 + <title>Good ways to work with patches</title> 1.14009 + 1.14010 + <para id="x_433">Whether you are working on a patch series to submit to a 1.14011 + free software or open source project, or a series that you 1.14012 + intend to treat as a sequence of regular changesets when you're 1.14013 + done, you can use some simple techniques to keep your work well 1.14014 + organized.</para> 1.14015 + 1.14016 + <para id="x_434">Give your patches descriptive names. A good name for a 1.14017 + patch might be <filename moreinfo="none">rework-device-alloc.patch</filename>, 1.14018 + because it will immediately give you a hint what the purpose of 1.14019 + the patch is. Long names shouldn't be a problem; you won't be 1.14020 + typing the names often, but you <emphasis>will</emphasis> be 1.14021 + 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 1.14022 + becomes especially important when you have a number of patches 1.14023 + to work with, or if you are juggling a number of different tasks 1.14024 + and your patches only get a fraction of your attention.</para> 1.14025 + 1.14026 + <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 1.14027 + 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 1.14028 + 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 1.14029 + one I intended, and it's often tricky to migrate changes into 1.14030 + the right patch after making them in the wrong one.</para> 1.14031 + 1.14032 + <para id="x_436">For this reason, it is very much worth investing a little 1.14033 + time to learn how to use some of the third-party tools I 1.14034 + described in <xref linkend="sec:mq:tools"/>, 1.14035 + particularly 1.14036 + <command moreinfo="none">diffstat</command> and <command moreinfo="none">filterdiff</command>. 1.14037 + The former will give you a quick idea of what changes your patch 1.14038 + is making, while the latter makes it easy to splice hunks 1.14039 + selectively out of one patch and into another.</para> 1.14040 + 1.14041 + </sect1> 1.14042 + <sect1> 1.14043 + <title>MQ cookbook</title> 1.14044 + 1.14045 + <sect2> 1.14046 + <title>Manage <quote>trivial</quote> patches</title> 1.14047 + 1.14048 + <para id="x_437">Because the overhead of dropping files into a new 1.14049 + Mercurial repository is so low, it makes a lot of sense to 1.14050 + manage patches this way even if you simply want to make a few 1.14051 + changes to a source tarball that you downloaded.</para> 1.14052 + 1.14053 + <para id="x_438">Begin by downloading and unpacking the source tarball, and 1.14054 + turning it into a Mercurial repository.</para> 1.14055 + 1.14056 + <!-- BEGIN mq.tarball.download --> 1.14057 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.5.tar.bz2</userinput> 1.14058 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.5.tar.bz2</userinput> 1.14059 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.5</userinput> 1.14060 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init</userinput> 1.14061 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -q --addremove --message netplug-1.2.5</userinput> 1.14062 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.14063 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug</userinput> 1.14064 +updating working directory 1.14065 +18 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.14066 +</screen> 1.14067 +<!-- END mq.tarball.download --> 1.14068 + 1.14069 + 1.14070 + <para id="x_439">Continue by creating a patch stack and making your 1.14071 + changes.</para> 1.14072 + 1.14073 + <!-- BEGIN mq.tarball.qinit --> 1.14074 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug</userinput> 1.14075 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> 1.14076 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -m 'fix build problem with gcc 4' build-fix.patch</userinput> 1.14077 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c</userinput> 1.14078 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.14079 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -p</userinput> 1.14080 +changeset: 1:eeab56666c54 1.14081 +tag: qtip 1.14082 +tag: build-fix.patch 1.14083 +tag: tip 1.14084 +tag: qbase 1.14085 +user: Bryan O'Sullivan <bos@serpentine.com> 1.14086 +date: Sun Aug 16 14:05:10 2009 +0000 1.14087 +summary: fix build problem with gcc 4 1.14088 + 1.14089 +diff -r 1f6afe9a2d68 -r eeab56666c54 netlink.c 1.14090 +--- a/netlink.c Sun Aug 16 14:05:09 2009 +0000 1.14091 ++++ b/netlink.c Sun Aug 16 14:05:10 2009 +0000 1.14092 +@@ -275,7 +275,7 @@ 1.14093 + exit(1); 1.14094 + } 1.14095 + 1.14096 +- int addr_len = sizeof(addr); 1.14097 ++ socklen_t addr_len = sizeof(addr); 1.14098 + 1.14099 + if (getsockname(fd, (struct sockaddr *) &addr, &addr_len) == -1) { 1.14100 + do_log(LOG_ERR, "Could not get socket details: %m"); 1.14101 + 1.14102 +</screen> 1.14103 +<!-- END mq.tarball.qinit --> 1.14104 + 1.14105 + 1.14106 + <para id="x_43a">Let's say a few weeks or months pass, and your package 1.14107 + author releases a new version. First, bring their changes 1.14108 + into the repository.</para> 1.14109 + 1.14110 + <!-- BEGIN mq.tarball.newsource --> 1.14111 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> 1.14112 +patch queue now empty 1.14113 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.14114 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.8.tar.bz2</userinput> 1.14115 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug-1.2.8</userinput> 1.14116 +updating working directory 1.14117 +18 files updated, 0 files merged, 0 files removed, 0 files unresolved 1.14118 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput> 1.14119 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg locate -0 | xargs -0 rm</userinput> 1.14120 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> 1.14121 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.8.tar.bz2</userinput> 1.14122 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput> 1.14123 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit --addremove --message netplug-1.2.8</userinput> 1.14124 +</screen> 1.14125 +<!-- END mq.tarball.newsource --> 1.14126 + 1.14127 + 1.14128 + <para id="x_43b">The pipeline starting with <command role="hg-cmd" moreinfo="none">hg 1.14129 + locate</command> above deletes all files in the working 1.14130 + directory, so that <command role="hg-cmd" moreinfo="none">hg 1.14131 + commit</command>'s <option role="hg-opt-commit">--addremove</option> option can 1.14132 + actually tell which files have really been removed in the 1.14133 + newer version of the source.</para> 1.14134 + 1.14135 + <para id="x_43c">Finally, you can apply your patches on top of the new 1.14136 + tree.</para> 1.14137 + 1.14138 + <!-- BEGIN mq.tarball.repush --> 1.14139 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../netplug</userinput> 1.14140 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../netplug-1.2.8</userinput> 1.14141 +pulling from ../netplug-1.2.8 1.14142 +searching for changes 1.14143 +adding changesets 1.14144 +adding manifests 1.14145 +adding file changes 1.14146 +added 1 changesets with 12 changes to 12 files 1.14147 +(run 'hg update' to get a working copy) 1.14148 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> 1.14149 +(working directory not at tip) 1.14150 +applying build-fix.patch 1.14151 +now at: build-fix.patch 1.14152 +</screen> 1.14153 +<!-- END mq.tarball.repush --> 1.14154 + 1.14155 + </sect2> 1.14156 + 1.14157 + <sect2 id="sec:mq:combine"> 1.14158 + <title>Combining entire patches</title> 1.14159 + 1.14160 + <para id="x_43d">MQ provides a command, <command role="hg-ext-mq" moreinfo="none">qfold</command> that lets you combine 1.14161 + entire patches. This <quote>folds</quote> the patches you 1.14162 + name, in the order you name them, into the topmost applied 1.14163 + patch, and concatenates their descriptions onto the end of its 1.14164 + description. The patches that you fold must be unapplied 1.14165 + before you fold them.</para> 1.14166 + 1.14167 + <para id="x_43e">The order in which you fold patches matters. If your 1.14168 + topmost applied patch is <literal moreinfo="none">foo</literal>, and you 1.14169 + <command role="hg-ext-mq" moreinfo="none">qfold</command> 1.14170 + <literal moreinfo="none">bar</literal> and <literal moreinfo="none">quux</literal> into it, 1.14171 + you will end up with a patch that has the same effect as if 1.14172 + you applied first <literal moreinfo="none">foo</literal>, then 1.14173 + <literal moreinfo="none">bar</literal>, followed by 1.14174 + <literal moreinfo="none">quux</literal>.</para> 1.14175 + </sect2> 1.14176 + 1.14177 + <sect2> 1.14178 + <title>Merging part of one patch into another</title> 1.14179 + 1.14180 + <para id="x_43f">Merging <emphasis>part</emphasis> of one patch into 1.14181 + another is more difficult than combining entire 1.14182 + patches.</para> 1.14183 + 1.14184 + <para id="x_440">If you want to move changes to entire files, you can use 1.14185 + <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 1.14186 + modifications to snip out of one patch, concatenating its 1.14187 + output onto the end of the patch you want to merge into. You 1.14188 + usually won't need to modify the patch you've merged the 1.14189 + changes from. Instead, MQ will report some rejected hunks 1.14190 + when you <command role="hg-ext-mq" moreinfo="none">qpush</command> it (from 1.14191 + the hunks you moved into the other patch), and you can simply 1.14192 + <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the patch to drop 1.14193 + the duplicate hunks.</para> 1.14194 + 1.14195 + <para id="x_441">If you have a patch that has multiple hunks modifying a 1.14196 + file, and you only want to move a few of those hunks, the job 1.14197 + becomes more messy, but you can still partly automate it. Use 1.14198 + <command moreinfo="none">lsdiff -nvv</command> to print some metadata about 1.14199 + the patch.</para> 1.14200 + 1.14201 + <!-- BEGIN mq.tools.lsdiff --> 1.14202 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">lsdiff -nvv remove-redundant-null-checks.patch</userinput> 1.14203 +22 File #1 a/drivers/char/agp/sgi-agp.c 1.14204 + 24 Hunk #1 static int __devinit agp_sgi_init(void) 1.14205 +37 File #2 a/drivers/char/hvcs.c 1.14206 + 39 Hunk #1 static struct tty_operations hvcs_ops = 1.14207 + 53 Hunk #2 static int hvcs_alloc_index_list(int n) 1.14208 +69 File #3 a/drivers/message/fusion/mptfc.c 1.14209 + 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in 1.14210 +85 File #4 a/drivers/message/fusion/mptsas.c 1.14211 + 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc) 1.14212 +98 File #5 a/drivers/net/fs_enet/fs_enet-mii.c 1.14213 + 100 Hunk #1 static struct fs_enet_mii_bus *create_bu 1.14214 +111 File #6 a/drivers/net/wireless/ipw2200.c 1.14215 + 113 Hunk #1 static struct ipw_fw_error *ipw_alloc_er 1.14216 + 126 Hunk #2 static ssize_t clear_error(struct device 1.14217 + 140 Hunk #3 static void ipw_irq_tasklet(struct ipw_p 1.14218 + 150 Hunk #4 static void ipw_pci_remove(struct pci_de 1.14219 +164 File #7 a/drivers/scsi/libata-scsi.c 1.14220 + 166 Hunk #1 int ata_cmd_ioctl(struct scsi_device *sc 1.14221 +178 File #8 a/drivers/video/au1100fb.c 1.14222 + 180 Hunk #1 void __exit au1100fb_cleanup(void) 1.14223 +</screen> 1.14224 +<!-- END mq.tools.lsdiff --> 1.14225 + 1.14226 + 1.14227 + <para id="x_442">This command prints three different kinds of 1.14228 + number:</para> 1.14229 + <itemizedlist> 1.14230 + <listitem><para id="x_443">(in the first column) a <emphasis>file 1.14231 + number</emphasis> to identify each file modified in the 1.14232 + patch;</para> 1.14233 + </listitem> 1.14234 + <listitem><para id="x_444">(on the next line, indented) the line number 1.14235 + within a modified file where a hunk starts; and</para> 1.14236 + </listitem> 1.14237 + <listitem><para id="x_445">(on the same line) a <emphasis>hunk 1.14238 + number</emphasis> to identify that hunk.</para> 1.14239 + </listitem></itemizedlist> 1.14240 + 1.14241 + <para id="x_446">You'll have to use some visual inspection, and reading of 1.14242 + the patch, to identify the file and hunk numbers you'll want, 1.14243 + but you can then pass them to to 1.14244 + <command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">--files</option> and <option role="cmd-opt-filterdiff">--hunks</option> options, to 1.14245 + select exactly the file and hunk you want to extract.</para> 1.14246 + 1.14247 + <para id="x_447">Once you have this hunk, you can concatenate it onto the 1.14248 + end of your destination patch and continue with the remainder 1.14249 + of <xref linkend="sec:mq:combine"/>.</para> 1.14250 + 1.14251 + </sect2> 1.14252 + </sect1> 1.14253 + <sect1> 1.14254 + <title>Differences between quilt and MQ</title> 1.14255 + 1.14256 + <para id="x_448">If you are already familiar with quilt, MQ provides a 1.14257 + similar command set. There are a few differences in the way 1.14258 + that it works.</para> 1.14259 + 1.14260 + <para id="x_449">You will already have noticed that most quilt commands have 1.14261 + MQ counterparts that simply begin with a 1.14262 + <quote><literal moreinfo="none">q</literal></quote>. The exceptions are quilt's 1.14263 + <literal moreinfo="none">add</literal> and <literal moreinfo="none">remove</literal> commands, 1.14264 + 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 1.14265 + remove</command> commands. There is no MQ equivalent of the 1.14266 + quilt <literal moreinfo="none">edit</literal> command.</para> 1.14267 + 1.14268 + </sect1> 1.14269 +</chapter> 1.14270 + 1.14271 +<!-- 1.14272 +local variables: 1.14273 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.14274 +end: 1.14275 +--> 1.14276 + 1.14277 + <!-- BEGIN ch13 --> 1.14278 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.14279 + 1.14280 +<chapter id="chap:mq-collab"> 1.14281 + <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?> 1.14282 + <title>Advanced uses of Mercurial Queues</title> 1.14283 + 1.14284 + <para id="x_15d">While it's easy to pick up straightforward uses of Mercurial 1.14285 + Queues, use of a little discipline and some of MQ's less 1.14286 + frequently used capabilities makes it possible to work in 1.14287 + complicated development environments.</para> 1.14288 + 1.14289 + <para id="x_15e">In this chapter, I will use as an example a technique I have 1.14290 + used to manage the development of an Infiniband device driver for 1.14291 + the Linux kernel. The driver in question is large (at least as 1.14292 + drivers go), with 25,000 lines of code spread across 35 source 1.14293 + files. It is maintained by a small team of developers.</para> 1.14294 + 1.14295 + <para id="x_15f">While much of the material in this chapter is specific to 1.14296 + Linux, the same principles apply to any code base for which you're 1.14297 + not the primary owner, and upon which you need to do a lot of 1.14298 + development.</para> 1.14299 + 1.14300 + <sect1> 1.14301 + <title>The problem of many targets</title> 1.14302 + 1.14303 + <para id="x_160">The Linux kernel changes rapidly, and has never been 1.14304 + internally stable; developers frequently make drastic changes 1.14305 + between releases. This means that a version of the driver that 1.14306 + works well with a particular released version of the kernel will 1.14307 + not even <emphasis>compile</emphasis> correctly against, 1.14308 + typically, any other version.</para> 1.14309 + 1.14310 + <para id="x_161">To maintain a driver, we have to keep a number of distinct 1.14311 + versions of Linux in mind.</para> 1.14312 + <itemizedlist> 1.14313 + <listitem><para id="x_162">One target is the main Linux kernel development 1.14314 + tree. Maintenance of the code is in this case partly shared 1.14315 + by other developers in the kernel community, who make 1.14316 + <quote>drive-by</quote> modifications to the driver as they 1.14317 + develop and refine kernel subsystems.</para> 1.14318 + </listitem> 1.14319 + <listitem><para id="x_163">We also maintain a number of 1.14320 + <quote>backports</quote> to older versions of the Linux 1.14321 + kernel, to support the needs of customers who are running 1.14322 + older Linux distributions that do not incorporate our 1.14323 + drivers. (To <emphasis>backport</emphasis> a piece of code 1.14324 + is to modify it to work in an older version of its target 1.14325 + environment than the version it was developed for.)</para> 1.14326 + </listitem> 1.14327 + <listitem><para id="x_164">Finally, we make software releases on a schedule 1.14328 + that is necessarily not aligned with those used by Linux 1.14329 + distributors and kernel developers, so that we can deliver 1.14330 + new features to customers without forcing them to upgrade 1.14331 + their entire kernels or distributions.</para> 1.14332 + </listitem></itemizedlist> 1.14333 + 1.14334 + <sect2> 1.14335 + <title>Tempting approaches that don't work well</title> 1.14336 + 1.14337 + <para id="x_165">There are two <quote>standard</quote> ways to maintain a 1.14338 + piece of software that has to target many different 1.14339 + environments.</para> 1.14340 + 1.14341 + <para id="x_166">The first is to maintain a number of branches, each 1.14342 + intended for a single target. The trouble with this approach 1.14343 + is that you must maintain iron discipline in the flow of 1.14344 + changes between repositories. A new feature or bug fix must 1.14345 + start life in a <quote>pristine</quote> repository, then 1.14346 + percolate out to every backport repository. Backport changes 1.14347 + are more limited in the branches they should propagate to; a 1.14348 + backport change that is applied to a branch where it doesn't 1.14349 + belong will probably stop the driver from compiling.</para> 1.14350 + 1.14351 + <para id="x_167">The second is to maintain a single source tree filled with 1.14352 + conditional statements that turn chunks of code on or off 1.14353 + depending on the intended target. Because these 1.14354 + <quote>ifdefs</quote> are not allowed in the Linux kernel 1.14355 + tree, a manual or automatic process must be followed to strip 1.14356 + them out and yield a clean tree. A code base maintained in 1.14357 + this fashion rapidly becomes a rat's nest of conditional 1.14358 + blocks that are difficult to understand and maintain.</para> 1.14359 + 1.14360 + <para id="x_168">Neither of these approaches is well suited to a situation 1.14361 + where you don't <quote>own</quote> the canonical copy of a 1.14362 + source tree. In the case of a Linux driver that is 1.14363 + distributed with the standard kernel, Linus's tree contains 1.14364 + the copy of the code that will be treated by the world as 1.14365 + canonical. The upstream version of <quote>my</quote> driver 1.14366 + can be modified by people I don't know, without me even 1.14367 + finding out about it until after the changes show up in 1.14368 + Linus's tree.</para> 1.14369 + 1.14370 + <para id="x_169">These approaches have the added weakness of making it 1.14371 + difficult to generate well-formed patches to submit 1.14372 + upstream.</para> 1.14373 + 1.14374 + <para id="x_16a">In principle, Mercurial Queues seems like a good candidate 1.14375 + to manage a development scenario such as the above. While 1.14376 + this is indeed the case, MQ contains a few added features that 1.14377 + make the job more pleasant.</para> 1.14378 + 1.14379 + </sect2> 1.14380 + </sect1> 1.14381 + <sect1> 1.14382 + <title>Conditionally applying patches with guards</title> 1.14383 + 1.14384 + <para id="x_16b">Perhaps the best way to maintain sanity with so many targets 1.14385 + is to be able to choose specific patches to apply for a given 1.14386 + situation. MQ provides a feature called <quote>guards</quote> 1.14387 + (which originates with quilt's <literal moreinfo="none">guards</literal> 1.14388 + command) that does just this. To start off, let's create a 1.14389 + simple repository for experimenting in.</para> 1.14390 + 1.14391 + <!-- BEGIN mq.guards.init --> 1.14392 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> 1.14393 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew hello.patch</userinput> 1.14394 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello > hello</userinput> 1.14395 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add hello</userinput> 1.14396 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.14397 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew goodbye.patch</userinput> 1.14398 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye > goodbye</userinput> 1.14399 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add goodbye</userinput> 1.14400 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> 1.14401 +</screen> 1.14402 +<!-- END mq.guards.init --> 1.14403 + 1.14404 + 1.14405 + <para id="x_16c">This gives us a tiny repository that contains two patches 1.14406 + that don't have any dependencies on each other, because they 1.14407 + touch different files.</para> 1.14408 + 1.14409 + <para id="x_16d">The idea behind conditional application is that you can 1.14410 + <quote>tag</quote> a patch with a <emphasis>guard</emphasis>, 1.14411 + which is simply a text string of your choosing, then tell MQ to 1.14412 + select specific guards to use when applying patches. MQ will 1.14413 + then either apply, or skip over, a guarded patch, depending on 1.14414 + the guards that you have selected.</para> 1.14415 + 1.14416 + <para id="x_16e">A patch can have an arbitrary number of guards; each one is 1.14417 + <emphasis>positive</emphasis> (<quote>apply this patch if this 1.14418 + guard is selected</quote>) or <emphasis>negative</emphasis> 1.14419 + (<quote>skip this patch if this guard is selected</quote>). A 1.14420 + patch with no guards is always applied.</para> 1.14421 + 1.14422 + </sect1> 1.14423 + <sect1> 1.14424 + <title>Controlling the guards on a patch</title> 1.14425 + 1.14426 + <para id="x_16f">The <command role="hg-ext-mq" moreinfo="none">qguard</command> command lets 1.14427 + you determine which guards should apply to a patch, or display 1.14428 + the guards that are already in effect. Without any arguments, it 1.14429 + displays the guards on the current topmost patch.</para> 1.14430 + 1.14431 + <!-- BEGIN mq.guards.qguard --> 1.14432 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput> 1.14433 +goodbye.patch: unguarded 1.14434 +</screen> 1.14435 +<!-- END mq.guards.qguard --> 1.14436 + 1.14437 + 1.14438 + <para id="x_170">To set a positive guard on a patch, prefix the name of the 1.14439 + guard with a <quote><literal moreinfo="none">+</literal></quote>.</para> 1.14440 + 1.14441 + <!-- BEGIN mq.guards.qguard.pos --> 1.14442 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard +foo</userinput> 1.14443 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput> 1.14444 +goodbye.patch: +foo 1.14445 +</screen> 1.14446 +<!-- END mq.guards.qguard.pos --> 1.14447 + 1.14448 + 1.14449 + <para id="x_171">To set a negative guard 1.14450 + on a patch, prefix the name of the guard with a 1.14451 + <quote><literal moreinfo="none">-</literal></quote>.</para> 1.14452 + 1.14453 + <!-- BEGIN mq.guards.qguard.neg --> 1.14454 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard -- hello.patch -quux</userinput> 1.14455 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard hello.patch</userinput> 1.14456 +hello.patch: -quux 1.14457 +</screen> 1.14458 +<!-- END mq.guards.qguard.neg --> 1.14459 + 1.14460 + 1.14461 + <para id="x_74a">Notice that we prefixed the arguments to the <command moreinfo="none">hg 1.14462 + qguard</command> command with a <literal moreinfo="none">--</literal> here, so 1.14463 + that Mercurial would not interpret the text 1.14464 + <literal moreinfo="none">-quux</literal> as an option.</para> 1.14465 + 1.14466 + <note> 1.14467 + <title>Setting vs. modifying</title> 1.14468 + 1.14469 + <para id="x_172"> The <command role="hg-ext-mq" moreinfo="none">qguard</command> command 1.14470 + <emphasis>sets</emphasis> the guards on a patch; it doesn't 1.14471 + <emphasis>modify</emphasis> them. What this means is that if 1.14472 + you run <command role="hg-cmd" moreinfo="none">hg qguard +a +b</command> on a 1.14473 + patch, then <command role="hg-cmd" moreinfo="none">hg qguard +c</command> on 1.14474 + the same patch, the <emphasis>only</emphasis> guard that will 1.14475 + be set on it afterwards is <literal moreinfo="none">+c</literal>.</para> 1.14476 + </note> 1.14477 + 1.14478 + <para id="x_173">Mercurial stores guards in the <filename role="special" moreinfo="none">series</filename> file; the form in which they 1.14479 + are stored is easy both to understand and to edit by hand. (In 1.14480 + other words, you don't have to use the <command role="hg-ext-mq" moreinfo="none">qguard</command> command if you don't want 1.14481 + to; it's okay to simply edit the <filename role="special" moreinfo="none">series</filename> file.)</para> 1.14482 + 1.14483 + <!-- BEGIN mq.guards.series --> 1.14484 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/series</userinput> 1.14485 +hello.patch #-quux 1.14486 +goodbye.patch #+foo 1.14487 +</screen> 1.14488 +<!-- END mq.guards.series --> 1.14489 + 1.14490 + 1.14491 + </sect1> 1.14492 + <sect1> 1.14493 + <title>Selecting the guards to use</title> 1.14494 + 1.14495 + <para id="x_174">The <command role="hg-ext-mq" moreinfo="none">qselect</command> command 1.14496 + determines which guards are active at a given time. The effect 1.14497 + of this is to determine which patches MQ will apply the next 1.14498 + time you run <command role="hg-ext-mq" moreinfo="none">qpush</command>. It has 1.14499 + no other effect; in particular, it doesn't do anything to 1.14500 + patches that are already applied.</para> 1.14501 + 1.14502 + <para id="x_175">With no arguments, the <command role="hg-ext-mq" moreinfo="none">qselect</command> command lists the guards 1.14503 + currently in effect, one per line of output. Each argument is 1.14504 + treated as the name of a guard to apply.</para> 1.14505 + 1.14506 + <!-- BEGIN mq.guards.qselect.foo --> 1.14507 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> 1.14508 +patch queue now empty 1.14509 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput> 1.14510 +no active guards 1.14511 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo</userinput> 1.14512 +number of unguarded, unapplied patches has changed from 1 to 2 1.14513 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput> 1.14514 +foo 1.14515 +</screen> 1.14516 +<!-- END mq.guards.qselect.foo --> 1.14517 + 1.14518 + 1.14519 + <para id="x_176">In case you're interested, the currently selected guards are 1.14520 + stored in the <filename role="special" moreinfo="none">guards</filename> file.</para> 1.14521 + 1.14522 + <!-- BEGIN mq.guards.qselect.cat --> 1.14523 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/guards</userinput> 1.14524 +foo 1.14525 +</screen> 1.14526 +<!-- END mq.guards.qselect.cat --> 1.14527 + 1.14528 + 1.14529 + <para id="x_177">We can see the effect the selected guards have when we run 1.14530 + <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para> 1.14531 + 1.14532 + <!-- BEGIN mq.guards.qselect.qpush --> 1.14533 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> 1.14534 +applying hello.patch 1.14535 +applying goodbye.patch 1.14536 +now at: goodbye.patch 1.14537 +</screen> 1.14538 +<!-- END mq.guards.qselect.qpush --> 1.14539 + 1.14540 + 1.14541 + <para id="x_178">A guard cannot start with a 1.14542 + <quote><literal moreinfo="none">+</literal></quote> or 1.14543 + <quote><literal moreinfo="none">-</literal></quote> character. The name of a 1.14544 + guard must not contain white space, but most other characters 1.14545 + are acceptable. If you try to use a guard with an invalid name, 1.14546 + MQ will complain:</para> 1.14547 + 1.14548 + <!-- BEGIN mq.guards.qselect.error --> 1.14549 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect +foo</userinput> 1.14550 +abort: guard '+foo' starts with invalid character: '+' 1.14551 +</screen> 1.14552 +<!-- END mq.guards.qselect.error --> 1.14553 + 1.14554 + 1.14555 + <para id="x_179">Changing the selected guards changes the patches that are 1.14556 + applied.</para> 1.14557 + 1.14558 + <!-- BEGIN mq.guards.qselect.quux --> 1.14559 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect quux</userinput> 1.14560 +number of guarded, applied patches has changed from 0 to 2 1.14561 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> 1.14562 +patch queue now empty 1.14563 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> 1.14564 +patch series already fully applied 1.14565 +</screen> 1.14566 +<!-- END mq.guards.qselect.quux --> 1.14567 + 1.14568 + 1.14569 + <para id="x_17a">You can see in the example below that negative guards take 1.14570 + precedence over positive guards.</para> 1.14571 + 1.14572 + <!-- BEGIN mq.guards.qselect.foobar --> 1.14573 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo bar</userinput> 1.14574 +number of unguarded, unapplied patches has changed from 0 to 2 1.14575 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> 1.14576 +no patches applied 1.14577 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> 1.14578 +applying hello.patch 1.14579 +applying goodbye.patch 1.14580 +now at: goodbye.patch 1.14581 +</screen> 1.14582 +<!-- END mq.guards.qselect.foobar --> 1.14583 + 1.14584 + 1.14585 + </sect1> 1.14586 + <sect1> 1.14587 + <title>MQ's rules for applying patches</title> 1.14588 + 1.14589 + <para id="x_17b">The rules that MQ uses when deciding whether to apply a 1.14590 + patch are as follows.</para> 1.14591 + <itemizedlist> 1.14592 + <listitem><para id="x_17c">A patch that has no guards is always 1.14593 + applied.</para> 1.14594 + </listitem> 1.14595 + <listitem><para id="x_17d">If the patch has any negative guard that matches 1.14596 + any currently selected guard, the patch is skipped.</para> 1.14597 + </listitem> 1.14598 + <listitem><para id="x_17e">If the patch has any positive guard that matches 1.14599 + any currently selected guard, the patch is applied.</para> 1.14600 + </listitem> 1.14601 + <listitem><para id="x_17f">If the patch has positive or negative guards, 1.14602 + but none matches any currently selected guard, the patch is 1.14603 + skipped.</para> 1.14604 + </listitem></itemizedlist> 1.14605 + 1.14606 + </sect1> 1.14607 + <sect1> 1.14608 + <title>Trimming the work environment</title> 1.14609 + 1.14610 + <para id="x_180">In working on the device driver I mentioned earlier, I don't 1.14611 + apply the patches to a normal Linux kernel tree. Instead, I use 1.14612 + a repository that contains only a snapshot of the source files 1.14613 + and headers that are relevant to Infiniband development. This 1.14614 + repository is 1% the size of a kernel repository, so it's easier 1.14615 + to work with.</para> 1.14616 + 1.14617 + <para id="x_181">I then choose a <quote>base</quote> version on top of which 1.14618 + the patches are applied. This is a snapshot of the Linux kernel 1.14619 + tree as of a revision of my choosing. When I take the snapshot, 1.14620 + I record the changeset ID from the kernel repository in the 1.14621 + commit message. Since the snapshot preserves the 1.14622 + <quote>shape</quote> and content of the relevant parts of the 1.14623 + kernel tree, I can apply my patches on top of either my tiny 1.14624 + repository or a normal kernel tree.</para> 1.14625 + 1.14626 + <para id="x_182">Normally, the base tree atop which the patches apply should 1.14627 + be a snapshot of a very recent upstream tree. This best 1.14628 + facilitates the development of patches that can easily be 1.14629 + submitted upstream with few or no modifications.</para> 1.14630 + 1.14631 + </sect1> 1.14632 + <sect1> 1.14633 + <title>Dividing up the <filename role="special" moreinfo="none">series</filename> 1.14634 + file</title> 1.14635 + 1.14636 + <para id="x_183">I categorise the patches in the <filename role="special" moreinfo="none">series</filename> file into a number of logical 1.14637 + groups. Each section of like patches begins with a block of 1.14638 + comments that describes the purpose of the patches that 1.14639 + follow.</para> 1.14640 + 1.14641 + <para id="x_184">The sequence of patch groups that I maintain follows. The 1.14642 + ordering of these groups is important; I'll describe why after I 1.14643 + introduce the groups.</para> 1.14644 + <itemizedlist> 1.14645 + <listitem><para id="x_185">The <quote>accepted</quote> group. Patches that 1.14646 + the development team has submitted to the maintainer of the 1.14647 + Infiniband subsystem, and which he has accepted, but which 1.14648 + are not present in the snapshot that the tiny repository is 1.14649 + based on. These are <quote>read only</quote> patches, 1.14650 + present only to transform the tree into a similar state as 1.14651 + it is in the upstream maintainer's repository.</para> 1.14652 + </listitem> 1.14653 + <listitem><para id="x_186">The <quote>rework</quote> group. Patches that I 1.14654 + have submitted, but that the upstream maintainer has 1.14655 + requested modifications to before he will accept 1.14656 + them.</para> 1.14657 + </listitem> 1.14658 + <listitem><para id="x_187">The <quote>pending</quote> group. Patches that 1.14659 + I have not yet submitted to the upstream maintainer, but 1.14660 + which we have finished working on. These will be <quote>read 1.14661 + only</quote> for a while. If the upstream maintainer 1.14662 + accepts them upon submission, I'll move them to the end of 1.14663 + the <quote>accepted</quote> group. If he requests that I 1.14664 + modify any, I'll move them to the beginning of the 1.14665 + <quote>rework</quote> group.</para> 1.14666 + </listitem> 1.14667 + <listitem><para id="x_188">The <quote>in progress</quote> group. Patches 1.14668 + that are actively being developed, and should not be 1.14669 + submitted anywhere yet.</para> 1.14670 + </listitem> 1.14671 + <listitem><para id="x_189">The <quote>backport</quote> group. Patches that 1.14672 + adapt the source tree to older versions of the kernel 1.14673 + tree.</para> 1.14674 + </listitem> 1.14675 + <listitem><para id="x_18a">The <quote>do not ship</quote> group. Patches 1.14676 + that for some reason should never be submitted upstream. 1.14677 + For example, one such patch might change embedded driver 1.14678 + identification strings to make it easier to distinguish, in 1.14679 + the field, between an out-of-tree version of the driver and 1.14680 + a version shipped by a distribution vendor.</para> 1.14681 + </listitem></itemizedlist> 1.14682 + 1.14683 + <para id="x_18b">Now to return to the reasons for ordering groups of patches 1.14684 + in this way. We would like the lowest patches in the stack to 1.14685 + be as stable as possible, so that we will not need to rework 1.14686 + higher patches due to changes in context. Putting patches that 1.14687 + will never be changed first in the <filename role="special" moreinfo="none">series</filename> file serves this 1.14688 + purpose.</para> 1.14689 + 1.14690 + <para id="x_18c">We would also like the patches that we know we'll need to 1.14691 + modify to be applied on top of a source tree that resembles the 1.14692 + upstream tree as closely as possible. This is why we keep 1.14693 + accepted patches around for a while.</para> 1.14694 + 1.14695 + <para id="x_18d">The <quote>backport</quote> and <quote>do not ship</quote> 1.14696 + patches float at the end of the <filename role="special" moreinfo="none">series</filename> file. The backport patches 1.14697 + must be applied on top of all other patches, and the <quote>do 1.14698 + not ship</quote> patches might as well stay out of harm's 1.14699 + way.</para> 1.14700 + 1.14701 + </sect1> 1.14702 + <sect1> 1.14703 + <title>Maintaining the patch series</title> 1.14704 + 1.14705 + <para id="x_18e">In my work, I use a number of guards to control which 1.14706 + patches are to be applied.</para> 1.14707 + 1.14708 + <itemizedlist> 1.14709 + <listitem><para id="x_18f"><quote>Accepted</quote> patches are guarded with 1.14710 + <literal moreinfo="none">accepted</literal>. I enable this guard most of 1.14711 + the time. When I'm applying the patches on top of a tree 1.14712 + where the patches are already present, I can turn this patch 1.14713 + off, and the patches that follow it will apply 1.14714 + cleanly.</para> 1.14715 + </listitem> 1.14716 + <listitem><para id="x_190">Patches that are <quote>finished</quote>, but 1.14717 + not yet submitted, have no guards. If I'm applying the 1.14718 + patch stack to a copy of the upstream tree, I don't need to 1.14719 + enable any guards in order to get a reasonably safe source 1.14720 + tree.</para> 1.14721 + </listitem> 1.14722 + <listitem><para id="x_191">Those patches that need reworking before being 1.14723 + resubmitted are guarded with 1.14724 + <literal moreinfo="none">rework</literal>.</para> 1.14725 + </listitem> 1.14726 + <listitem><para id="x_192">For those patches that are still under 1.14727 + development, I use <literal moreinfo="none">devel</literal>.</para> 1.14728 + </listitem> 1.14729 + <listitem><para id="x_193">A backport patch may have several guards, one 1.14730 + for each version of the kernel to which it applies. For 1.14731 + example, a patch that backports a piece of code to 2.6.9 1.14732 + will have a <literal moreinfo="none">2.6.9</literal> guard.</para> 1.14733 + </listitem></itemizedlist> 1.14734 + <para id="x_194">This variety of guards gives me considerable flexibility in 1.14735 + determining what kind of source tree I want to end up with. For 1.14736 + most situations, the selection of appropriate guards is 1.14737 + automated during the build process, but I can manually tune the 1.14738 + guards to use for less common circumstances.</para> 1.14739 + 1.14740 + <sect2> 1.14741 + <title>The art of writing backport patches</title> 1.14742 + 1.14743 + <para id="x_195">Using MQ, writing a backport patch is a simple process. 1.14744 + All such a patch has to do is modify a piece of code that uses 1.14745 + a kernel feature not present in the older version of the 1.14746 + kernel, so that the driver continues to work correctly under 1.14747 + that older version.</para> 1.14748 + 1.14749 + <para id="x_196">A useful goal when writing a good backport patch is to 1.14750 + make your code look as if it was written for the older version 1.14751 + of the kernel you're targeting. The less obtrusive the patch, 1.14752 + the easier it will be to understand and maintain. If you're 1.14753 + writing a collection of backport patches to avoid the 1.14754 + <quote>rat's nest</quote> effect of lots of 1.14755 + <literal moreinfo="none">#ifdef</literal>s (hunks of source code that are only 1.14756 + used conditionally) in your code, don't introduce 1.14757 + version-dependent <literal moreinfo="none">#ifdef</literal>s into the patches. 1.14758 + Instead, write several patches, each of which makes 1.14759 + unconditional changes, and control their application using 1.14760 + guards.</para> 1.14761 + 1.14762 + <para id="x_197">There are two reasons to divide backport patches into a 1.14763 + distinct group, away from the <quote>regular</quote> patches 1.14764 + whose effects they modify. The first is that intermingling the 1.14765 + two makes it more difficult to use a tool like the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension to automate the 1.14766 + process of submitting the patches to an upstream maintainer. 1.14767 + The second is that a backport patch could perturb the context 1.14768 + in which a subsequent regular patch is applied, making it 1.14769 + impossible to apply the regular patch cleanly 1.14770 + <emphasis>without</emphasis> the earlier backport patch 1.14771 + already being applied.</para> 1.14772 + 1.14773 + </sect2> 1.14774 + </sect1> 1.14775 + <sect1> 1.14776 + <title>Useful tips for developing with MQ</title> 1.14777 + 1.14778 + <sect2> 1.14779 + <title>Organising patches in directories</title> 1.14780 + 1.14781 + <para id="x_198">If you're working on a substantial project with MQ, it's 1.14782 + not difficult to accumulate a large number of patches. For 1.14783 + example, I have one patch repository that contains over 250 1.14784 + patches.</para> 1.14785 + 1.14786 + <para id="x_199">If you can group these patches into separate logical 1.14787 + categories, you can if you like store them in different 1.14788 + directories; MQ has no problems with patch names that contain 1.14789 + path separators.</para> 1.14790 + 1.14791 + </sect2> 1.14792 + <sect2 id="mq-collab:tips:interdiff"> 1.14793 + <title>Viewing the history of a patch</title> 1.14794 + 1.14795 + <para id="x_19a">If you're developing a set of patches over a long time, 1.14796 + it's a good idea to maintain them in a repository, as 1.14797 + discussed in <xref linkend="sec:mq:repo"/>. If you do 1.14798 + so, you'll quickly 1.14799 + discover that using the <command role="hg-cmd" moreinfo="none">hg 1.14800 + diff</command> command to look at the history of changes to 1.14801 + a patch is unworkable. This is in part because you're looking 1.14802 + at the second derivative of the real code (a diff of a diff), 1.14803 + but also because MQ adds noise to the process by modifying 1.14804 + time stamps and directory names when it updates a 1.14805 + patch.</para> 1.14806 + 1.14807 + <para id="x_19b">However, you can use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension, which is bundled 1.14808 + with Mercurial, to turn a diff of two versions of a patch into 1.14809 + something readable. To do this, you will need a third-party 1.14810 + package called <literal role="package" moreinfo="none">patchutils</literal> 1.14811 + <citation>web:patchutils</citation>. This provides a command 1.14812 + named <command moreinfo="none">interdiff</command>, which shows the 1.14813 + differences between two diffs as a diff. Used on two versions 1.14814 + of the same diff, it generates a diff that represents the diff 1.14815 + from the first to the second version.</para> 1.14816 + 1.14817 + <para id="x_19c">You can enable the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension in the usual way, 1.14818 + by adding a line to the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your 1.14819 + <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> 1.14820 + <programlisting format="linespecific">[extensions] 1.14821 +extdiff =</programlisting> 1.14822 + <para id="x_19d">The <command moreinfo="none">interdiff</command> command expects to be 1.14823 + passed the names of two files, but the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension passes the program 1.14824 + it runs a pair of directories, each of which can contain an 1.14825 + arbitrary number of files. We thus need a small program that 1.14826 + will run <command moreinfo="none">interdiff</command> on each pair of files in 1.14827 + 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 1.14828 + source code repository that accompanies this book. <!-- 1.14829 + &example.hg-interdiff; --></para> 1.14830 + 1.14831 + <para id="x_19e">With the <filename role="special" moreinfo="none">hg-interdiff</filename> 1.14832 + program in your shell's search path, you can run it as 1.14833 + follows, from inside an MQ patch directory:</para> 1.14834 + <programlisting format="linespecific">hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting> 1.14835 + <para id="x_19f">Since you'll probably want to use this long-winded command 1.14836 + a lot, you can get <literal role="hg-ext" moreinfo="none">hgext</literal> to 1.14837 + make it available as a normal Mercurial command, again by 1.14838 + editing your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> 1.14839 + <programlisting format="linespecific">[extdiff] 1.14840 +cmd.interdiff = hg-interdiff</programlisting> 1.14841 + <para id="x_1a0">This directs <literal role="hg-ext" moreinfo="none">hgext</literal> to 1.14842 + make an <literal moreinfo="none">interdiff</literal> command available, so you 1.14843 + can now shorten the previous invocation of <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> to something a 1.14844 + little more wieldy.</para> 1.14845 + <programlisting format="linespecific">hg interdiff -r A:B my-change.patch</programlisting> 1.14846 + 1.14847 + <note> 1.14848 + <para id="x_1a1"> The <command moreinfo="none">interdiff</command> command works well 1.14849 + only if the underlying files against which versions of a 1.14850 + patch are generated remain the same. If you create a patch, 1.14851 + modify the underlying files, and then regenerate the patch, 1.14852 + <command moreinfo="none">interdiff</command> may not produce useful 1.14853 + output.</para> 1.14854 + </note> 1.14855 + 1.14856 + <para id="x_1a2">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is 1.14857 + useful for more than merely improving the presentation of MQ 1.14858 + patches. To read more about it, go to <xref linkend="sec:hgext:extdiff"/>.</para> 1.14859 + 1.14860 + </sect2> 1.14861 + </sect1> 1.14862 +</chapter> 1.14863 + 1.14864 +<!-- 1.14865 +local variables: 1.14866 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.14867 +end: 1.14868 +--> 1.14869 + 1.14870 + <!-- BEGIN ch14 --> 1.14871 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.14872 + 1.14873 +<chapter id="chap:hgext"> 1.14874 + <?dbhtml filename="adding-functionality-with-extensions.html"?> 1.14875 + <title>Adding functionality with extensions</title> 1.14876 + 1.14877 + <para id="x_4fe">While the core of Mercurial is quite complete from a 1.14878 + functionality standpoint, it's deliberately shorn of fancy 1.14879 + features. This approach of preserving simplicity keeps the 1.14880 + software easy to deal with for both maintainers and users.</para> 1.14881 + 1.14882 + <para id="x_4ff">However, Mercurial doesn't box you in with an inflexible 1.14883 + command set: you can add features to it as 1.14884 + <emphasis>extensions</emphasis> (sometimes known as 1.14885 + <emphasis>plugins</emphasis>). We've already discussed a few of 1.14886 + these extensions in earlier chapters.</para> 1.14887 + <itemizedlist> 1.14888 + <listitem><para id="x_500"><xref linkend="sec:tour-merge:fetch"/> 1.14889 + covers the <literal role="hg-ext" moreinfo="none">fetch</literal> extension; 1.14890 + this combines pulling new changes and merging them with local 1.14891 + changes into a single command, <command role="hg-ext-fetch" moreinfo="none">fetch</command>.</para> 1.14892 + </listitem> 1.14893 + <listitem><para id="x_501">In <xref linkend="chap:hook"/>, we covered 1.14894 + several extensions that are useful for hook-related 1.14895 + functionality: <literal role="hg-ext" moreinfo="none">acl</literal> adds 1.14896 + access control lists; <literal role="hg-ext" moreinfo="none">bugzilla</literal> adds integration with the 1.14897 + Bugzilla bug tracking system; and <literal role="hg-ext" moreinfo="none">notify</literal> sends notification emails on 1.14898 + new changes.</para> 1.14899 + </listitem> 1.14900 + <listitem><para id="x_502">The Mercurial Queues patch management extension is 1.14901 + so invaluable that it merits two chapters and an appendix all 1.14902 + to itself. <xref linkend="chap:mq"/> covers the 1.14903 + basics; <xref linkend="chap:mq-collab"/> discusses advanced topics; 1.14904 + and <xref linkend="chap:mqref"/> goes into detail on 1.14905 + each 1.14906 + command.</para> 1.14907 + </listitem></itemizedlist> 1.14908 + 1.14909 + <para id="x_503">In this chapter, we'll cover some of the other extensions that 1.14910 + are available for Mercurial, and briefly touch on some of the 1.14911 + machinery you'll need to know about if you want to write an 1.14912 + extension of your own.</para> 1.14913 + <itemizedlist> 1.14914 + <listitem><para id="x_504">In <xref linkend="sec:hgext:inotify"/>, 1.14915 + we'll discuss the possibility of <emphasis>huge</emphasis> 1.14916 + performance improvements using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension.</para> 1.14917 + </listitem></itemizedlist> 1.14918 + 1.14919 + <sect1 id="sec:hgext:inotify"> 1.14920 + <title>Improve performance with the <literal role="hg-ext" moreinfo="none">inotify</literal> extension</title> 1.14921 + 1.14922 + <para id="x_505">Are you interested in having some of the most common 1.14923 + Mercurial operations run as much as a hundred times faster? 1.14924 + Read on!</para> 1.14925 + 1.14926 + <para id="x_506">Mercurial has great performance under normal circumstances. 1.14927 + For example, when you run the <command role="hg-cmd" moreinfo="none">hg 1.14928 + status</command> command, Mercurial has to scan almost every 1.14929 + directory and file in your repository so that it can display 1.14930 + file status. Many other Mercurial commands need to do the same 1.14931 + work behind the scenes; for example, the <command role="hg-cmd" moreinfo="none">hg diff</command> command uses the status 1.14932 + machinery to avoid doing an expensive comparison operation on 1.14933 + files that obviously haven't changed.</para> 1.14934 + 1.14935 + <para id="x_507">Because obtaining file status is crucial to good 1.14936 + performance, the authors of Mercurial have optimised this code 1.14937 + to within an inch of its life. However, there's no avoiding the 1.14938 + fact that when you run <command role="hg-cmd" moreinfo="none">hg 1.14939 + status</command>, Mercurial is going to have to perform at 1.14940 + least one expensive system call for each managed file to 1.14941 + determine whether it's changed since the last time Mercurial 1.14942 + checked. For a sufficiently large repository, this can take a 1.14943 + long time.</para> 1.14944 + 1.14945 + <para id="x_508">To put a number on the magnitude of this effect, I created a 1.14946 + repository containing 150,000 managed files. I timed <command role="hg-cmd" moreinfo="none">hg status</command> as taking ten seconds to 1.14947 + run, even when <emphasis>none</emphasis> of those files had been 1.14948 + modified.</para> 1.14949 + 1.14950 + <para id="x_509">Many modern operating systems contain a file notification 1.14951 + facility. If a program signs up to an appropriate service, the 1.14952 + operating system will notify it every time a file of interest is 1.14953 + created, modified, or deleted. On Linux systems, the kernel 1.14954 + component that does this is called 1.14955 + <literal moreinfo="none">inotify</literal>.</para> 1.14956 + 1.14957 + <para id="x_50a">Mercurial's <literal role="hg-ext" moreinfo="none">inotify</literal> 1.14958 + extension talks to the kernel's <literal moreinfo="none">inotify</literal> 1.14959 + component to optimise <command role="hg-cmd" moreinfo="none">hg status</command> 1.14960 + commands. The extension has two components. A daemon sits in 1.14961 + the background and receives notifications from the 1.14962 + <literal moreinfo="none">inotify</literal> subsystem. It also listens for 1.14963 + connections from a regular Mercurial command. The extension 1.14964 + modifies Mercurial's behavior so that instead of scanning the 1.14965 + filesystem, it queries the daemon. Since the daemon has perfect 1.14966 + information about the state of the repository, it can respond 1.14967 + with a result instantaneously, avoiding the need to scan every 1.14968 + directory and file in the repository.</para> 1.14969 + 1.14970 + <para id="x_50b">Recall the ten seconds that I measured plain Mercurial as 1.14971 + taking to run <command role="hg-cmd" moreinfo="none">hg status</command> on a 1.14972 + 150,000 file repository. With the <literal role="hg-ext" moreinfo="none">inotify</literal> extension enabled, the time 1.14973 + dropped to 0.1 seconds, a factor of <emphasis>one 1.14974 + hundred</emphasis> faster.</para> 1.14975 + 1.14976 + <para id="x_50c">Before we continue, please pay attention to some 1.14977 + caveats.</para> 1.14978 + <itemizedlist> 1.14979 + <listitem><para id="x_50d">The <literal role="hg-ext" moreinfo="none">inotify</literal> 1.14980 + extension is Linux-specific. Because it interfaces directly 1.14981 + to the Linux kernel's <literal moreinfo="none">inotify</literal> subsystem, 1.14982 + it does not work on other operating systems.</para> 1.14983 + </listitem> 1.14984 + <listitem><para id="x_50e">It should work on any Linux distribution that 1.14985 + was released after early 2005. Older distributions are 1.14986 + likely to have a kernel that lacks 1.14987 + <literal moreinfo="none">inotify</literal>, or a version of 1.14988 + <literal moreinfo="none">glibc</literal> that does not have the necessary 1.14989 + interfacing support.</para> 1.14990 + </listitem> 1.14991 + <listitem><para id="x_50f">Not all filesystems are suitable for use with 1.14992 + the <literal role="hg-ext" moreinfo="none">inotify</literal> extension. 1.14993 + Network filesystems such as NFS are a non-starter, for 1.14994 + example, particularly if you're running Mercurial on several 1.14995 + systems, all mounting the same network filesystem. The 1.14996 + kernel's <literal moreinfo="none">inotify</literal> system has no way of 1.14997 + knowing about changes made on another system. Most local 1.14998 + filesystems (e.g. ext3, XFS, ReiserFS) should work 1.14999 + fine.</para> 1.15000 + </listitem></itemizedlist> 1.15001 + 1.15002 + <para id="x_510">The <literal role="hg-ext" moreinfo="none">inotify</literal> extension is 1.15003 + not yet shipped with Mercurial as of May 2007, so it's a little 1.15004 + more involved to set up than other extensions. But the 1.15005 + performance improvement is worth it!</para> 1.15006 + 1.15007 + <para id="x_511">The extension currently comes in two parts: a set of patches 1.15008 + to the Mercurial source code, and a library of Python bindings 1.15009 + to the <literal moreinfo="none">inotify</literal> subsystem.</para> 1.15010 + <note> 1.15011 + <para id="x_512"> There are <emphasis>two</emphasis> Python 1.15012 + <literal moreinfo="none">inotify</literal> binding libraries. One of them is 1.15013 + called <literal moreinfo="none">pyinotify</literal>, and is packaged by some 1.15014 + Linux distributions as <literal moreinfo="none">python-inotify</literal>. 1.15015 + This is <emphasis>not</emphasis> the one you'll need, as it is 1.15016 + too buggy and inefficient to be practical.</para> 1.15017 + </note> 1.15018 + <para id="x_513">To get going, it's best to already have a functioning copy 1.15019 + of Mercurial installed.</para> 1.15020 + <note> 1.15021 + <para id="x_514"> If you follow the instructions below, you'll be 1.15022 + <emphasis>replacing</emphasis> and overwriting any existing 1.15023 + installation of Mercurial that you might already have, using 1.15024 + the latest <quote>bleeding edge</quote> Mercurial code. Don't 1.15025 + say you weren't warned!</para> 1.15026 + </note> 1.15027 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.15028 + <listitem><para id="x_515">Clone the Python <literal moreinfo="none">inotify</literal> 1.15029 + binding repository. Build and install it.</para> 1.15030 + <programlisting format="linespecific">hg clone http://hg.kublai.com/python/inotify 1.15031 +cd inotify 1.15032 +python setup.py build --force 1.15033 +sudo python setup.py install --skip-build</programlisting> 1.15034 + </listitem> 1.15035 + <listitem><para id="x_516">Clone the <filename class="directory" moreinfo="none">crew</filename> Mercurial repository. 1.15036 + Clone the <literal role="hg-ext" moreinfo="none">inotify</literal> patch 1.15037 + repository so that Mercurial Queues will be able to apply 1.15038 + patches to your cope of the <filename class="directory" moreinfo="none">crew</filename> repository.</para> 1.15039 + <programlisting format="linespecific">hg clone http://hg.intevation.org/mercurial/crew 1.15040 +hg clone crew inotify 1.15041 +hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting> 1.15042 + </listitem> 1.15043 + <listitem><para id="x_517">Make sure that you have the Mercurial Queues 1.15044 + extension, <literal role="hg-ext" moreinfo="none">mq</literal>, enabled. If 1.15045 + you've never used MQ, read <xref linkend="sec:mq:start"/> to get started 1.15046 + quickly.</para> 1.15047 + </listitem> 1.15048 + <listitem><para id="x_518">Go into the <filename class="directory" moreinfo="none">inotify</filename> repo, and apply all 1.15049 + of the <literal role="hg-ext" moreinfo="none">inotify</literal> patches 1.15050 + using the <option role="hg-ext-mq-cmd-qpush-opt">hg 1.15051 + -a</option> option to the <command role="hg-ext-mq" moreinfo="none">qpush</command> command.</para> 1.15052 + <programlisting format="linespecific">cd inotify 1.15053 +hg qpush -a</programlisting> 1.15054 + </listitem> 1.15055 + <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. 1.15056 + Instead, ask for help.</para> 1.15057 + </listitem> 1.15058 + <listitem><para id="x_51a">Build and install the patched version of 1.15059 + Mercurial.</para> 1.15060 + <programlisting format="linespecific">python setup.py build --force 1.15061 +sudo python setup.py install --skip-build</programlisting> 1.15062 + </listitem> 1.15063 + </orderedlist> 1.15064 + <para id="x_51b">Once you've build a suitably patched version of Mercurial, 1.15065 + all you need to do to enable the <literal role="hg-ext" moreinfo="none">inotify</literal> extension is add an entry to 1.15066 + your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> 1.15067 + <programlisting format="linespecific">[extensions] inotify =</programlisting> 1.15068 + <para id="x_51c">When the <literal role="hg-ext" moreinfo="none">inotify</literal> extension 1.15069 + is enabled, Mercurial will automatically and transparently start 1.15070 + the status daemon the first time you run a command that needs 1.15071 + status in a repository. It runs one status daemon per 1.15072 + repository.</para> 1.15073 + 1.15074 + <para id="x_51d">The status daemon is started silently, and runs in the 1.15075 + background. If you look at a list of running processes after 1.15076 + you've enabled the <literal role="hg-ext" moreinfo="none">inotify</literal> 1.15077 + extension and run a few commands in different repositories, 1.15078 + you'll thus see a few <literal moreinfo="none">hg</literal> processes sitting 1.15079 + around, waiting for updates from the kernel and queries from 1.15080 + Mercurial.</para> 1.15081 + 1.15082 + <para id="x_51e">The first time you run a Mercurial command in a repository 1.15083 + when you have the <literal role="hg-ext" moreinfo="none">inotify</literal> 1.15084 + extension enabled, it will run with about the same performance 1.15085 + as a normal Mercurial command. This is because the status 1.15086 + daemon needs to perform a normal status scan so that it has a 1.15087 + baseline against which to apply later updates from the kernel. 1.15088 + However, <emphasis>every</emphasis> subsequent command that does 1.15089 + any kind of status check should be noticeably faster on 1.15090 + repositories of even fairly modest size. Better yet, the bigger 1.15091 + your repository is, the greater a performance advantage you'll 1.15092 + see. The <literal role="hg-ext" moreinfo="none">inotify</literal> daemon makes 1.15093 + status operations almost instantaneous on repositories of all 1.15094 + sizes!</para> 1.15095 + 1.15096 + <para id="x_51f">If you like, you can manually start a status daemon using 1.15097 + the <command role="hg-ext-inotify" moreinfo="none">inserve</command> command. 1.15098 + This gives you slightly finer control over how the daemon ought 1.15099 + to run. This command will of course only be available when the 1.15100 + <literal role="hg-ext" moreinfo="none">inotify</literal> extension is 1.15101 + enabled.</para> 1.15102 + 1.15103 + <para id="x_520">When you're using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension, you should notice 1.15104 + <emphasis>no difference at all</emphasis> in Mercurial's 1.15105 + behavior, with the sole exception of status-related commands 1.15106 + running a whole lot faster than they used to. You should 1.15107 + specifically expect that commands will not print different 1.15108 + output; neither should they give different results. If either of 1.15109 + these situations occurs, please report a bug.</para> 1.15110 + 1.15111 + </sect1> 1.15112 + <sect1 id="sec:hgext:extdiff"> 1.15113 + <title>Flexible diff support with the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension</title> 1.15114 + 1.15115 + <para id="x_521">Mercurial's built-in <command role="hg-cmd" moreinfo="none">hg 1.15116 + diff</command> command outputs plaintext unified diffs.</para> 1.15117 + 1.15118 + <!-- BEGIN extdiff.diff --> 1.15119 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> 1.15120 +diff -r 801b35c37d8b myfile 1.15121 +--- a/myfile Sun Aug 16 14:05:02 2009 +0000 1.15122 ++++ b/myfile Sun Aug 16 14:05:02 2009 +0000 1.15123 +@@ -1,1 +1,2 @@ 1.15124 + The first line. 1.15125 ++The second line. 1.15126 +</screen> 1.15127 +<!-- END extdiff.diff --> 1.15128 + 1.15129 + 1.15130 + <para id="x_522">If you would like to use an external tool to display 1.15131 + modifications, you'll want to use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension. This will let you 1.15132 + use, for example, a graphical diff tool.</para> 1.15133 + 1.15134 + <para id="x_523">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is 1.15135 + bundled with Mercurial, so it's easy to set up. In the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your 1.15136 + <filename role="special" moreinfo="none">~/.hgrc</filename>, simply add a 1.15137 + one-line entry to enable the extension.</para> 1.15138 + <programlisting format="linespecific">[extensions] 1.15139 +extdiff =</programlisting> 1.15140 + <para id="x_524">This introduces a command named <command role="hg-ext-extdiff" moreinfo="none">extdiff</command>, which by default uses 1.15141 + your system's <command moreinfo="none">diff</command> command to generate a 1.15142 + unified diff in the same form as the built-in <command role="hg-cmd" moreinfo="none">hg diff</command> command.</para> 1.15143 + 1.15144 + <!-- BEGIN extdiff.extdiff --> 1.15145 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff</userinput> 1.15146 +--- a.801b35c37d8b/myfile 2009-08-16 14:05:02.000000000 +0000 1.15147 ++++ /tmp/extdiffl1y_s9/a/myfile 2009-08-16 14:05:02.000000000 +0000 1.15148 +@@ -1 +1,2 @@ 1.15149 + The first line. 1.15150 ++The second line. 1.15151 +</screen> 1.15152 +<!-- END extdiff.extdiff --> 1.15153 + 1.15154 + 1.15155 + <para id="x_525">The result won't be exactly the same as with the built-in 1.15156 + <command role="hg-cmd" moreinfo="none">hg diff</command> variations, because the 1.15157 + output of <command moreinfo="none">diff</command> varies from one system to 1.15158 + another, even when passed the same options.</para> 1.15159 + 1.15160 + <para id="x_526">As the <quote><literal moreinfo="none">making snapshot</literal></quote> 1.15161 + lines of output above imply, the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command works by 1.15162 + creating two snapshots of your source tree. The first snapshot 1.15163 + is of the source revision; the second, of the target revision or 1.15164 + working directory. The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command generates 1.15165 + these snapshots in a temporary directory, passes the name of 1.15166 + each directory to an external diff viewer, then deletes the 1.15167 + temporary directory. For efficiency, it only snapshots the 1.15168 + directories and files that have changed between the two 1.15169 + revisions.</para> 1.15170 + 1.15171 + <para id="x_527">Snapshot directory names have the same base name as your 1.15172 + 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 1.15173 + snapshot directory. Each snapshot directory name has its 1.15174 + changeset ID appended, if appropriate. If a snapshot is of 1.15175 + revision <literal moreinfo="none">a631aca1083f</literal>, the directory will be 1.15176 + named <filename class="directory" moreinfo="none">foo.a631aca1083f</filename>. 1.15177 + A snapshot of the working directory won't have a changeset ID 1.15178 + appended, so it would just be <filename class="directory" moreinfo="none">foo</filename> in this example. To see what 1.15179 + this looks like in practice, look again at the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> example above. Notice 1.15180 + that the diff has the snapshot directory names embedded in its 1.15181 + header.</para> 1.15182 + 1.15183 + <para id="x_528">The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command 1.15184 + accepts two important options. The <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option 1.15185 + lets you choose a program to view differences with, instead of 1.15186 + <command moreinfo="none">diff</command>. With the <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option, 1.15187 + you can change the options that <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> passes to the program 1.15188 + (by default, these options are 1.15189 + <quote><literal moreinfo="none">-Npru</literal></quote>, which only make sense 1.15190 + if you're running <command moreinfo="none">diff</command>). In other respects, 1.15191 + the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command 1.15192 + acts similarly to the built-in <command role="hg-cmd" moreinfo="none">hg 1.15193 + diff</command> command: you use the same option names, syntax, 1.15194 + and arguments to specify the revisions you want, the files you 1.15195 + want, and so on.</para> 1.15196 + 1.15197 + <para id="x_529">As an example, here's how to run the normal system 1.15198 + <command moreinfo="none">diff</command> command, getting it to generate context 1.15199 + diffs (using the <option role="cmd-opt-diff">-c</option> option) 1.15200 + instead of unified diffs, and five lines of context instead of 1.15201 + the default three (passing <literal moreinfo="none">5</literal> as the argument 1.15202 + to the <option role="cmd-opt-diff">-C</option> option).</para> 1.15203 + 1.15204 + <!-- BEGIN extdiff.extdiff-ctx --> 1.15205 +<screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff -o -NprcC5</userinput> 1.15206 +*** a.801b35c37d8b/myfile Sun Aug 16 14:05:02 2009 1.15207 +--- /tmp/extdiffl1y_s9/a/myfile Sun Aug 16 14:05:02 2009 1.15208 +*************** 1.15209 +*** 1 **** 1.15210 +--- 1,2 ---- 1.15211 + The first line. 1.15212 ++ The second line. 1.15213 +</screen> 1.15214 +<!-- END extdiff.extdiff-ctx --> 1.15215 + 1.15216 + 1.15217 + <para id="x_52a">Launching a visual diff tool is just as easy. Here's how to 1.15218 + launch the <command moreinfo="none">kdiff3</command> viewer.</para> 1.15219 + <programlisting format="linespecific">hg extdiff -p kdiff3 -o</programlisting> 1.15220 + 1.15221 + <para id="x_52b">If your diff viewing command can't deal with directories, 1.15222 + you can easily work around this with a little scripting. For an 1.15223 + example of such scripting in action with the <literal role="hg-ext" moreinfo="none">mq</literal> extension and the 1.15224 + <command moreinfo="none">interdiff</command> command, see <xref linkend="mq-collab:tips:interdiff"/>.</para> 1.15225 + 1.15226 + <sect2> 1.15227 + <title>Defining command aliases</title> 1.15228 + 1.15229 + <para id="x_52c">It can be cumbersome to remember the options to both the 1.15230 + <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command and 1.15231 + the diff viewer you want to use, so the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension lets you define 1.15232 + <emphasis>new</emphasis> commands that will invoke your diff 1.15233 + viewer with exactly the right options.</para> 1.15234 + 1.15235 + <para id="x_52d">All you need to do is edit your <filename role="special" moreinfo="none">~/.hgrc</filename>, and add a section named 1.15236 + <literal role="rc-extdiff" moreinfo="none">extdiff</literal>. Inside this 1.15237 + section, you can define multiple commands. Here's how to add 1.15238 + a <literal moreinfo="none">kdiff3</literal> command. Once you've defined 1.15239 + this, you can type <quote><literal moreinfo="none">hg kdiff3</literal></quote> 1.15240 + and the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension 1.15241 + will run <command moreinfo="none">kdiff3</command> for you.</para> 1.15242 + <programlisting format="linespecific">[extdiff] 1.15243 +cmd.kdiff3 =</programlisting> 1.15244 + <para id="x_52e">If you leave the right hand side of the definition empty, 1.15245 + as above, the <literal role="hg-ext" moreinfo="none">extdiff</literal> 1.15246 + extension uses the name of the command you defined as the name 1.15247 + of the external program to run. But these names don't have to 1.15248 + be the same. Here, we define a command named 1.15249 + <quote><literal moreinfo="none">hg wibble</literal></quote>, which runs 1.15250 + <command moreinfo="none">kdiff3</command>.</para> 1.15251 + <programlisting format="linespecific">[extdiff] 1.15252 + cmd.wibble = kdiff3</programlisting> 1.15253 + 1.15254 + <para id="x_52f">You can also specify the default options that you want to 1.15255 + invoke your diff viewing program with. The prefix to use is 1.15256 + <quote><literal moreinfo="none">opts.</literal></quote>, followed by the name 1.15257 + of the command to which the options apply. This example 1.15258 + defines a <quote><literal moreinfo="none">hg vimdiff</literal></quote> command 1.15259 + that runs the <command moreinfo="none">vim</command> editor's 1.15260 + <literal moreinfo="none">DirDiff</literal> extension.</para> 1.15261 + <programlisting format="linespecific">[extdiff] 1.15262 + cmd.vimdiff = vim 1.15263 +opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting> 1.15264 + 1.15265 + </sect2> 1.15266 + </sect1> 1.15267 + <sect1 id="sec:hgext:transplant"> 1.15268 + <title>Cherrypicking changes with the <literal role="hg-ext" moreinfo="none">transplant</literal> extension</title> 1.15269 + 1.15270 + <para id="x_530">Need to have a long chat with Brendan about this.</para> 1.15271 + 1.15272 + </sect1> 1.15273 + <sect1 id="sec:hgext:patchbomb"> 1.15274 + <title>Send changes via email with the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension</title> 1.15275 + 1.15276 + <para id="x_531">Many projects have a culture of <quote>change 1.15277 + review</quote>, in which people send their modifications to a 1.15278 + mailing list for others to read and comment on before they 1.15279 + commit the final version to a shared repository. Some projects 1.15280 + have people who act as gatekeepers; they apply changes from 1.15281 + other people to a repository to which those others don't have 1.15282 + access.</para> 1.15283 + 1.15284 + <para id="x_532">Mercurial makes it easy to send changes over email for 1.15285 + review or application, via its <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension. The extension is 1.15286 + so named because changes are formatted as patches, and it's usual 1.15287 + to send one changeset per email message. Sending a long series 1.15288 + of changes by email is thus much like <quote>bombing</quote> the 1.15289 + recipient's inbox, hence <quote>patchbomb</quote>.</para> 1.15290 + 1.15291 + <para id="x_533">As usual, the basic configuration of the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension takes just one or 1.15292 + two lines in your <filename role="special" moreinfo="none"> 1.15293 + /.hgrc</filename>.</para> 1.15294 + <programlisting format="linespecific">[extensions] 1.15295 +patchbomb =</programlisting> 1.15296 + <para id="x_534">Once you've enabled the extension, you will have a new 1.15297 + command available, named <command role="hg-ext-patchbomb" moreinfo="none">email</command>.</para> 1.15298 + 1.15299 + <para id="x_535">The safest and best way to invoke the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command is to 1.15300 + <emphasis>always</emphasis> run it first with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option. 1.15301 + This will show you what the command <emphasis>would</emphasis> 1.15302 + send, without actually sending anything. Once you've had a 1.15303 + quick glance over the changes and verified that you are sending 1.15304 + the right ones, you can rerun the same command, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option 1.15305 + removed.</para> 1.15306 + 1.15307 + <para id="x_536">The <command role="hg-ext-patchbomb" moreinfo="none">email</command> command 1.15308 + accepts the same kind of revision syntax as every other 1.15309 + Mercurial command. For example, this command will send every 1.15310 + revision between 7 and <literal moreinfo="none">tip</literal>, inclusive.</para> 1.15311 + <programlisting format="linespecific">hg email -n 7:tip</programlisting> 1.15312 + <para id="x_537">You can also specify a <emphasis>repository</emphasis> to 1.15313 + compare with. If you provide a repository but no revisions, the 1.15314 + <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will 1.15315 + send all revisions in the local repository that are not present 1.15316 + in the remote repository. If you additionally specify revisions 1.15317 + or a branch name (the latter using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option), 1.15318 + this will constrain the revisions sent.</para> 1.15319 + 1.15320 + <para id="x_538">It's perfectly safe to run the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command without the 1.15321 + names of the people you want to send to: if you do this, it will 1.15322 + just prompt you for those values interactively. (If you're 1.15323 + using a Linux or Unix-like system, you should have enhanced 1.15324 + <literal moreinfo="none">readline</literal>-style editing capabilities when 1.15325 + entering those headers, too, which is useful.)</para> 1.15326 + 1.15327 + <para id="x_539">When you are sending just one revision, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will by 1.15328 + default use the first line of the changeset description as the 1.15329 + subject of the single email message it sends.</para> 1.15330 + 1.15331 + <para id="x_53a">If you send multiple revisions, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will usually 1.15332 + send one message per changeset. It will preface the series with 1.15333 + an introductory message, in which you should describe the 1.15334 + purpose of the series of changes you're sending.</para> 1.15335 + 1.15336 + <sect2> 1.15337 + <title>Changing the behavior of patchbombs</title> 1.15338 + 1.15339 + <para id="x_53b">Not every project has exactly the same conventions for 1.15340 + sending changes in email; the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension tries to 1.15341 + accommodate a number of variations through command line 1.15342 + options.</para> 1.15343 + <itemizedlist> 1.15344 + <listitem><para id="x_53c">You can write a subject for the introductory 1.15345 + message on the command line using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -s</option> 1.15346 + option. This takes one argument, the text of the subject 1.15347 + to use.</para> 1.15348 + </listitem> 1.15349 + <listitem><para id="x_53d">To change the email address from which the 1.15350 + messages originate, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -f</option> 1.15351 + option. This takes one argument, the email address to 1.15352 + use.</para> 1.15353 + </listitem> 1.15354 + <listitem><para id="x_53e">The default behavior is to send unified diffs 1.15355 + (see <xref linkend="sec:mq:patch"/> for a 1.15356 + description of the 1.15357 + format), one per message. You can send a binary bundle 1.15358 + instead with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> 1.15359 + option.</para> 1.15360 + </listitem> 1.15361 + <listitem><para id="x_53f">Unified diffs are normally prefaced with a 1.15362 + metadata header. You can omit this, and send unadorned 1.15363 + diffs, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg 1.15364 + --plain</option> option.</para> 1.15365 + </listitem> 1.15366 + <listitem><para id="x_540">Diffs are normally sent <quote>inline</quote>, 1.15367 + in the same body part as the description of a patch. This 1.15368 + makes it easiest for the largest number of readers to 1.15369 + quote and respond to parts of a diff, as some mail clients 1.15370 + will only quote the first MIME body part in a message. If 1.15371 + you'd prefer to send the description and the diff in 1.15372 + separate body parts, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -a</option> 1.15373 + option.</para> 1.15374 + </listitem> 1.15375 + <listitem><para id="x_541">Instead of sending mail messages, you can 1.15376 + write them to an <literal moreinfo="none">mbox</literal>-format mail 1.15377 + folder using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -m</option> 1.15378 + option. That option takes one argument, the name of the 1.15379 + file to write to.</para> 1.15380 + </listitem> 1.15381 + <listitem><para id="x_542">If you would like to add a 1.15382 + <command moreinfo="none">diffstat</command>-format summary to each patch, 1.15383 + and one to the introductory message, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -d</option> 1.15384 + option. The <command moreinfo="none">diffstat</command> command displays 1.15385 + a table containing the name of each file patched, the 1.15386 + number of lines affected, and a histogram showing how much 1.15387 + each file is modified. This gives readers a qualitative 1.15388 + glance at how complex a patch is.</para> 1.15389 + </listitem></itemizedlist> 1.15390 + 1.15391 + </sect2> 1.15392 + </sect1> 1.15393 +</chapter> 1.15394 + 1.15395 +<!-- 1.15396 +local variables: 1.15397 +sgml-parent-document: ("00book.xml" "book" "chapter") 1.15398 +end: 1.15399 +--> 1.15400 + 1.15401 + <!-- BEGIN appA --> 1.15402 + 1.15403 + 1.15404 +<appendix id="svn"> 1.15405 + <?dbhtml filename="migrating-to-mercurial.html"?> 1.15406 +<title>Migrer vers Mercurial</title> 1.15407 + 1.15408 + <para id="x_6e1">Une manière courante de s'essayer à un nouveau 1.15409 + gestionnaire de révisions est d'expérimenter en migrant un 1.15410 + projet existant, plutôt que le faire avec un nouveau projet. 1.15411 + </para> 1.15412 + 1.15413 + <para id="x_6e2">Dans cette annexe, nous discuterons comment importer 1.15414 + l'historique d'un projet dans Mercurial, et à quoi faire attention 1.15415 + si vous êtes habitués à un autre outil de gestion de révisions. 1.15416 + </para> 1.15417 + 1.15418 + <sect1> 1.15419 + <title>Importer l'historique depuis un autre système</title> 1.15420 + 1.15421 + <para id="x_6e3">Mercurial est livré avec une extension nommée 1.15422 + <literal moreinfo="none">convert</literal>, qui permet d'importer un historique 1.15423 + depuis les gestionnaire de révisions les plus courants. Au moment de 1.15424 + l'écriture de ce livre, il pouvait importer l'historique depuis: 1.15425 + </para> 1.15426 + <itemizedlist> 1.15427 + <listitem> 1.15428 + <para id="x_6e4">Subversion</para> 1.15429 + </listitem> 1.15430 + <listitem> 1.15431 + <para id="x_6e5">CVS</para> 1.15432 + </listitem> 1.15433 + <listitem> 1.15434 + <para id="x_6e6">git</para> 1.15435 + </listitem> 1.15436 + <listitem> 1.15437 + <para id="x_6e7">Darcs</para> 1.15438 + </listitem> 1.15439 + <listitem> 1.15440 + <para id="x_6e8">Bazaar</para> 1.15441 + </listitem> 1.15442 + <listitem> 1.15443 + <para id="x_6e9">Monotone</para> 1.15444 + </listitem> 1.15445 + <listitem> 1.15446 + <para id="x_6ea">GNU Arch</para> 1.15447 + </listitem> 1.15448 + <listitem> 1.15449 + <para id="x_6eb">Mercurial</para> 1.15450 + </listitem> 1.15451 + </itemizedlist> 1.15452 + 1.15453 + <para id="x_6ec">(Pour savoir pourquoi Mercurial lui même est supporté 1.15454 + comme source, voir <xref linkend="svn.filemap"/>.)</para> 1.15455 + 1.15456 + <para id="x_6ed">Vous pouvez activer l'extension de la manière 1.15457 + habituelle, en éditant votre fichier <filename moreinfo="none">~/.hgrc</filename></para> 1.15458 + 1.15459 + <programlisting format="linespecific">[extensions] 1.15460 +convert =</programlisting> 1.15461 + 1.15462 + <para id="x_6ee">Ceci rendra la commande <command moreinfo="none">hg convert</command> 1.15463 + disponible. La commande est facile à utiliser. Par exemple, la 1.15464 + commande suivante va importer l'historique Subversion du <emphasis remap="it">framework</emphasis> de test <quote>Nose Unit</quote> dans Mercurial. 1.15465 + </para> 1.15466 + 1.15467 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen> 1.15468 + 1.15469 + <para id="x_6ef">L'extension <literal moreinfo="none">convert</literal> opère de 1.15470 + manière incrémentale. En d'autres mots, après une première exécution de 1.15471 + la commande <command moreinfo="none">hg convert</command>, les exécutions ultérieures 1.15472 + importeront les révisions ultérieures à l'exécution précédente. 1.15473 + La conversion incrémentale ne réussira que si 1.15474 + vous exécutez <command moreinfo="none">hg convert</command> dans le même dépôt que vous 1.15475 + aviez utilisé à l'origine, ceci parce que l'extension <literal moreinfo="none">convert</literal> 1.15476 + sauvegarde un certain nombre de méta-données privées dans le fichier 1.15477 + <filename moreinfo="none">.hg/shamap</filename> (non versioné) au sein du dépôt cible. 1.15478 + </para> 1.15479 + 1.15480 + <para id="x_707">Lorsque vous voulez faire des modifications en utilisant 1.15481 + Mercurial, le mieux est de faire un clone de l'ensemble de l'arborescence 1.15482 + que vous souhaitez convertir, et de laisser l'arborescence d'origine pour 1.15483 + de futures conversions incrémentales. C'est la manière la plus sûre pour vous laisser 1.15484 + récupérer et fusionner les modifications futures depuis l'outil de gestion 1.15485 + de révisions dans votre nouveau dépôt Mercurial.</para> 1.15486 + 1.15487 + <sect2> 1.15488 + <title>Convertir plusieurs branches</title> 1.15489 + 1.15490 + <para id="x_708">La commande <command moreinfo="none">hg convert</command> citée 1.15491 + ci-dessus convertit seulement l'historique de la <literal moreinfo="none">branche 1.15492 + principale (trunk)</literal> du dépôt Subversion. Si nous utilisons 1.15493 + à la place l'URL <literal moreinfo="none">http://python-nose.googlecode.com/svn</literal>, 1.15494 + Mercurial va automatiquement détecter la 1.15495 + <literal moreinfo="none">branche principale (trunk)</literal>, les <literal moreinfo="none">étiquettes 1.15496 + (tags)</literal>, et les <literal moreinfo="none">branches</literal> que les dépôts 1.15497 + Subversion utilisent généralement, et les importera chacun dans 1.15498 + une branche Mercurial distincte.</para> 1.15499 + 1.15500 + <para id="x_709">Par défaut, chaque branche Subversion importée 1.15501 + dans Mercurial se voit attribuer un nom de branche. Une fois la 1.15502 + conversion achevée, vous pouvez obtenir la liste des noms des branches 1.15503 + actives dans le dépôt Mercurial en utilisant la commande 1.15504 + <command moreinfo="none">hg branches -a</command>. Si vous préférez importer les 1.15505 + branches Subversion sans noms, ajoutez l'option <option>--config 1.15506 + convert.hg.usebranches=false</option> à la commande 1.15507 + <command moreinfo="none">hg convert</command>.</para> 1.15508 + 1.15509 + <para id="x_70a">Une fois votre arborescence convertie, 1.15510 + si vous souhaitez travailler selon la pratique habituelle sous Mercurial 1.15511 + avec une arborescence qui ne contient qu'une seule branche, vous pouvez cloner 1.15512 + cette seule branche en utilisant 1.15513 + <command moreinfo="none">hg clone -r nomdemabranche</command>.</para> 1.15514 + </sect2> 1.15515 + 1.15516 + <sect2> 1.15517 + <title>Associer les noms d'utilisateurs</title> 1.15518 + 1.15519 + <para id="x_6f0">Certains outils de gestion de révisions 1.15520 + ne sauvegardent, avec les modifications, que les noms 1.15521 + d'utilisateurs raccourcis. Ceux-ci peuvent être difficiles à 1.15522 + interpréter. La norme avec Mercurial est de sauvegarder le 1.15523 + nom du <emphasis remap="it">committeur</emphasis> et son adresse 1.15524 + mail, ce qui est beaucoup plus utile pour discuter avec lui 1.15525 + par la suite.</para> 1.15526 + 1.15527 + <para id="x_6f1">Si vous convertissez une arborescence depuis 1.15528 + un gestionnaire de révisions qui utilise seulement les noms 1.15529 + raccourcis, vous pouvez associer ces noms à des équivalents 1.15530 + plus détaillés en passant l'option <option>--authors</option> 1.15531 + à la commande <command moreinfo="none">hg convert</command>. Cette option 1.15532 + attend un fichier qui contient des entrées sous la forme suivante: 1.15533 + </para> 1.15534 + 1.15535 + <programlisting format="linespecific">arist = Aristotle <aristotle@phil.example.gr> 1.15536 +soc = Socrates <socrates@phil.example.gr></programlisting> 1.15537 + 1.15538 + <para id="x_6f2">Quand <literal moreinfo="none">convert</literal> trouve une 1.15539 + modification associée au nom <literal moreinfo="none">arist</literal> dans le 1.15540 + dépôt de source, il va utiliser le nom <literal moreinfo="none">Aristotle 1.15541 + <aristotle@phil.example.gr></literal> dans les révisions 1.15542 + Mercurial. Si aucune correspondance n'est trouvé, il utilise 1.15543 + le nom tel quel.</para> 1.15544 + </sect2> 1.15545 + 1.15546 + <sect2 id="svn.filemap"> 1.15547 + <title>Nettoyer l'arboresence</title> 1.15548 + 1.15549 + <para id="x_6f3">Tous les projets n'ont pas un historique parfait. 1.15550 + Il peut y avoir des répertoires qui n'auraient jamais dû être ajoutés, 1.15551 + un fichier qui est trop volumineux, ou même une partie de la 1.15552 + hiérarchie qui devrait être réorganisée.</para> 1.15553 + 1.15554 + <para id="x_6f4">L'extension <literal moreinfo="none">convert</literal> permet 1.15555 + d'utiliser un <quote>fichier d'association</quote> qui peut 1.15556 + réorganiser les fichiers et les répertoires dans un projet lors de 1.15557 + l'importation de son historique. Ceci est utile non seulement quand vous 1.15558 + importez l'historique d'un autre gestionnaire de révisions, mais 1.15559 + aussi pour nettoyer ou réorganiser l'arborescence d'un projet 1.15560 + Mercurial.</para> 1.15561 + 1.15562 + <para id="x_6f5">Pour indiquer le fichier d'association, on utilise 1.15563 + l'option <option>--filemap</option> en lui fournissant un nom de 1.15564 + fichier. Le fichier d'association contient des lignes de la forme 1.15565 + suivante :</para> 1.15566 + 1.15567 + <programlisting format="linespecific"># Ceci est un commentaire. 1.15568 +# Les lignes vides sont ignorées. 1.15569 + 1.15570 +include path/to/file 1.15571 + 1.15572 +exclude path/to/file 1.15573 + 1.15574 +rename from/some/path to/some/other/place 1.15575 +</programlisting> 1.15576 + 1.15577 + <para id="x_6f6">La directive <literal moreinfo="none">include</literal> inclut un 1.15578 + fichier, ou l'ensemble des fichiers d'un répertoire, dans le dépôt 1.15579 + de destination. La directive <literal moreinfo="none">exclude</literal> omet les 1.15580 + fichiers ou répertoires du dépôt. Ceci inclut aussi les autres 1.15581 + fichiers et répertoires qui ne sont pas explicitement inclus. 1.15582 + La directive <literal moreinfo="none">exclude</literal> entraine l'omission 1.15583 + des fichiers ou répertoires, et autres fichiers qui ne sont pas 1.15584 + explicitement inclus.</para> 1.15585 + 1.15586 + <para id="x_6f7">Pour déplacer un fichier ou un répertoire d'un 1.15587 + emplacement à un autre, utilisez la directive 1.15588 + <literal moreinfo="none">rename</literal>. Si vous avez besoin de déplacer un 1.15589 + fichier ou un répertoire depuis un sous répertoire dans la racine 1.15590 + du dépôt, utilisez <literal moreinfo="none">.</literal> comme second argument de 1.15591 + la directive <literal moreinfo="none">rename</literal>.</para> 1.15592 + </sect2> 1.15593 + 1.15594 + <sect2> 1.15595 + <title>Améliorer les performances de la conversion Subversion</title> 1.15596 + 1.15597 + <para id="x_70b">Vous aurez souvent besoin de plusieurs essais 1.15598 + avant d'arriver à la parfaite combinaison de fichier d'association de fichiers, 1.15599 + de fichier d'association de noms d'utilisateurs et des autres paramètres. Or, 1.15600 + convertir un dépôt Mercurial via un protocole comme <literal moreinfo="none">ssh</literal> 1.15601 + ou <literal moreinfo="none">http</literal> peut être des milliers de fois plus long 1.15602 + que ce dont le système d'exploitation est en fait capable de faire, 1.15603 + à cause des latence réseau. Ceci peut rendre la conception de cette 1.15604 + combinaison parfaite très douloureuse.</para> 1.15605 + 1.15606 + <para id="x_70c">La commande <ulink url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command moreinfo="none">svnsync</command></ulink> 1.15607 + peut grandement améliorer la vitesse de conversion d'un dépôt 1.15608 + Subversion. Il s'agit d'un programme de miroir de dépôt Subversion 1.15609 + en lecture seule. L'idée est de créer un miroir local d'une 1.15610 + arborescence Subversion, puis de convertir ce miroir en dépôt 1.15611 + Mercurial.</para> 1.15612 + 1.15613 + <para id="x_70d">Supposez que nous voulions convertir le dépôt 1.15614 + Subversion du populaire projet Memcached en une arborescence Mercurial. 1.15615 + Tout d'abord, nous créons un dépôt Subversion local.</para> 1.15616 + 1.15617 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnadmin create memcached-mirror</userinput></screen> 1.15618 + 1.15619 + <para id="x_70e">Puis, nous allons mettre en place un <quote>hook</quote> Subversion 1.15620 + dont <command moreinfo="none">svnsync</command> a besoin.</para> 1.15621 + 1.15622 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '#!/bin/sh' > memcached-mirror/hooks/pre-revprop-change</userinput> 1.15623 +<prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen> 1.15624 + 1.15625 + <para id="x_70f">Nous initialisons ensuite <command moreinfo="none">svnsync</command> dans ce 1.15626 + dépôt.</para> 1.15627 + 1.15628 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync --init file://`pwd`/memcached-mirror \ 1.15629 + http://code.sixapart.com/svn/memcached</userinput></screen> 1.15630 + 1.15631 + <para id="x_710">La prochaine étape est de commencer le processus de 1.15632 + mirroring de <command moreinfo="none">svnsync</command>.</para> 1.15633 + 1.15634 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync sync file://`pwd`/memcached-mirror</userinput></screen> 1.15635 + 1.15636 + <para id="x_711">Enfin, nous importons l'historique de notre dépôt 1.15637 + local Subversion dans Mercurial.</para> 1.15638 + 1.15639 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert memcached-mirror</userinput></screen> 1.15640 + 1.15641 + <para id="x_712">Nous pouvons utiliser ce processus de manière 1.15642 + incrémentale, si le dépôt Subversion est toujours en activité. 1.15643 + Il suffit d'exécuter de nouveau <command moreinfo="none">svnsync</command> pour 1.15644 + récupérer les récentes modifications dans notre miroir, puis <command moreinfo="none">hg 1.15645 + convert</command> 1.15646 + les importe dans notre arborescence Mercurial.</para> 1.15647 + 1.15648 + <para id="x_713">Il y a deux avantages à utiliser un import à deux 1.15649 + étages comme avec <command moreinfo="none">svnsync</command>. Le premier 1.15650 + est qu'il utilise du code de synchronisation réseau de Subversion 1.15651 + plus efficace que la commande <command moreinfo="none">hg convert</command>, 1.15652 + et donc transfère moins de données par le réseau. Le deuxième 1.15653 + est que l'import depuis un dépôt Subversion local est si rapide que 1.15654 + vous pouvez peaufiner et réitérer les paramètres de conversion de 1.15655 + ce dernier sans souffrir de la qualité de la connexion réseau.</para> 1.15656 + </sect2> 1.15657 + </sect1> 1.15658 + 1.15659 + <sect1> 1.15660 + <title>Migrer depuis Subversion</title> 1.15661 + 1.15662 + <para id="x_6f8">Subversion est le système de gestion de versions 1.15663 + open source le plus populaire aujourd'hui. Bien qu'il y ait des 1.15664 + différences entre Mercurial et Subversion, faire la transition de 1.15665 + l'un à l'autre n'est pas très difficile. Les deux disposent en effet 1.15666 + de jeux de commandes similaires et d'interfaces similaires.</para> 1.15667 + 1.15668 + <sect2> 1.15669 + <title>Différences philosophiques</title> 1.15670 + 1.15671 + <para id="x_6f9">La différence fondamentale entre Subversion et 1.15672 + Mercurial est bien évidement que Subversion est centralisé, alors 1.15673 + que Mercurial est distribué. Puisque que Mercurial enregistre tout 1.15674 + l'historique d'un projet sur votre disque dur local, il n'a besoin 1.15675 + d'effectuer des accès au réseau que lorsque vous voulez 1.15676 + explicitement communiquer avec un autre dépôt. Subversion, par contre, 1.15677 + ne conserve que peu d'informations localement, et le client 1.15678 + doit donc communiquer avec le serveur central pour la 1.15679 + plupart des opérations communes.</para> 1.15680 + 1.15681 + <para id="x_6fa">Subversion s'en tire plus ou moins bien sans notion 1.15682 + de branche réellement bien définie : quelle portion de l'espace de nommage 1.15683 + du serveur est une branche est une simple question de convention, le 1.15684 + logiciel n'imposant rien à ce sujet. Mercurial considère 1.15685 + un dépôt comme un élément de la gestion des branches.</para> 1.15686 + 1.15687 + <sect3> 1.15688 + <title>Portée des commandes</title> 1.15689 + 1.15690 + <para id="x_6fb">Puisque que Subversion ne sait pas réellement 1.15691 + quelle partie de son espace de nommage est en fait une branche, il 1.15692 + traite la plupart des commandes comme des requêtes à exécuter sur le 1.15693 + répertoire où vous vous situez, et ses sous répertoires. Par exemple, 1.15694 + si vous exécutez <command moreinfo="none">svn log</command>, vous verrez l'historique 1.15695 + de la partie de l'arborescence où vous vous situez, et non de la 1.15696 + hiérarchie entière.</para> 1.15697 + 1.15698 + <para id="x_6fc">Les commandes de Mercurial ont un comportement 1.15699 + différent : toutes les commandes s'appliquent à l'ensemble de l'arborescence 1.15700 + du dépôt. Exécutez la commande <command moreinfo="none">hg log</command> et elle vous 1.15701 + donnera l'historique de l'ensemble de l'arborescence, quel que soit le 1.15702 + sous-répertoire où vous vous situez. Si 1.15703 + vous souhaitez obtenir l'historique d'un répertoire ou seulement d'un 1.15704 + fichier, ajouter simplement le nom de celui-ci à la commande, par 1.15705 + exemple <command moreinfo="none">hg log src</command>.</para> 1.15706 + 1.15707 + <para id="x_6fd">De ma propre expérience, cette différence dans leur 1.15708 + comportement par défaut est probablement ce qui risque de vous 1.15709 + surprendre le plus si vous passez régulièrement d'un outil à l'autre.</para> 1.15710 + </sect3> 1.15711 + 1.15712 + <sect3> 1.15713 + <title>Opération multi utilisateur et sécurité</title> 1.15714 + 1.15715 + <para id="x_6fe">Avec Subversion, il est normal (bien que légèrement 1.15716 + désapprouvé) que différentes personnes collaborent sur une seule 1.15717 + branche. Si Alice et Bob travaillent ensemble, et Alice ajoute ses 1.15718 + modifications à leur branche partagée, Bob doit alors mettre à jour 1.15719 + sa vue de la branche avant de pouvoir appliquer un commit. 1.15720 + Puisqu'il n'a, à ce moment, pas effectué de commit 1.15721 + des modifications qu'il a faites, il se peut qu'il ne corrompe 1.15722 + ou ne perde 1.15723 + ses modifications pendant ou après la mise à jour.</para> 1.15724 + 1.15725 + <para id="x_6ff">Mercurial encourage, à l'inverse, un modèle 1.15726 + "commit-puis-merge". Avant de récupérer des modifications depuis le 1.15727 + serveur, ou avant d'y envoyer les siennes, Bob enregistre ses 1.15728 + modifications de manière locale en appliquant un commit. C'est à dire 1.15729 + que si Alice avait envoyé ses modifications sur le serveur avant 1.15730 + que Bob n'envoie les siennes, ce dernier ne pourra le faire 1.15731 + qu'après avoir récupéré et fusionné celles d'Alice avec les siennes. 1.15732 + Si Bob fait alors une 1.15733 + erreur lors de la fusion, il pourra toujours restaurer sa version, pour 1.15734 + laquelle il avait appliqué le commit.</para> 1.15735 + 1.15736 + <para id="x_700">Il est important de souligner qu'il s'agit de la 1.15737 + manière habituelle de travailler avec ces outils. Subversion propose 1.15738 + une manière plus sûre de "travailler-dans-votre-propre-branche", mais elle 1.15739 + est assez complexe pour que, en pratique, elle ne soit que rarement utilisé. 1.15740 + Mercurial propose de son côté un mode un peu moins sûr, permettant de 1.15741 + récupérer des modifications par dessus des modifications non 1.15742 + committées, qui reste toutefois très peu répandu.</para> 1.15743 + </sect3> 1.15744 + 1.15745 + <sect3> 1.15746 + <title>Publication vs changement locaux</title> 1.15747 + 1.15748 + <para id="x_701">Une commande Subversion <command moreinfo="none">svn 1.15749 + commit</command> publie immédiatement les modifications sur le 1.15750 + serveur, où elles peuvent être vu par n'importe qui doté d'un privilège 1.15751 + de lecture.</para> 1.15752 + 1.15753 + <para id="x_702">Avec Mercurial, les modifications sont toujours d'abord 1.15754 + enregistrées localement, et doivent être par la suite transférés par 1.15755 + la commande <command moreinfo="none">hg push</command>.</para> 1.15756 + 1.15757 + <para id="x_703">Chaque approche a ses avantages et ses inconvénients. 1.15758 + Le modèle Subversion implique que les modifications soient publiées, et 1.15759 + donc disponibles immédiatement. D'un autre coté, cela implique aussi 1.15760 + que, pour pouvoir utiliser le logiciel normalement, un utilisateur doit 1.15761 + avoir les droits d'écriture dans le dépôt, et ce privilège n'est pas concédé 1.15762 + facilement par la plupart des projets Open Source.</para> 1.15763 + 1.15764 + <para id="x_704">L'approche de Mercurial permet à quiconque de faire 1.15765 + un clone du dépôt et d'y ajouter ses modifications sans jamais avoir 1.15766 + besoin de la permission de quiconque, et l'on peut même publier ses 1.15767 + modifications et continuer à participer comme on le désire. Toutefois, la 1.15768 + distinction entre les commits et le transfert de ces derniers présente 1.15769 + le risque que quelqu'un applique ses modifications par un commit local 1.15770 + sur son portable et parte se promener pendant quelques jours en ayant 1.15771 + oublié de les transférer, ce qui peut, dans certains rares cas, 1.15772 + bloquer temporairement ses collaborateurs.</para> 1.15773 + </sect3> 1.15774 + </sect2> 1.15775 + 1.15776 + <sect2> 1.15777 + <title>Références des commandes</title> 1.15778 + 1.15779 + <table> 1.15780 + <title>Commandes Subversion et leurs équivalents Mercurial</title> 1.15781 + <tgroup cols="3"> 1.15782 + <thead> 1.15783 + <row> 1.15784 + <entry>Subversion</entry> 1.15785 + <entry>Mercurial</entry> 1.15786 + <entry>Notes</entry> 1.15787 + </row> 1.15788 + </thead> 1.15789 + <tbody> 1.15790 + <row> 1.15791 + <entry><command moreinfo="none">svn add</command></entry> 1.15792 + <entry><command moreinfo="none">hg add</command></entry> 1.15793 + <entry/> 1.15794 + </row> 1.15795 + <row> 1.15796 + <entry><command moreinfo="none">svn blame</command></entry> 1.15797 + <entry><command moreinfo="none">hg annotate</command></entry> 1.15798 + <entry/> 1.15799 + </row> 1.15800 + <row> 1.15801 + <entry><command moreinfo="none">svn cat</command></entry> 1.15802 + <entry><command moreinfo="none">hg cat</command></entry> 1.15803 + <entry/> 1.15804 + </row> 1.15805 + <row> 1.15806 + <entry><command moreinfo="none">svn checkout</command></entry> 1.15807 + <entry><command moreinfo="none">hg clone</command></entry> 1.15808 + <entry/> 1.15809 + </row> 1.15810 + <row> 1.15811 + <entry><command moreinfo="none">svn cleanup</command></entry> 1.15812 + <entry>n/a</entry> 1.15813 + <entry>Aucun nettoyage nécessaire.</entry> 1.15814 + </row> 1.15815 + <row> 1.15816 + <entry><command moreinfo="none">svn commit</command></entry> 1.15817 + <entry><command moreinfo="none">hg commit</command>; <command moreinfo="none">hg 1.15818 + push</command></entry> 1.15819 + <entry><command moreinfo="none">hg push</command> publie les modifications 1.15820 + après un commit.</entry> 1.15821 + </row> 1.15822 + <row> 1.15823 + <entry><command moreinfo="none">svn copy</command></entry> 1.15824 + <entry><command moreinfo="none">hg clone</command></entry> 1.15825 + <entry>Pour créer une nouvelle branche</entry> 1.15826 + </row> 1.15827 + <row> 1.15828 + <entry><command moreinfo="none">svn copy</command></entry> 1.15829 + <entry><command moreinfo="none">hg copy</command></entry> 1.15830 + <entry>Pour copier des fichiers ou des répertoires</entry> 1.15831 + </row> 1.15832 + <row> 1.15833 + <entry><command moreinfo="none">svn delete</command> (<command moreinfo="none">svn 1.15834 + remove</command>)</entry> 1.15835 + <entry><command moreinfo="none">hg remove</command></entry> 1.15836 + <entry/> 1.15837 + </row> 1.15838 + <row> 1.15839 + <entry><command moreinfo="none">svn diff</command></entry> 1.15840 + <entry><command moreinfo="none">hg diff</command></entry> 1.15841 + <entry/> 1.15842 + </row> 1.15843 + <row> 1.15844 + <entry><command moreinfo="none">svn export</command></entry> 1.15845 + <entry><command moreinfo="none">hg archive</command></entry> 1.15846 + <entry/> 1.15847 + </row> 1.15848 + <row> 1.15849 + <entry><command moreinfo="none">svn help</command></entry> 1.15850 + <entry><command moreinfo="none">hg help</command></entry> 1.15851 + <entry/> 1.15852 + </row> 1.15853 + <row> 1.15854 + <entry><command moreinfo="none">svn import</command></entry> 1.15855 + <entry><command moreinfo="none">hg addremove</command>; <command moreinfo="none">hg 1.15856 + commit</command></entry> 1.15857 + <entry/> 1.15858 + </row> 1.15859 + <row> 1.15860 + <entry><command moreinfo="none">svn info</command></entry> 1.15861 + <entry><command moreinfo="none">hg parents</command></entry> 1.15862 + <entry>Affiche la version sur la base de laquelle on travaille</entry> 1.15863 + </row> 1.15864 + <row> 1.15865 + <entry><command moreinfo="none">svn info</command></entry> 1.15866 + <entry><command moreinfo="none">hg showconfig 1.15867 + paths.default</command></entry> 1.15868 + <entry>Affiche de quelle URL est extrait ce dépôt</entry> 1.15869 + </row> 1.15870 + <row> 1.15871 + <entry><command moreinfo="none">svn list</command></entry> 1.15872 + <entry><command moreinfo="none">hg manifest</command></entry> 1.15873 + <entry/> 1.15874 + </row> 1.15875 + <row> 1.15876 + <entry><command moreinfo="none">svn log</command></entry> 1.15877 + <entry><command moreinfo="none">hg log</command></entry> 1.15878 + <entry/> 1.15879 + </row> 1.15880 + <row> 1.15881 + <entry><command moreinfo="none">svn merge</command></entry> 1.15882 + <entry><command moreinfo="none">hg merge</command></entry> 1.15883 + <entry/> 1.15884 + </row> 1.15885 + <row> 1.15886 + <entry><command moreinfo="none">svn mkdir</command></entry> 1.15887 + <entry>n/a</entry> 1.15888 + <entry>Mercurial ne versionne pas les répertoires</entry> 1.15889 + </row> 1.15890 + <row> 1.15891 + <entry><command moreinfo="none">svn move</command> (<command moreinfo="none">svn 1.15892 + rename</command>)</entry> 1.15893 + <entry><command moreinfo="none">hg rename</command></entry> 1.15894 + <entry/> 1.15895 + </row> 1.15896 + <row> 1.15897 + <entry><command moreinfo="none">svn resolved</command></entry> 1.15898 + <entry><command moreinfo="none">hg resolve -m</command></entry> 1.15899 + <entry/> 1.15900 + </row> 1.15901 + <row> 1.15902 + <entry><command moreinfo="none">svn revert</command></entry> 1.15903 + <entry><command moreinfo="none">hg revert</command></entry> 1.15904 + <entry/> 1.15905 + </row> 1.15906 + <row> 1.15907 + <entry><command moreinfo="none">svn status</command></entry> 1.15908 + <entry><command moreinfo="none">hg status</command></entry> 1.15909 + <entry/> 1.15910 + </row> 1.15911 + <row> 1.15912 + <entry><command moreinfo="none">svn update</command></entry> 1.15913 + <entry><command moreinfo="none">hg pull -u</command></entry> 1.15914 + <entry/> 1.15915 + </row> 1.15916 + </tbody> 1.15917 + </tgroup> 1.15918 + </table> 1.15919 + </sect2> 1.15920 + </sect1> 1.15921 + 1.15922 + <sect1> 1.15923 + <title>Conseils utiles pour les débutants</title> 1.15924 + 1.15925 + <para id="x_705">Avec la plupart des gestionnaire de versions, afficher 1.15926 + un diff associé à une révision peut être assez douloureux. Par exemple, 1.15927 + avec Subversion, pour voir ce qui a été modifiée dans la révision 104654, 1.15928 + vous devez saisir <command moreinfo="none">svn diff -r104653:104654</command>. Mercurial 1.15929 + élimine le besoin de saisir l'identifiant d'une révision deux fois dans 1.15930 + ce cas classique. Pour un simple diff, <command moreinfo="none">hg 1.15931 + export 104654</command> suffit. Pour obtenir une entrée du journal suivie d'un diff, 1.15932 + <command moreinfo="none">hg log -r104654 -p</command>.</para> 1.15933 + 1.15934 + <para id="x_706">Quand vous exécutez la commande <command moreinfo="none">hg status</command> 1.15935 + sans aucun argument, elle affiche l'état de l'ensemble de l'arborescence, 1.15936 + avec des chemins relatifs partant de la racine du dépôt. Ceci rend 1.15937 + difficile de copier un nom de fichier depuis la sortie de la commande 1.15938 + <command moreinfo="none">hg status</command> dans une autre ligne de commande. Si vous 1.15939 + fournissez un fichier ou un répertoire à la commande <command moreinfo="none">hg 1.15940 + status</command>, elle va afficher les chemins relatif depuis votre 1.15941 + répertoire courant à la place. Ainsi, pour avoir un état sur l'ensemble 1.15942 + de l'arborescence à l'aide de <command moreinfo="none">hg status</command>, avec des 1.15943 + chemins relatifs à votre répertoire courant, et non la racine du dépôt, 1.15944 + ajoutez la sortie de <command moreinfo="none">hg root</command> à la commande 1.15945 + <command moreinfo="none">hg status</command>. Vous pouvez le faire aisément sur un 1.15946 + système Unix ainsi :</para> 1.15947 + 1.15948 + <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput></screen> 1.15949 + </sect1> 1.15950 +</appendix> 1.15951 + 1.15952 +<!-- 1.15953 +local variables: 1.15954 +sgml-parent-document: ("00book.xml" "book" "appendix") 1.15955 +end: 1.15956 +--> 1.15957 + 1.15958 + <!-- BEGIN appB --> 1.15959 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.15960 + 1.15961 +<appendix id="chap:mqref"> 1.15962 + <?dbhtml filename="mercurial-queues-reference.html"?> 1.15963 + <title>Mercurial Queues reference</title> 1.15964 + 1.15965 + <sect1 id="sec:mqref:cmdref"> 1.15966 + <title>MQ command reference</title> 1.15967 + 1.15968 + <para id="x_5e8">For an overview of the commands provided by MQ, use the 1.15969 + command <command role="hg-cmd" moreinfo="none">hg help mq</command>.</para> 1.15970 + 1.15971 + <sect2> 1.15972 + <title><command role="hg-ext-mq" moreinfo="none">qapplied</command>—print 1.15973 + applied patches</title> 1.15974 + 1.15975 + <para id="x_5e9">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command 1.15976 + prints the current stack of applied patches. Patches are 1.15977 + printed in oldest-to-newest order, so the last patch in the 1.15978 + list is the <quote>top</quote> patch.</para> 1.15979 + 1.15980 + </sect2> 1.15981 + <sect2> 1.15982 + <title><command role="hg-ext-mq" moreinfo="none">qcommit</command>—commit 1.15983 + changes in the queue repository</title> 1.15984 + 1.15985 + <para id="x_5ea">The <command role="hg-ext-mq" moreinfo="none">qcommit</command> command 1.15986 + commits any outstanding changes in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> 1.15987 + repository. This command only works if the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> 1.15988 + directory is a repository, i.e. you created the directory 1.15989 + using <command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or 1.15990 + ran <command role="hg-cmd" moreinfo="none">hg init</command> in the directory 1.15991 + after running <command role="hg-ext-mq" moreinfo="none">qinit</command>.</para> 1.15992 + 1.15993 + <para id="x_5eb">This command is shorthand for <command role="hg-cmd" moreinfo="none">hg 1.15994 + commit --cwd .hg/patches</command>.</para> 1.15995 + </sect2> 1.15996 + <sect2> 1.15997 + <title><command role="hg-ext-mq" moreinfo="none">qdelete</command>—delete a patch 1.15998 + from the <filename role="special" moreinfo="none">series</filename> 1.15999 + file</title> 1.16000 + 1.16001 + <para id="x_5ec">The <command role="hg-ext-mq" moreinfo="none">qdelete</command> command 1.16002 + 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> 1.16003 + directory. It does not pop the patch if the patch is already 1.16004 + applied. By default, it does not delete the patch file; use 1.16005 + the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option 1.16006 + to do that.</para> 1.16007 + 1.16008 + <para id="x_5ed">Options:</para> 1.16009 + <itemizedlist> 1.16010 + <listitem><para id="x_5ee"><option role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the 1.16011 + patch file.</para> 1.16012 + </listitem></itemizedlist> 1.16013 + 1.16014 + </sect2> 1.16015 + <sect2> 1.16016 + <title><command role="hg-ext-mq" moreinfo="none">qdiff</command>—print a 1.16017 + diff of the topmost applied patch</title> 1.16018 + 1.16019 + <para id="x_5ef">The <command role="hg-ext-mq" moreinfo="none">qdiff</command> command 1.16020 + prints a diff of the topmost applied patch. It is equivalent 1.16021 + to <command role="hg-cmd" moreinfo="none">hg diff -r-2:-1</command>.</para> 1.16022 + 1.16023 + </sect2> 1.16024 + <sect2> 1.16025 + <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—move 1.16026 + applied patches into repository history</title> 1.16027 + 1.16028 + <para id="x_72d">The <command moreinfo="none">hg qfinish</command> command converts the 1.16029 + specified applied patches into permanent changes by moving 1.16030 + them out of MQ's control so that they will be treated as 1.16031 + normal repository history.</para> 1.16032 + </sect2> 1.16033 + 1.16034 + <sect2> 1.16035 + <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—merge 1.16036 + (<quote>fold</quote>) several patches into one</title> 1.16037 + 1.16038 + <para id="x_5f0">The <command role="hg-ext-mq" moreinfo="none">qfold</command> command 1.16039 + merges multiple patches into the topmost applied patch, so 1.16040 + that the topmost applied patch makes the union of all of the 1.16041 + changes in the patches in question.</para> 1.16042 + 1.16043 + <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 1.16044 + any is. The order in which patches are folded is significant; 1.16045 + <command role="hg-cmd" moreinfo="none">hg qfold a b</command> means 1.16046 + <quote>apply the current topmost patch, followed by 1.16047 + <literal moreinfo="none">a</literal>, followed by 1.16048 + <literal moreinfo="none">b</literal></quote>.</para> 1.16049 + 1.16050 + <para id="x_5f2">The comments from the folded patches are appended to the 1.16051 + comments of the destination patch, with each block of comments 1.16052 + separated by three asterisk 1.16053 + (<quote><literal moreinfo="none">*</literal></quote>) characters. Use the 1.16054 + <option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to 1.16055 + edit the commit message for the combined patch/changeset after 1.16056 + the folding has completed.</para> 1.16057 + 1.16058 + <para id="x_5f3">Options:</para> 1.16059 + <itemizedlist> 1.16060 + <listitem><para id="x_5f4"><option role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the 1.16061 + commit message and patch description for the newly folded 1.16062 + patch.</para> 1.16063 + </listitem> 1.16064 + <listitem><para id="x_5f5"><option role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the 1.16065 + contents of the given file as the new commit message and 1.16066 + patch description for the folded patch.</para> 1.16067 + </listitem> 1.16068 + <listitem><para id="x_5f6"><option role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the 1.16069 + given text as the new commit message and patch description 1.16070 + for the folded patch.</para> 1.16071 + </listitem></itemizedlist> 1.16072 + 1.16073 + </sect2> 1.16074 + <sect2> 1.16075 + <title><command role="hg-ext-mq" moreinfo="none">qheader</command>—display the 1.16076 + header/description of a patch</title> 1.16077 + 1.16078 + <para id="x_5f7">The <command role="hg-ext-mq" moreinfo="none">qheader</command> command 1.16079 + prints the header, or description, of a patch. By default, it 1.16080 + prints the header of the topmost applied patch. Given an 1.16081 + argument, it prints the header of the named patch.</para> 1.16082 + 1.16083 + </sect2> 1.16084 + <sect2> 1.16085 + <title><command role="hg-ext-mq" moreinfo="none">qimport</command>—import 1.16086 + a third-party patch into the queue</title> 1.16087 + 1.16088 + <para id="x_5f8">The <command role="hg-ext-mq" moreinfo="none">qimport</command> command 1.16089 + adds an entry for an external patch to the <filename role="special" moreinfo="none">series</filename> file, and copies the patch 1.16090 + into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory. It adds 1.16091 + the entry immediately after the topmost applied patch, but 1.16092 + does not push the patch.</para> 1.16093 + 1.16094 + <para id="x_5f9">If the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a 1.16095 + repository, <command role="hg-ext-mq" moreinfo="none">qimport</command> 1.16096 + automatically does an <command role="hg-cmd" moreinfo="none">hg add</command> 1.16097 + of the imported patch.</para> 1.16098 + 1.16099 + </sect2> 1.16100 + <sect2> 1.16101 + <title><command role="hg-ext-mq" moreinfo="none">qinit</command>—prepare 1.16102 + a repository to work with MQ</title> 1.16103 + 1.16104 + <para id="x_5fa">The <command role="hg-ext-mq" moreinfo="none">qinit</command> command 1.16105 + prepares a repository to work with MQ. It creates a directory 1.16106 + called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>.</para> 1.16107 + 1.16108 + <para id="x_5fb">Options:</para> 1.16109 + <itemizedlist> 1.16110 + <listitem><para id="x_5fc"><option role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create 1.16111 + <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> as a repository 1.16112 + in its own right. Also creates a <filename role="special" moreinfo="none">.hgignore</filename> file that will 1.16113 + ignore the <filename role="special" moreinfo="none">status</filename> 1.16114 + file.</para> 1.16115 + </listitem></itemizedlist> 1.16116 + 1.16117 + <para id="x_5fd">When the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a 1.16118 + repository, the <command role="hg-ext-mq" moreinfo="none">qimport</command> 1.16119 + and <command role="hg-ext-mq" moreinfo="none">qnew</command> commands 1.16120 + automatically <command role="hg-cmd" moreinfo="none">hg add</command> new 1.16121 + patches.</para> 1.16122 + 1.16123 + </sect2> 1.16124 + <sect2> 1.16125 + <title><command role="hg-ext-mq" moreinfo="none">qnew</command>—create a 1.16126 + new patch</title> 1.16127 + 1.16128 + <para id="x_5fe">The <command role="hg-ext-mq" moreinfo="none">qnew</command> command 1.16129 + creates a new patch. It takes one mandatory argument, the 1.16130 + name to use for the patch file. The newly created patch is 1.16131 + created empty by default. It is added to the <filename role="special" moreinfo="none">series</filename> file after the current 1.16132 + topmost applied patch, and is immediately pushed on top of 1.16133 + that patch.</para> 1.16134 + 1.16135 + <para id="x_5ff">If <command role="hg-ext-mq" moreinfo="none">qnew</command> finds modified 1.16136 + files in the working directory, it will refuse to create a new 1.16137 + patch unless the <option role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used 1.16138 + (see below). This behavior allows you to <command role="hg-ext-mq" moreinfo="none">qrefresh</command> your topmost applied 1.16139 + patch before you apply a new patch on top of it.</para> 1.16140 + 1.16141 + <para id="x_600">Options:</para> 1.16142 + <itemizedlist> 1.16143 + <listitem><para id="x_601"><option role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new 1.16144 + patch if the contents of the working directory are 1.16145 + modified. Any outstanding modifications are added to the 1.16146 + newly created patch, so after this command completes, the 1.16147 + working directory will no longer be modified.</para> 1.16148 + </listitem> 1.16149 + <listitem><para id="x_602"><option role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given 1.16150 + text as the commit message. This text will be stored at 1.16151 + the beginning of the patch file, before the patch 1.16152 + data.</para> 1.16153 + </listitem></itemizedlist> 1.16154 + 1.16155 + </sect2> 1.16156 + <sect2> 1.16157 + <title><command role="hg-ext-mq" moreinfo="none">qnext</command>—print 1.16158 + the name of the next patch</title> 1.16159 + 1.16160 + <para id="x_603">The <command role="hg-ext-mq" moreinfo="none">qnext</command> command 1.16161 + prints the name name of the next patch in the <filename role="special" moreinfo="none">series</filename> file after the topmost 1.16162 + applied patch. This patch will become the topmost applied 1.16163 + patch if you run <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para> 1.16164 + 1.16165 + </sect2> 1.16166 + <sect2> 1.16167 + <title><command role="hg-ext-mq" moreinfo="none">qpop</command>—pop 1.16168 + patches off the stack</title> 1.16169 + 1.16170 + <para id="x_604">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command 1.16171 + removes applied patches from the top of the stack of applied 1.16172 + patches. By default, it removes only one patch.</para> 1.16173 + 1.16174 + <para id="x_605">This command removes the changesets that represent the 1.16175 + popped patches from the repository, and updates the working 1.16176 + directory to undo the effects of the patches.</para> 1.16177 + 1.16178 + <para id="x_606">This command takes an optional argument, which it uses as 1.16179 + the name or index of the patch to pop to. If given a name, it 1.16180 + will pop patches until the named patch is the topmost applied 1.16181 + patch. If given a number, <command role="hg-ext-mq" moreinfo="none">qpop</command> treats the number as an 1.16182 + index into the entries in the series file, counting from zero 1.16183 + (empty lines and lines containing only comments do not count). 1.16184 + It pops patches until the patch identified by the given index 1.16185 + is the topmost applied patch.</para> 1.16186 + 1.16187 + <para id="x_607">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command does 1.16188 + not read or write patches or the <filename role="special" moreinfo="none">series</filename> file. It is thus safe to 1.16189 + <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch that you have 1.16190 + removed from the <filename role="special" moreinfo="none">series</filename> 1.16191 + file, or a patch that you have renamed or deleted entirely. 1.16192 + In the latter two cases, use the name of the patch as it was 1.16193 + when you applied it.</para> 1.16194 + 1.16195 + <para id="x_608">By default, the <command role="hg-ext-mq" moreinfo="none">qpop</command> 1.16196 + command will not pop any patches if the working directory has 1.16197 + been modified. You can override this behavior using the 1.16198 + <option role="hg-ext-mq-cmd-qpop-opt">-f</option> option, 1.16199 + which reverts all modifications in the working 1.16200 + directory.</para> 1.16201 + 1.16202 + <para id="x_609">Options:</para> 1.16203 + <itemizedlist> 1.16204 + <listitem><para id="x_60a"><option role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all 1.16205 + applied patches. This returns the repository to its state 1.16206 + before you applied any patches.</para> 1.16207 + </listitem> 1.16208 + <listitem><para id="x_60b"><option role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly 1.16209 + revert any modifications to the working directory when 1.16210 + popping.</para> 1.16211 + </listitem> 1.16212 + <listitem><para id="x_60c"><option role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch 1.16213 + from the named queue.</para> 1.16214 + </listitem></itemizedlist> 1.16215 + 1.16216 + <para id="x_60d">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command 1.16217 + removes one line from the end of the <filename role="special" moreinfo="none">status</filename> file for each patch that it 1.16218 + pops.</para> 1.16219 + 1.16220 + </sect2> 1.16221 + <sect2> 1.16222 + <title><command role="hg-ext-mq" moreinfo="none">qprev</command>—print 1.16223 + the name of the previous patch</title> 1.16224 + 1.16225 + <para id="x_60e">The <command role="hg-ext-mq" moreinfo="none">qprev</command> command 1.16226 + prints the name of the patch in the <filename role="special" moreinfo="none">series</filename> file that comes before the 1.16227 + topmost applied patch. This will become the topmost applied 1.16228 + patch if you run <command role="hg-ext-mq" moreinfo="none">qpop</command>.</para> 1.16229 + 1.16230 + </sect2> 1.16231 + <sect2 id="sec:mqref:cmd:qpush"> 1.16232 + <title><command role="hg-ext-mq" moreinfo="none">qpush</command>—push 1.16233 + patches onto the stack</title> 1.16234 + 1.16235 + <para id="x_60f">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command adds 1.16236 + patches onto the applied stack. By default, it adds only one 1.16237 + patch.</para> 1.16238 + 1.16239 + <para id="x_610">This command creates a new changeset to represent each 1.16240 + applied patch, and updates the working directory to apply the 1.16241 + effects of the patches.</para> 1.16242 + 1.16243 + <para id="x_611">The default data used when creating a changeset are as 1.16244 + follows:</para> 1.16245 + <itemizedlist> 1.16246 + <listitem><para id="x_612">The commit date and time zone are the current 1.16247 + date and time zone. Because these data are used to 1.16248 + compute the identity of a changeset, this means that if 1.16249 + you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and 1.16250 + <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the 1.16251 + changeset that you push will have a different identity 1.16252 + than the changeset you popped.</para> 1.16253 + </listitem> 1.16254 + <listitem><para id="x_613">The author is the same as the default used by 1.16255 + the <command role="hg-cmd" moreinfo="none">hg commit</command> 1.16256 + command.</para> 1.16257 + </listitem> 1.16258 + <listitem><para id="x_614">The commit message is any text from the patch 1.16259 + file that comes before the first diff header. If there is 1.16260 + no such text, a default commit message is used that 1.16261 + identifies the name of the patch.</para> 1.16262 + </listitem></itemizedlist> 1.16263 + <para id="x_615">If a patch contains a Mercurial patch header, 1.16264 + the information in the patch header overrides these 1.16265 + defaults.</para> 1.16266 + 1.16267 + <para id="x_616">Options:</para> 1.16268 + <itemizedlist> 1.16269 + <listitem><para id="x_617"><option role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all 1.16270 + unapplied patches from the <filename role="special" moreinfo="none">series</filename> file until there are 1.16271 + none left to push.</para> 1.16272 + </listitem> 1.16273 + <listitem><para id="x_618"><option role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name 1.16274 + of the patch to the end of the commit message.</para> 1.16275 + </listitem> 1.16276 + <listitem><para id="x_619"><option role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch 1.16277 + fails to apply cleanly, use the entry for the patch in 1.16278 + another saved queue to compute the parameters for a 1.16279 + three-way merge, and perform a three-way merge using the 1.16280 + normal Mercurial merge machinery. Use the resolution of 1.16281 + the merge as the new patch content.</para> 1.16282 + </listitem> 1.16283 + <listitem><para id="x_61a"><option role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the 1.16284 + named queue if merging while pushing.</para> 1.16285 + </listitem></itemizedlist> 1.16286 + 1.16287 + <para id="x_61b">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command 1.16288 + reads, but does not modify, the <filename role="special" moreinfo="none">series</filename> file. It appends one line 1.16289 + to the <command role="hg-cmd" moreinfo="none">hg status</command> file for 1.16290 + each patch that it pushes.</para> 1.16291 + 1.16292 + </sect2> 1.16293 + <sect2> 1.16294 + <title><command role="hg-ext-mq" moreinfo="none">qrefresh</command>—update the 1.16295 + topmost applied patch</title> 1.16296 + 1.16297 + <para id="x_61c">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command 1.16298 + updates the topmost applied patch. It modifies the patch, 1.16299 + removes the old changeset that represented the patch, and 1.16300 + creates a new changeset to represent the modified 1.16301 + patch.</para> 1.16302 + 1.16303 + <para id="x_61d">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command 1.16304 + looks for the following modifications:</para> 1.16305 + <itemizedlist> 1.16306 + <listitem><para id="x_61e">Changes to the commit message, i.e. the text 1.16307 + before the first diff header in the patch file, are 1.16308 + reflected in the new changeset that represents the 1.16309 + patch.</para> 1.16310 + </listitem> 1.16311 + <listitem><para id="x_61f">Modifications to tracked files in the working 1.16312 + directory are added to the patch.</para> 1.16313 + </listitem> 1.16314 + <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 1.16315 + and rename destinations are added to the patch, while 1.16316 + removed files and rename sources are removed.</para> 1.16317 + </listitem></itemizedlist> 1.16318 + 1.16319 + <para id="x_621">Even if <command role="hg-ext-mq" moreinfo="none">qrefresh</command> 1.16320 + detects no changes, it still recreates the changeset that 1.16321 + represents the patch. This causes the identity of the 1.16322 + changeset to differ from the previous changeset that 1.16323 + identified the patch.</para> 1.16324 + 1.16325 + <para id="x_622">Options:</para> 1.16326 + <itemizedlist> 1.16327 + <listitem><para id="x_623"><option role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify 1.16328 + the commit and patch description, using the preferred text 1.16329 + editor.</para> 1.16330 + </listitem> 1.16331 + <listitem><para id="x_624"><option role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify 1.16332 + the commit message and patch description, using the given 1.16333 + text.</para> 1.16334 + </listitem> 1.16335 + <listitem><para id="x_625"><option role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify 1.16336 + the commit message and patch description, using text from 1.16337 + the given file.</para> 1.16338 + </listitem></itemizedlist> 1.16339 + 1.16340 + </sect2> 1.16341 + <sect2> 1.16342 + <title><command role="hg-ext-mq" moreinfo="none">qrename</command>—rename 1.16343 + a patch</title> 1.16344 + 1.16345 + <para id="x_626">The <command role="hg-ext-mq" moreinfo="none">qrename</command> command 1.16346 + renames a patch, and changes the entry for the patch in the 1.16347 + <filename role="special" moreinfo="none">series</filename> file.</para> 1.16348 + 1.16349 + <para id="x_627">With a single argument, <command role="hg-ext-mq" moreinfo="none">qrename</command> renames the topmost 1.16350 + applied patch. With two arguments, it renames its first 1.16351 + argument to its second.</para> 1.16352 + 1.16353 + </sect2> 1.16354 + <sect2> 1.16355 + <title><command role="hg-ext-mq" moreinfo="none">qseries</command>—print 1.16356 + the entire patch series</title> 1.16357 + 1.16358 + <para id="x_62a">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command 1.16359 + prints the entire patch series from the <filename role="special" moreinfo="none">series</filename> file. It prints only patch 1.16360 + names, not empty lines or comments. It prints in order from 1.16361 + first to be applied to last.</para> 1.16362 + 1.16363 + </sect2> 1.16364 + <sect2> 1.16365 + <title><command role="hg-ext-mq" moreinfo="none">qtop</command>—print the 1.16366 + name of the current patch</title> 1.16367 + 1.16368 + <para id="x_62b">The <command role="hg-ext-mq" moreinfo="none">qtop</command> prints the 1.16369 + name of the topmost currently applied patch.</para> 1.16370 + 1.16371 + </sect2> 1.16372 + <sect2> 1.16373 + <title><command role="hg-ext-mq" moreinfo="none">qunapplied</command>—print patches 1.16374 + not yet applied</title> 1.16375 + 1.16376 + <para id="x_62c">The <command role="hg-ext-mq" moreinfo="none">qunapplied</command> command 1.16377 + prints the names of patches from the <filename role="special" moreinfo="none">series</filename> file that are not yet 1.16378 + applied. It prints them in order from the next patch that 1.16379 + will be pushed to the last.</para> 1.16380 + 1.16381 + </sect2> 1.16382 + <sect2> 1.16383 + <title><command role="hg-cmd" moreinfo="none">hg strip</command>—remove a 1.16384 + revision and descendants</title> 1.16385 + 1.16386 + <para id="x_62d">The <command role="hg-cmd" moreinfo="none">hg strip</command> command 1.16387 + removes a revision, and all of its descendants, from the 1.16388 + repository. It undoes the effects of the removed revisions 1.16389 + from the repository, and updates the working directory to the 1.16390 + first parent of the removed revision.</para> 1.16391 + 1.16392 + <para id="x_62e">The <command role="hg-cmd" moreinfo="none">hg strip</command> command 1.16393 + saves a backup of the removed changesets in a bundle, so that 1.16394 + they can be reapplied if removed in error.</para> 1.16395 + 1.16396 + <para id="x_62f">Options:</para> 1.16397 + <itemizedlist> 1.16398 + <listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save 1.16399 + unrelated changesets that are intermixed with the stripped 1.16400 + changesets in the backup bundle.</para> 1.16401 + </listitem> 1.16402 + <listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a 1.16403 + branch has multiple heads, remove all heads.</para> 1.16404 + </listitem> 1.16405 + <listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do 1.16406 + not save a backup bundle.</para> 1.16407 + </listitem></itemizedlist> 1.16408 + 1.16409 + </sect2> 1.16410 + </sect1> 1.16411 + <sect1> 1.16412 + <title>MQ file reference</title> 1.16413 + 1.16414 + <sect2> 1.16415 + <title>The <filename role="special" moreinfo="none">series</filename> 1.16416 + file</title> 1.16417 + 1.16418 + <para id="x_633">The <filename role="special" moreinfo="none">series</filename> file 1.16419 + contains a list of the names of all patches that MQ can apply. 1.16420 + It is represented as a list of names, with one name saved per 1.16421 + line. Leading and trailing white space in each line are 1.16422 + ignored.</para> 1.16423 + 1.16424 + <para id="x_634">Lines may contain comments. A comment begins with the 1.16425 + <quote><literal moreinfo="none">#</literal></quote> character, and extends to 1.16426 + the end of the line. Empty lines, and lines that contain only 1.16427 + comments, are ignored.</para> 1.16428 + 1.16429 + <para id="x_635">You will often need to edit the <filename role="special" moreinfo="none">series</filename> file by hand, hence the 1.16430 + support for comments and empty lines noted above. For 1.16431 + example, you can comment out a patch temporarily, and <command role="hg-ext-mq" moreinfo="none">qpush</command> will skip over that patch 1.16432 + when applying patches. You can also change the order in which 1.16433 + patches are applied by reordering their entries in the 1.16434 + <filename role="special" moreinfo="none">series</filename> file.</para> 1.16435 + 1.16436 + <para id="x_636">Placing the <filename role="special" moreinfo="none">series</filename> 1.16437 + file under revision control is also supported; it is a good 1.16438 + idea to place all of the patches that it refers to under 1.16439 + revision control, as well. If you create a patch directory 1.16440 + using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> 1.16441 + option to <command role="hg-ext-mq" moreinfo="none">qinit</command>, this will 1.16442 + be done for you automatically.</para> 1.16443 + 1.16444 + </sect2> 1.16445 + <sect2> 1.16446 + <title>The <filename role="special" moreinfo="none">status</filename> 1.16447 + file</title> 1.16448 + 1.16449 + <para id="x_637">The <filename role="special" moreinfo="none">status</filename> file 1.16450 + contains the names and changeset hashes of all patches that MQ 1.16451 + currently has applied. Unlike the <filename role="special" moreinfo="none">series</filename> file, this file is not 1.16452 + intended for editing. You should not place this file under 1.16453 + revision control, or modify it in any way. It is used by MQ 1.16454 + strictly for internal book-keeping.</para> 1.16455 + 1.16456 + </sect2> 1.16457 + </sect1> 1.16458 +</appendix> 1.16459 + 1.16460 +<!-- 1.16461 +local variables: 1.16462 +sgml-parent-document: ("00book.xml" "book" "appendix") 1.16463 +end: 1.16464 +--> 1.16465 + 1.16466 + <!-- BEGIN appC --> 1.16467 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.16468 + 1.16469 +<appendix id="chap:srcinstall"> 1.16470 + <?dbhtml filename="installing-mercurial-from-source.html"?> 1.16471 + <title>Installer Mercurial à partir des sources</title> 1.16472 + 1.16473 + <sect1 id="sec:srcinstall:unixlike"> 1.16474 + <title>Pour un système Unix ou similaire</title> 1.16475 + 1.16476 + <para id="x_5e0">Si vous utilisez un système Unix ou similaire, pour lequel 1.16477 + une version récente de Python (2.3 ou plus) est disponible, l'installation 1.16478 + de Mercurial à partir des sources est simple.</para> 1.16479 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.16480 + <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> 1.16481 + </listitem> 1.16482 + <listitem><para id="x_5e2">Extrayez le paquet : </para> 1.16483 + <programlisting format="linespecific">gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting> 1.16484 + </listitem> 1.16485 + <listitem><para id="x_5e3">Allez dans le répertoires où les sources ont 1.16486 + été extraites et exécutez le script d'installation. Ce dernier compilera 1.16487 + Mercurial et l'installera dans votre répertoire utilisateur.</para> 1.16488 + <programlisting format="linespecific">cd mercurial-MYVERSION 1.16489 +python setup.py install --force --home=$HOME</programlisting> 1.16490 + </listitem> 1.16491 + </orderedlist> 1.16492 + <para id="x_5e4">Lorsque l'installation est terminée, Mercurial se 1.16493 + trouvera dans le répertoire <literal moreinfo="none">bin</literal> de votre répertoire 1.16494 + utilisateur. 1.16495 + N'oubliez pas de vérifier que ce répertoire se trouve dans la liste 1.16496 + des répertoires où votre shell recherche les exécutables.</para> 1.16497 + 1.16498 + <para id="x_5e5">Vous devrez vraisemblablement définir la variable 1.16499 + d'environnement <envar>PYTHONPATH</envar> de manière à ce que 1.16500 + l'exécutable de Mercurial puisse trouver le reste des paquets logiciels. 1.16501 + Par exemple, sur mon ordinateur portable, je dois le définir ainsi: 1.16502 + <literal moreinfo="none">/home/bos/lib/python</literal>. Le chemin exact à utiliser 1.16503 + dépendra de la manière dont Python aura été construit pour votre 1.16504 + système. Il ne devrait pas être difficile de le trouver. En cas de 1.16505 + doute, lisez le texte généré lors de l'installation ci-dessus, et 1.16506 + recherchez l'emplacement où le contenu du répertoire 1.16507 + <literal moreinfo="none">mercurial</literal> a été installé.</para> 1.16508 + 1.16509 + </sect1> 1.16510 + <sect1> 1.16511 + <title>Pour Windows</title> 1.16512 + 1.16513 + <para id="x_5e6">Construire et installer Mercurial sous Windows nécessite 1.16514 + des outils logiciels divers, une certaine connaissance technique et une 1.16515 + bonne dose de patience. Je vous <emphasis>déconseille fortement</emphasis> 1.16516 + de tenter de le faire si vous êtes un <quote>simple utilisateur</quote>. 1.16517 + A moins que vous n'ayez l'intention de "hacker" Mercurial, je vous 1.16518 + suggère d'avoir recours à un paquet d'installation de la version binaire.</para> 1.16519 + 1.16520 + <para id="x_5e7">Si vous avez vraiment l'intention de construire 1.16521 + Mercurial à partir des sources sous Windows, suivez les indications pour 1.16522 + 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>, 1.16523 + et préparez vous à un travail épineux.</para> 1.16524 + 1.16525 + </sect1> 1.16526 +</appendix> 1.16527 + 1.16528 +<!-- 1.16529 +local variables: 1.16530 +sgml-parent-document: ("00book.xml" "book" "appendix") 1.16531 +end: 1.16532 +--> 1.16533 + 1.16534 + <!-- BEGIN appD --> 1.16535 + <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 1.16536 + 1.16537 +<appendix id="cha:opl"> 1.16538 + <?dbhtml filename="open-publication-license.html"?> 1.16539 + <title>Open Publication License</title> 1.16540 + 1.16541 + <para id="x_638">Version 1.0, 8 June 1999</para> 1.16542 + 1.16543 + <sect1> 1.16544 + <title>Requirements on both unmodified and modified 1.16545 + versions</title> 1.16546 + 1.16547 + <para id="x_639">The Open Publication works may be reproduced and distributed 1.16548 + in whole or in part, in any medium physical or electronic, 1.16549 + provided that the terms of this license are adhered to, and that 1.16550 + this license or an incorporation of it by reference (with any 1.16551 + options elected by the author(s) and/or publisher) is displayed 1.16552 + in the reproduction.</para> 1.16553 + 1.16554 + <para id="x_63a">Proper form for an incorporation by reference is as 1.16555 + follows:</para> 1.16556 + 1.16557 + <blockquote> 1.16558 + <para id="x_63b"> Copyright (c) <emphasis>year</emphasis> by 1.16559 + <emphasis>author's name or designee</emphasis>. This material 1.16560 + may be distributed only subject to the terms and conditions 1.16561 + set forth in the Open Publication License, 1.16562 + v<emphasis>x.y</emphasis> or later (the latest version is 1.16563 + presently available at <ulink url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para> 1.16564 + </blockquote> 1.16565 + 1.16566 + <para id="x_63c">The reference must be immediately followed with any options 1.16567 + elected by the author(s) and/or publisher of the document (see 1.16568 + <xref linkend="sec:opl:options"/>).</para> 1.16569 + 1.16570 + <para id="x_63d">Commercial redistribution of Open Publication-licensed 1.16571 + material is permitted.</para> 1.16572 + 1.16573 + <para id="x_63e">Any publication in standard (paper) book form shall require 1.16574 + the citation of the original publisher and author. The publisher 1.16575 + and author's names shall appear on all outer surfaces of the 1.16576 + book. On all outer surfaces of the book the original publisher's 1.16577 + name shall be as large as the title of the work and cited as 1.16578 + possessive with respect to the title.</para> 1.16579 + 1.16580 + </sect1> 1.16581 + <sect1> 1.16582 + <title>Copyright</title> 1.16583 + 1.16584 + <para id="x_63f">The copyright to each Open Publication is owned by its 1.16585 + author(s) or designee.</para> 1.16586 + 1.16587 + </sect1> 1.16588 + <sect1> 1.16589 + <title>Scope of license</title> 1.16590 + 1.16591 + <para id="x_640">The following license terms apply to all Open Publication 1.16592 + works, unless otherwise explicitly stated in the 1.16593 + document.</para> 1.16594 + 1.16595 + <para id="x_641">Mere aggregation of Open Publication works or a portion of 1.16596 + an Open Publication work with other works or programs on the 1.16597 + same media shall not cause this license to apply to those other 1.16598 + works. The aggregate work shall contain a notice specifying the 1.16599 + inclusion of the Open Publication material and appropriate 1.16600 + copyright notice.</para> 1.16601 + 1.16602 + <para id="x_642"><emphasis role="bold">Severability</emphasis>. If any part 1.16603 + of this license is found to be unenforceable in any 1.16604 + jurisdiction, the remaining portions of the license remain in 1.16605 + force.</para> 1.16606 + 1.16607 + <para id="x_643"><emphasis role="bold">No warranty</emphasis>. Open 1.16608 + Publication works are licensed and provided <quote>as is</quote> 1.16609 + without warranty of any kind, express or implied, including, but 1.16610 + not limited to, the implied warranties of merchantability and 1.16611 + fitness for a particular purpose or a warranty of 1.16612 + non-infringement.</para> 1.16613 + 1.16614 + </sect1> 1.16615 + <sect1> 1.16616 + <title>Requirements on modified works</title> 1.16617 + 1.16618 + <para id="x_644">All modified versions of documents covered by this license, 1.16619 + including translations, anthologies, compilations and partial 1.16620 + documents, must meet the following requirements:</para> 1.16621 + 1.16622 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.16623 + <listitem><para id="x_645">The modified version must be labeled as 1.16624 + such.</para> 1.16625 + </listitem> 1.16626 + <listitem><para id="x_646">The person making the modifications must be 1.16627 + identified and the modifications dated.</para> 1.16628 + </listitem> 1.16629 + <listitem><para id="x_647">Acknowledgement of the original author and 1.16630 + publisher if applicable must be retained according to normal 1.16631 + academic citation practices.</para> 1.16632 + </listitem> 1.16633 + <listitem><para id="x_648">The location of the original unmodified document 1.16634 + must be identified.</para> 1.16635 + </listitem> 1.16636 + <listitem><para id="x_649">The original author's (or authors') name(s) may 1.16637 + not be used to assert or imply endorsement of the resulting 1.16638 + document without the original author's (or authors') 1.16639 + permission.</para> 1.16640 + </listitem></orderedlist> 1.16641 + 1.16642 + </sect1> 1.16643 + <sect1> 1.16644 + <title>Good-practice recommendations</title> 1.16645 + 1.16646 + <para id="x_64a">In addition to the requirements of this license, it is 1.16647 + requested from and strongly recommended of redistributors 1.16648 + that:</para> 1.16649 + 1.16650 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.16651 + <listitem><para id="x_64b">If you are distributing Open Publication works 1.16652 + on hardcopy or CD-ROM, you provide email notification to the 1.16653 + authors of your intent to redistribute at least thirty days 1.16654 + before your manuscript or media freeze, to give the authors 1.16655 + time to provide updated documents. This notification should 1.16656 + describe modifications, if any, made to the document.</para> 1.16657 + </listitem> 1.16658 + <listitem><para id="x_64c">All substantive modifications (including 1.16659 + deletions) be either clearly marked up in the document or 1.16660 + else described in an attachment to the document.</para> 1.16661 + </listitem> 1.16662 + <listitem><para id="x_64d">Finally, while it is not mandatory under this 1.16663 + license, it is considered good form to offer a free copy of 1.16664 + any hardcopy and CD-ROM expression of an Open 1.16665 + Publication-licensed work to its author(s).</para> 1.16666 + </listitem></orderedlist> 1.16667 + 1.16668 + </sect1> 1.16669 + <sect1 id="sec:opl:options"> 1.16670 + <title>License options</title> 1.16671 + 1.16672 + <para id="x_64e">The author(s) and/or publisher of an Open 1.16673 + Publication-licensed document may elect certain options by 1.16674 + appending language to the reference to or copy of the license. 1.16675 + These options are considered part of the license instance and 1.16676 + must be included with the license (or its incorporation by 1.16677 + reference) in derived works.</para> 1.16678 + 1.16679 + <orderedlist inheritnum="ignore" continuation="restarts"> 1.16680 + <listitem><para id="x_64f">To prohibit distribution of substantively 1.16681 + modified versions without the explicit permission of the 1.16682 + author(s). <quote>Substantive modification</quote> is 1.16683 + defined as a change to the semantic content of the document, 1.16684 + and excludes mere changes in format or typographical 1.16685 + corrections.</para> 1.16686 + </listitem> 1.16687 + <listitem><para id="x_650"> To accomplish this, add the phrase 1.16688 + <quote>Distribution of substantively modified versions of 1.16689 + this document is prohibited without the explicit 1.16690 + permission of the copyright holder.</quote> to the license 1.16691 + reference or copy.</para> 1.16692 + </listitem> 1.16693 + <listitem><para id="x_651">To prohibit any publication of this work or 1.16694 + derivative works in whole or in part in standard (paper) 1.16695 + book form for commercial purposes is prohibited unless prior 1.16696 + permission is obtained from the copyright holder.</para> 1.16697 + </listitem> 1.16698 + <listitem><para id="x_652">To accomplish this, add the phrase 1.16699 + <quote>Distribution of the work or derivative of the work in 1.16700 + any standard (paper) book form is prohibited unless prior 1.16701 + permission is obtained from the copyright holder.</quote> 1.16702 + to the license reference or copy.</para> 1.16703 + </listitem></orderedlist> 1.16704 + 1.16705 + </sect1> 1.16706 +</appendix> 1.16707 + 1.16708 +<!-- 1.16709 +local variables: 1.16710 +sgml-parent-document: ("00book.xml" "book" "appendix") 1.16711 +end: 1.16712 +--> 1.16713 + 1.16714 +</book>