hgbook
annotate fr/complete.xml @ 1114:527b86d55d4a
inotify: update installation information
inotify is shipped in Mercurial since 1.0, which greatly simplifies the installation process
inotify is shipped in Mercurial since 1.0, which greatly simplifies the installation process
author | Nicolas Dumazet <nicdumz.commits@gmail.com> |
---|---|
date | Sun Dec 13 16:35:56 2009 +0900 (2009-12-13) |
parents | |
children |
rev | line source |
---|---|
belaran@999 | 1 <?xml version="1.0"?> |
belaran@999 | 2 |
belaran@999 | 3 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" |
belaran@999 | 4 "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"> |
belaran@999 | 5 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 6 <book id="hg"> |
belaran@999 | 7 <title>Mercurial: The Definitive Guide</title> |
belaran@999 | 8 |
belaran@999 | 9 <!-- hg parents --template '{node|short} ({date|shortdate})' |
belaran@999 | 10 <subtitle>Compiled from 8a1d3f1aff17 (2009-03-10)</subtitle> |
belaran@999 | 11 --> |
belaran@999 | 12 <subtitle>Compiled from $rev_id$</subtitle> |
belaran@999 | 13 <bookinfo> |
belaran@999 | 14 <edition>1</edition> |
belaran@999 | 15 <isbn>9780596800673</isbn> |
belaran@999 | 16 <authorgroup> |
belaran@999 | 17 <author> |
belaran@999 | 18 <firstname>Bryan</firstname> |
belaran@999 | 19 <surname>O'Sullivan</surname> |
belaran@999 | 20 </author> |
belaran@999 | 21 </authorgroup> |
belaran@999 | 22 |
belaran@999 | 23 <editor> |
belaran@999 | 24 <firstname>Mike</firstname> |
belaran@999 | 25 <surname>Loukides</surname> |
belaran@999 | 26 </editor> |
belaran@999 | 27 |
belaran@999 | 28 <copyright> |
belaran@999 | 29 <year>2006</year> |
belaran@999 | 30 <year>2007</year> |
belaran@999 | 31 <year>2008</year> |
belaran@999 | 32 <year>2009</year> |
belaran@999 | 33 <holder>Bryan O'Sullivan</holder> |
belaran@999 | 34 </copyright> |
belaran@999 | 35 </bookinfo> |
belaran@999 | 36 |
belaran@999 | 37 <!-- BEGIN ch00 --> |
belaran@999 | 38 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 39 |
belaran@999 | 40 <preface id="chap:preface"> |
belaran@999 | 41 <?dbhtml filename="preface.html"?> |
belaran@999 | 42 <title>Preface</title> |
belaran@999 | 43 |
belaran@999 | 44 <sect1> |
belaran@999 | 45 <title>Un conte technique</title> |
belaran@999 | 46 |
belaran@999 | 47 <para id="x_72e">Il y a quelques années, quand j'ai voulu expliqué |
belaran@999 | 48 pourquoi je pensais que le gestion de révision distribuée est importante, |
belaran@999 | 49 le domaine était encore si nouveau qu'il n'y avait presque aucune |
belaran@999 | 50 littérature publiée pour servir de référence aux personnes intéressées.</para> |
belaran@999 | 51 |
belaran@999 | 52 <para id="x_72f">Bien qu'à cette époque je passais beaucoup de temps |
belaran@999 | 53 à travailler sur les entrailles de Mercurial, je me suis mis à la |
belaran@999 | 54 rédaction de ce livre parce qu'il me semblait la manière la plus efficace |
belaran@999 | 55 d'aider notre logiciel à atteindre un vaste auditoire, toujours avec |
belaran@999 | 56 l'idée que la gestion de révision devrait être distribuée par nature. J'ai |
belaran@999 | 57 publié ce libre en ligne sous une licence libre pour la même raison : pour |
belaran@999 | 58 diffuser la parole auprès du monde.</para> |
belaran@999 | 59 |
belaran@999 | 60 <para id="x_730">Il y a un rythme familier à un bon livre sur un logiciel |
belaran@999 | 61 qui ressemble de près au fait de conter une histoire : Pourquoi ceci est ? |
belaran@999 | 62 Pourquoi ceci est important ? Comment peut il m'aider ? Comment m'en |
belaran@999 | 63 servir ? Dans ce livre, j'essaye de répondre à toutes ces questions pour |
belaran@999 | 64 la gestion de révision distribuée en général, et pour Mercurial en |
belaran@999 | 65 particulier.</para> |
belaran@999 | 66 </sect1> |
belaran@999 | 67 |
belaran@999 | 68 <sect1> |
belaran@999 | 69 <title>Merci de votre soutien à Mercurial</title> |
belaran@999 | 70 |
belaran@999 | 71 <para id="x_731">En achetant une copie de ce livre, vous soutenez le |
belaran@999 | 72 développement et la liberté de Mercurial en particulier, et dans |
belaran@999 | 73 l'Open Source, au logiciel libre en général. O'Reilly Media et |
belaran@999 | 74 moi-même donnons les revenus issus des ventes de ce livre à la |
belaran@999 | 75 Software Freedom Conservancy (<ulink url="http://www.softwarefreedom.org/">http://www.softwarefreedom.org/</ulink>) |
belaran@999 | 76 qui fournit un support juridique à Mercurial et à de |
belaran@999 | 77 nombreux autres projets Open Source proéminents et de qualité.</para> |
belaran@999 | 78 </sect1> |
belaran@999 | 79 |
belaran@999 | 80 <sect1> |
belaran@999 | 81 <title>Remerciements</title> |
belaran@999 | 82 |
belaran@999 | 83 <para id="x_732">Ce livre n'aurait pas vu le jour sans les |
belaran@999 | 84 efforts de Matt Mackal, l'auteur et le chef du projet Mercurial. |
belaran@999 | 85 Il est assisté très efficacement par des centaines de contributeurs |
belaran@999 | 86 volontaires à travers le monde.</para> |
belaran@999 | 87 |
belaran@999 | 88 <para id="x_733">Les enfants, Cian et Ruairi, ont toujours été prêt |
belaran@999 | 89 à m'aider à me reposer avec de merveilleux et impulsif jeux d'enfants. |
belaran@999 | 90 Je tiens aussi à remercier mon ex-femme, Shannon, pour son soutien. |
belaran@999 | 91 </para> |
belaran@999 | 92 |
belaran@999 | 93 <para id="x_734">Mes collègues et amis m'ont aidé et assisté de |
belaran@999 | 94 de nombreuses manières. Cette liste de personne est nécessaire mais très |
belaran@999 | 95 incomplète : Stephen Hahn, Karyn Ritter, Bonnie Corwin, James Vasile, |
belaran@999 | 96 Matt Norwood, Eben Moglen, Bradley Kuhn, Robert Walsh, Jeremy |
belaran@999 | 97 Fitzhardinge, Rachel Chalmers.</para> |
belaran@999 | 98 |
belaran@999 | 99 <para id="x_735">J'ai conçu ce livre de manière ouverte, en publiant |
belaran@999 | 100 des brouillons des chapitres du livre sur des site web, au fur et à |
belaran@999 | 101 mesure que je les réalisais. Leurs lecteurs m'ont fait des retours |
belaran@999 | 102 utilisant l'application web que j'avais développée. A la fin de sa |
belaran@999 | 103 conception, plus de 100 personnes m'avaient fait des commentaires, |
belaran@999 | 104 un chiffre incroyable quand l'on considère que ce système de |
belaran@999 | 105 commentaire n'a tourné que dans les deux derniers mois de la |
belaran@999 | 106 rédaction du livre.</para> |
belaran@999 | 107 |
belaran@999 | 108 <para id="x_736">J'aimerais particulièrement remercier les |
belaran@999 | 109 personnes suivantes, dont les commentaires représentent plus |
belaran@999 | 110 d'un tiers de l'ensemble de ces derniers. Je voudrais les |
belaran@999 | 111 remercier pour leur attention et effort à me faire des retours |
belaran@999 | 112 très détaillés.</para> |
belaran@999 | 113 |
belaran@999 | 114 <para id="x_737">Martin Geisler, Damien Cassou, Alexey Bakhirkin, Till Plewe, |
belaran@999 | 115 Dan Himes, Paul Sargent, Gokberk Hamurcu, Matthijs van der |
belaran@999 | 116 Vleuten, Michael Chermside, John Mulligan, Jordi Fita, Jon |
belaran@999 | 117 Parise.</para> |
belaran@999 | 118 |
belaran@999 | 119 <para id="x_738">Je souhaite aussi remercier l'aide des personnes |
belaran@999 | 120 qui ont découvert des erreurs et fournit des suggestions avisées |
belaran@999 | 121 à travers tout le livre.</para> |
belaran@999 | 122 |
belaran@999 | 123 <para id="x_739">Jeremy W. Sherman, Brian Mearns, Vincent Furia, Iwan |
belaran@999 | 124 Luijks, Billy Edwards, Andreas Sliwka, Paweł Sołyga, Eric |
belaran@999 | 125 Hanchrow, Steve Nicolai, Michał Masłowski, Kevin Fitch, Johan |
belaran@999 | 126 Holmberg, Hal Wine, Volker Simonis, Thomas P Jakobsen, Ted |
belaran@999 | 127 Stresen-Reuter, Stephen Rasku, Raphael Das Gupta, Ned |
belaran@999 | 128 Batchelder, Lou Keeble, Li Linxiao, Kao Cardoso Félix, Joseph |
belaran@999 | 129 Wecker, Jon Prescot, Jon Maken, John Yeary, Jason Harris, |
belaran@999 | 130 Geoffrey Zheng, Fredrik Jonson, Ed Davies, David Zumbrunnen, |
belaran@999 | 131 David Mercer, David Cabana, Ben Karel, Alan Franzoni, Yousry |
belaran@999 | 132 Abdallah, Whitney Young, Vinay Sajip, Tom Towle, Tim Ottinger, |
belaran@999 | 133 Thomas Schraitle, Tero Saarni, Ted Mielczarek, Svetoslav |
belaran@999 | 134 Agafonkin, Shaun Rowland, Rocco Rutte, Polo-Francois Poli, |
belaran@999 | 135 Philip Jenvey, Petr Tesałék, Peter R. Annema, Paul Bonser, |
belaran@999 | 136 Olivier Scherler, Olivier Fournier, Nick Parker, Nick Fabry, |
belaran@999 | 137 Nicholas Guarracino, Mike Driscoll, Mike Coleman, Mietek Bák, |
belaran@999 | 138 Michael Maloney, László Nagy, Kent Johnson, Julio Nobrega, Jord |
belaran@999 | 139 Fita, Jonathan March, Jonas Nockert, Jim Tittsler, Jeduan |
belaran@999 | 140 Cornejo Legorreta, Jan Larres, James Murphy, Henri Wiechers, |
belaran@999 | 141 Hagen Möbius, Gábor Farkas, Fabien Engels, Evert Rol, Evan |
belaran@999 | 142 Willms, Eduardo Felipe Castegnaro, Dennis Decker Jensen, Deniz |
belaran@999 | 143 Dogan, David Smith, Daed Lee, Christine Slotty, Charles Merriam, |
belaran@999 | 144 Guillaume Catto, Brian Dorsey, Bob Nystrom, Benoit Boissinot, |
belaran@999 | 145 Avi Rosenschein, Andrew Watts, Andrew Donkin, Alexey Rodriguez, |
belaran@999 | 146 Ahmed Chaudhary.</para> |
belaran@999 | 147 </sect1> |
belaran@999 | 148 |
belaran@999 | 149 <sect1> |
belaran@999 | 150 <title>Conventions utilisées dans ce livre</title> |
belaran@999 | 151 |
belaran@999 | 152 <para id="x_73a">Les conventions typographiques suivantes sont utilisées dans ce livre :</para> |
belaran@999 | 153 |
belaran@999 | 154 <variablelist> |
belaran@999 | 155 <varlistentry> |
belaran@999 | 156 <term>Italique</term> |
belaran@999 | 157 |
belaran@999 | 158 <listitem> |
belaran@999 | 159 <para id="x_73b">Indique les termes nouveaux, les URLs, les |
belaran@999 | 160 adresses mail, les noms de fichiers et les extensions de |
belaran@999 | 161 fichier.</para> |
belaran@999 | 162 </listitem> |
belaran@999 | 163 </varlistentry> |
belaran@999 | 164 |
belaran@999 | 165 <varlistentry> |
belaran@999 | 166 <term><literal moreinfo="none">Taille constante</literal></term> |
belaran@999 | 167 |
belaran@999 | 168 <listitem> |
belaran@999 | 169 <para id="x_73c">Utilisé pour les extraits de code, comme |
belaran@999 | 170 dans les paragraphes pour référer aux éléments du programme, |
belaran@999 | 171 tels que les variables ou les noms de fonctions, de bases |
belaran@999 | 172 de données, de types de données, de variables d'environnement, |
belaran@999 | 173 d'instructions, et de mots clés.</para> |
belaran@999 | 174 </listitem> |
belaran@999 | 175 </varlistentry> |
belaran@999 | 176 |
belaran@999 | 177 <varlistentry> |
belaran@999 | 178 <term><userinput moreinfo="none">Taille constante avec gras</userinput></term> |
belaran@999 | 179 |
belaran@999 | 180 <listitem> |
belaran@999 | 181 <para id="x_73d">Afficher les commandes ou autres textes qui |
belaran@999 | 182 devraient être saisis par l'utilisateur.</para> |
belaran@999 | 183 </listitem> |
belaran@999 | 184 </varlistentry> |
belaran@999 | 185 |
belaran@999 | 186 <varlistentry> |
belaran@999 | 187 <term><replaceable>Constante avec italique</replaceable></term> |
belaran@999 | 188 |
belaran@999 | 189 <listitem> |
belaran@999 | 190 <para id="x_73e">Affiche les textes qui devraient être remplacés |
belaran@999 | 191 par une valeur définie par l'utilisateur ou des valeurs définies |
belaran@999 | 192 selon le contexte.</para> |
belaran@999 | 193 </listitem> |
belaran@999 | 194 </varlistentry> |
belaran@999 | 195 </variablelist> |
belaran@999 | 196 |
belaran@999 | 197 <tip> |
belaran@999 | 198 <para id="x_73f">Cette icône indique une astuce, une suggestion ou |
belaran@999 | 199 une note d'ordre général.</para> |
belaran@999 | 200 </tip> |
belaran@999 | 201 |
belaran@999 | 202 <caution> |
belaran@999 | 203 <para id="x_740">Cette icône est un message d'alerte ou de prudence.</para> |
belaran@999 | 204 </caution> |
belaran@999 | 205 </sect1> |
belaran@999 | 206 |
belaran@999 | 207 <sect1> |
belaran@999 | 208 <title>Utiliser les exemples de code</title> |
belaran@999 | 209 |
belaran@999 | 210 <para id="x_741">Ce livre est ici pour vous aider dans votre |
belaran@999 | 211 travail. De manière générale, vous pouvez donc utiliser le code |
belaran@999 | 212 de ce livre dans vos programmes et votre documentation. Vous |
belaran@999 | 213 n'avez pas à nous contacter pour nous demander la permission |
belaran@999 | 214 de le faire, à moins que vous ne reproduisiez une partie significative |
belaran@999 | 215 du code. Par exemple, écrire un programme qui utilise plusieurs |
belaran@999 | 216 extraits de code du livre ne demande aucune autorisation particulière. |
belaran@999 | 217 Vendre ou distribuer un CD-ROM provenant des livres O'Reilly demande |
belaran@999 | 218 à l'inverse une autorisation. Répondre à une question en citant ce |
belaran@999 | 219 livre ou ses exemples de code ne demande aucune autorisation préalable. |
belaran@999 | 220 Intégrer une grande quantité des codes d'exemples de ce livre dans |
belaran@999 | 221 votre propre ouvrage demande une autorisation de notre part.</para> |
belaran@999 | 222 |
belaran@999 | 223 <para id="x_742">Nous apprécions, sans l'exiger, que vous citiez |
belaran@999 | 224 l'ouvrage dans vos écrits l'utilisant, en indiquant le titre, |
belaran@999 | 225 l'auteur, l'éditeur et son ISBN. Par exemple: “<emphasis>Titre du |
belaran@999 | 226 livre</emphasis> par Son Auteur. Copyright 2008 O’Reilly Media, Inc., |
belaran@999 | 227 978-0-596-xxxx-x.”</para> |
belaran@999 | 228 |
belaran@999 | 229 <para id="x_743">Si vous estimez que votre usage des exemples de code |
belaran@999 | 230 dépasse le cadre défini ci dessus, n'hésitez pas à nous contacter : |
belaran@999 | 231 <email>permissions@oreilly.com</email>.</para> |
belaran@999 | 232 </sect1> |
belaran@999 | 233 |
belaran@999 | 234 <sect1> |
belaran@999 | 235 <title>Safari® Books Online</title> |
belaran@999 | 236 |
belaran@999 | 237 <note role="safarienabled"> |
belaran@999 | 238 <para id="x_744">Quand vous voyez l'icône de Safari® Books Online |
belaran@999 | 239 sur la couverture d'un de vos livres techniques préférés, cela signifie |
belaran@999 | 240 que le livre est disponible, en ligne, à travers le O’Reilly Network Safari |
belaran@999 | 241 Bookshelf.</para> |
belaran@999 | 242 </note> |
belaran@999 | 243 |
belaran@999 | 244 <para id="x_745">Safari offre une solution qui est meilleure que |
belaran@999 | 245 les e-books. C'est une bibliothèque virtuelle qui vous laisse |
belaran@999 | 246 aisément rechercher dans des milliers de livres, mais aussi |
belaran@999 | 247 copier-coller leurs exemples, télécharger des chapitres, et |
belaran@999 | 248 trouver des réponses rapides quand vous avez besoin d'une |
belaran@999 | 249 information précise et à jour. Essayez le gratuitement : |
belaran@999 | 250 <ulink role="orm:hideurl:ital" url="http://my.safaribooksonline.com/?portal=oreilly">http://my.safaribooksonline.com</ulink>.</para> |
belaran@999 | 251 </sect1> |
belaran@999 | 252 |
belaran@999 | 253 <sect1> |
belaran@999 | 254 <title>Comment nous contacter</title> |
belaran@999 | 255 |
belaran@999 | 256 <para id="x_746">Merci d'adresser vos commentaires et vos questions |
belaran@999 | 257 sur ce livre à son éditeur:</para> |
belaran@999 | 258 |
belaran@999 | 259 <simplelist type="vert"> |
belaran@999 | 260 <member>O’Reilly Media, Inc.</member> |
belaran@999 | 261 |
belaran@999 | 262 <member>1005 Gravenstein Highway North</member> |
belaran@999 | 263 |
belaran@999 | 264 <member>Sebastopol, CA 95472</member> |
belaran@999 | 265 |
belaran@999 | 266 <member>800-998-9938 (in the United States or Canada)</member> |
belaran@999 | 267 |
belaran@999 | 268 <member>707-829-0515 (international or local)</member> |
belaran@999 | 269 |
belaran@999 | 270 <member>707 829-0104 (fax)</member> |
belaran@999 | 271 </simplelist> |
belaran@999 | 272 |
belaran@999 | 273 <para id="x_747">Nous avons une page web pour cet ouvrage, où nous |
belaran@999 | 274 publions des errata, des exemples, et encore d'autres informations |
belaran@999 | 275 additionnelles. Vous pouvez accéder à cette page par l'URL suivante: |
belaran@999 | 276 </para> |
belaran@999 | 277 |
belaran@999 | 278 <simplelist type="vert"> |
belaran@999 | 279 <member><ulink url="http://www.oreilly.com/catalog/<catalog page>"/></member> |
belaran@999 | 280 </simplelist> |
belaran@999 | 281 |
belaran@999 | 282 <remark>N'oubliez pas de mettre à jour l'attribut <url> aussi.</remark> |
belaran@999 | 283 |
belaran@999 | 284 <para id="x_748">Pour commenter ou poser des questions techniques |
belaran@999 | 285 sur cet ouvrage, envoyez un email à :</para> |
belaran@999 | 286 |
belaran@999 | 287 <simplelist type="vert"> |
belaran@999 | 288 <member><email>bookquestions@oreilly.com</email></member> |
belaran@999 | 289 </simplelist> |
belaran@999 | 290 |
belaran@999 | 291 <para id="x_749">Pour plus d'informations sur nos livres, nos |
belaran@999 | 292 conférences, nos centres d'informations, et le réseau O’Reilly, |
belaran@999 | 293 voyez notre site web :</para> |
belaran@999 | 294 |
belaran@999 | 295 <simplelist type="vert"> |
belaran@999 | 296 <member><ulink url="http://www.oreilly.com"/></member> |
belaran@999 | 297 </simplelist> |
belaran@999 | 298 </sect1> |
belaran@999 | 299 </preface> |
belaran@999 | 300 |
belaran@999 | 301 <!-- |
belaran@999 | 302 local variables: |
belaran@999 | 303 sgml-parent-document: ("00book.xml" "book" "preface") |
belaran@999 | 304 end: |
belaran@999 | 305 --> |
belaran@999 | 306 |
belaran@999 | 307 <!-- BEGIN ch01 --> |
belaran@999 | 308 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 309 |
belaran@999 | 310 <chapter id="chap:intro"> |
belaran@999 | 311 <?dbhtml filename="how-did-we-get-here.html"?> |
belaran@999 | 312 <title>Comment en est on arrivé là ?</title> |
belaran@999 | 313 |
belaran@999 | 314 <sect1> |
belaran@999 | 315 <title>À propos de la gestion source</title> |
belaran@999 | 316 |
belaran@999 | 317 <para id="x_6d">La gestion de sources est un processus permettant de gérer différentes |
belaran@999 | 318 versions de la même information. Dans sa forme la plus simple, c'est |
belaran@999 | 319 ce que tout le monde fait manuellement : quand vous modifiez |
belaran@999 | 320 un fichier, vous le sauvegardez sous un nouveau nom contenant un numéro, |
belaran@999 | 321 à chaque fois plus grand que celui de la version précédente.</para> |
belaran@999 | 322 |
belaran@999 | 323 <para id="x_6e">Ce genre de gestion de version manuelle est cependant facilement sujette |
belaran@999 | 324 aux erreurs, ainsi, depuis longtemps, des logiciels existent pour |
belaran@999 | 325 résoudre cette problématique. Les premiers outils de gestion de sources |
belaran@999 | 326 étaient destinés à aider un seul utilisateur, à automatiser la gestion |
belaran@999 | 327 des versions d'un seul fichier. Dans les dernières décades, cette cible |
belaran@999 | 328 s'est largement agrandie, ils gèrent désormais de multiples fichiers, et |
belaran@999 | 329 aident un grand nombre de personnes à travailler ensemble. Les outils les |
belaran@999 | 330 plus modernes n'ont aucune difficulté à gérer plusieurs milliers de |
belaran@999 | 331 personnes travaillant ensemble sur des projets regroupant plusieurs |
belaran@999 | 332 centaines de milliers de fichiers.</para> |
belaran@999 | 333 |
belaran@999 | 334 <para id="x_6f">L'arrivée de la gestion de révision distribuée est |
belaran@999 | 335 relativement récente, et, pour le moment, ce nouveau domaine a grandi |
belaran@999 | 336 grâce à la volonté des gens d'explorer ces territoires encore inconnus. |
belaran@999 | 337 </para> |
belaran@999 | 338 |
belaran@999 | 339 <para id="x_70">J'écris un livre sur la gestion de révision distribuée |
belaran@999 | 340 parce que je pense qu'il s'agit d'un sujet important qui mérite un guide |
belaran@999 | 341 du terrain. J'ai choisi d'écrire un livre sur Mercurial car il est |
belaran@999 | 342 l'outil le plus facile pour découvrir ce nouveau domaine, tout en étant |
belaran@999 | 343 un outil efficace qui répond aux demandes d'environnements réels et |
belaran@999 | 344 difficiles, là où d'autres outils de gestions de versions s'effondrent.</para> |
belaran@999 | 345 |
belaran@999 | 346 <sect2> |
belaran@999 | 347 <title>Pourquoi utiliser un gestionnaire de source ?</title> |
belaran@999 | 348 |
belaran@999 | 349 <para id="x_71">Il y a de nombreuses raisons pour que vous ou votre équipe souhaitiez |
belaran@999 | 350 utiliser un outil automatisant la gestion de version pour votre projet.</para> |
belaran@999 | 351 |
belaran@999 | 352 <itemizedlist> |
belaran@999 | 353 <listitem><para id="x_72">L'outil se chargera de suivre l'évolution de votre projet, sans |
belaran@999 | 354 que vous ayez à le faire. Pour chaque modification, vous aurez à votre |
belaran@999 | 355 disposition un journal indiquant <emphasis>qui</emphasis> a fait quoi, <emphasis>pourquoi</emphasis> |
belaran@999 | 356 il l'a fait, <emphasis>quand</emphasis> il l'a fait, et |
belaran@999 | 357 <emphasis>ce</emphasis> qu'il a modifié.</para> |
belaran@999 | 358 </listitem> |
belaran@999 | 359 <listitem><para id="x_73">Quand vous travaillez avec d'autres personnes, les logiciels de |
belaran@999 | 360 gestion de source facilitent le travail collaboratif. Par exemple, quand |
belaran@999 | 361 plusieurs personnes font, plus ou moins simultanément, des modifications |
belaran@999 | 362 incompatibles, le logiciel vous aidera à identifier et à résoudre les conflits.</para> |
belaran@999 | 363 </listitem> |
belaran@999 | 364 <listitem><para id="x_74">L'outil vous aidera à réparer vos erreurs. Si vous effectuez un changement |
belaran@999 | 365 qui se révèle être une erreur, vous pourrez revenir à une version |
belaran@999 | 366 antérieure d'un fichier ou même d'un ensemble de fichiers. En fait, un outil de |
belaran@999 | 367 gestion de source <emphasis>vraiment</emphasis> efficace vous permettra d'identifier à quel |
belaran@999 | 368 moment le problème est apparu (voir la section <xref linkend="sec:undo:bisect"/> pour plus |
belaran@999 | 369 de détails).</para> |
belaran@999 | 370 </listitem> |
belaran@999 | 371 <listitem><para id="x_75">L'outil vous permettra aussi de travailler sur plusieurs versions différentes |
belaran@999 | 372 de votre projet et de gérer l'écart entre chacune.</para> |
belaran@999 | 373 </listitem></itemizedlist> |
belaran@999 | 374 <para id="x_76">La plupart de ces raisons ont autant d'importances —du |
belaran@999 | 375 moins en théorie— que vous travailliez sur un projet pour vous, ou |
belaran@999 | 376 avec une centaine d'autres personnes. |
belaran@999 | 377 </para> |
belaran@999 | 378 |
belaran@999 | 379 <para id="x_77">Une question fondamentale à propos des outils de gestion de |
belaran@999 | 380 source, qu'il s'agisse du projet d'une personne ou d'une grande équipe, est |
belaran@999 | 381 quels sont ses <emphasis>avantages</emphasis> par rapport à ses |
belaran@999 | 382 <emphasis>coûts</emphasis>. Un outil qui est difficile à utiliser ou à |
belaran@999 | 383 comprendre exigera un lourd effort d'adaptation. |
belaran@999 | 384 </para> |
belaran@999 | 385 |
belaran@999 | 386 <para id="x_78">)Un projet de cinq milles personnes s'effondrera très |
belaran@999 | 387 certainement de lui même sans aucun processus et outil de gestion de |
belaran@999 | 388 source. Dans ce cas, le coût d'utilisation d'un logiciel de gestion de |
belaran@999 | 389 source est dérisoire puisque <emphasis>sans</emphasis>, l'échec est presque |
belaran@999 | 390 garanti. |
belaran@999 | 391 </para> |
belaran@999 | 392 |
belaran@999 | 393 <para id="x_79">D'un autre coté, un <quote>rapide hack</quote> d'une personne |
belaran@999 | 394 peut sembler un contexte bien pauvre pour utiliser un outil de gestion de |
belaran@999 | 395 source, car, bien évidement le coût d'utilisation dépasse le coût total du |
belaran@999 | 396 projet. N'est ce pas ? |
belaran@999 | 397 </para> |
belaran@999 | 398 |
belaran@999 | 399 <para id="x_7a">Mercurial supporte ces <emphasis>deux</emphasis> |
belaran@999 | 400 échelles de travail. Vous pouvez apprendre les bases en quelques |
belaran@999 | 401 minutes seulement, et, grâce à sa performance, vous pouvez l'utiliser |
belaran@999 | 402 avec facilité sur le plus petit des projets. Cette simplicité |
belaran@999 | 403 signifie que vous n'avez pas de concept obscurs ou de séquence de |
belaran@999 | 404 commandes défiant l'imagination, sans aucune corrélation avec |
belaran@999 | 405 <emphasis>ce que vous êtes entrain de faire</emphasis>. En même |
belaran@999 | 406 temps, ces mêmes performances et sa nature |
belaran@999 | 407 <quote>peer-to-peer</quote> vous permettent d'adapter, sans |
belaran@999 | 408 difficulté, son utilisation à de très grands projets. |
belaran@999 | 409 </para> |
belaran@999 | 410 |
belaran@999 | 411 <para id="x_7b">Aucun outil de gestion de source ne peut sauver un |
belaran@999 | 412 projet mal mené, mais un bon outil peut rendre beaucoup plus fluide |
belaran@999 | 413 votre travail. |
belaran@999 | 414 </para> |
belaran@999 | 415 |
belaran@999 | 416 </sect2> |
belaran@999 | 417 |
belaran@999 | 418 <sect2> |
belaran@999 | 419 <title>Les multiples noms de la gestion de source</title> |
belaran@999 | 420 |
belaran@999 | 421 <para id="x_7c">La gestion de source |
belaran@999 | 422 <!-- TODO:<footnote><J'ai utilisé systématiquement le terme |
belaran@999 | 423 <quote>gestion de source</quote> à travers tout l'ouvrage. Ce |
belaran@999 | 424 n'est pas forcement la meilleure traduction, et ceci peut rendre |
belaran@999 | 425 la lecture un peu lourde, mais je pense que le document y gagne |
belaran@999 | 426 en clarté et en précision. --> |
belaran@999 | 427 est un domaine tellement large qu'il n'existe pas qu'un seul nom ou |
belaran@999 | 428 acronyme pour le désigner. Voici quelques noms ou acronymes que vous |
belaran@999 | 429 rencontrerez le plus souvent. |
belaran@999 | 430 <!-- TODO:<footnote> J'ai conservé la liste des noms en anglais pour |
belaran@999 | 431 des raisons de commodité (ils sont plus <quote>googelable</quote>). |
belaran@999 | 432 En outre, j'ai opté pour conserver l'ensemble des opérations de |
belaran@999 | 433 Mercurial (\textit{commit},\textit{push}, \textit{pull},...) en |
belaran@999 | 434 anglais, là aussi pour faciliter la lecture d'autres documents en |
belaran@999 | 435 anglais, ainsi que l'utilisation de Mercurial. --> |
belaran@999 | 436 </para> |
belaran@999 | 437 |
belaran@999 | 438 <para>: |
belaran@999 | 439 </para> |
belaran@999 | 440 |
belaran@999 | 441 <itemizedlist> |
belaran@999 | 442 <listitem><para id="x_7d">Revision control (RCS)</para></listitem> |
belaran@999 | 443 <listitem><para id="x_7e">Software configuration management (SCM), ou |
belaran@999 | 444 configuration management</para></listitem> |
belaran@999 | 445 <listitem><para id="x_7f">Source code management</para></listitem> |
belaran@999 | 446 <listitem><para id="x_80">Source code control, ou source control</para></listitem> |
belaran@999 | 447 <listitem><para id="x_81">Version control (VCS)</para></listitem></itemizedlist> |
belaran@999 | 448 |
belaran@999 | 449 <para id="x_82">Certaines personnes prétendent que ces termes ont en fait |
belaran@999 | 450 des sens différents mais en pratique ils se recouvrent tellement qu'il n'y |
belaran@999 | 451 a pas réellement de manière pertinente de les distinguer. </para> |
belaran@999 | 452 |
belaran@999 | 453 </sect2> |
belaran@999 | 454 </sect1> |
belaran@999 | 455 |
belaran@999 | 456 <sect1> |
belaran@999 | 457 |
belaran@999 | 458 <title>A propos des exemples dans ce livre</title> |
belaran@999 | 459 |
belaran@999 | 460 <para id="x_84">Ce livre prend une approche non usuel pour les exemples |
belaran@999 | 461 de code. Tous les exemples sont en <quote>live</quote> — Chacun |
belaran@999 | 462 est actuellement le résultat d'un script shell qui exécute les |
belaran@999 | 463 commandes Mercurial que vous voyez. A chaque fois qu'une image du livre |
belaran@999 | 464 est construite à partir des sources, tous les scripts d'exemple sont |
belaran@999 | 465 lancés automatiquement, et leurs résultats effectifs sont comparés aux |
belaran@999 | 466 résultats attendus.</para> |
belaran@999 | 467 |
belaran@999 | 468 <para id="x_85">L'avantage de dette approche est que les exemples sont |
belaran@999 | 469 toujours précis ; ils décrivent <emphasis>exactement</emphasis> la |
belaran@999 | 470 conduite de la version de Mercurial qui est mentionnée en entête du |
belaran@999 | 471 livre. Si je met à jour la version de Mercurial que je suis en train de |
belaran@999 | 472 documenter, et que la sortie de certaines commandes change, la |
belaran@999 | 473 construction du livre échoue.</para> |
belaran@999 | 474 |
belaran@999 | 475 <para id="x_86"> |
belaran@999 | 476 Il existe un petit désavantage à cette approche qui est que les dates et |
belaran@999 | 477 heures que vous verrez dans les exemples tendent à être |
belaran@999 | 478 <quote>écrasés</quote> ensemble, dans le sens où elles ne sont pas |
belaran@999 | 479 celles qu'elles auraient été si un humain avait tapé les commandes. En |
belaran@999 | 480 effet, humain ne peut pas taper plus d'une commande toutes les quelques |
belaran@999 | 481 secondes, avec le temps qui s'écoule, mes scripts d'exemples exécutent |
belaran@999 | 482 plusieurs commandes en une seconde. |
belaran@999 | 483 </para> |
belaran@999 | 484 |
belaran@999 | 485 <para id="x_87">Une circonstance de ceci est que plusieurs commits |
belaran@999 | 486 consécutifs dans un exemple peuvent apparaître comme ayant eu lieu |
belaran@999 | 487 durant la même seconde. |
belaran@999 | 488 Vous pouvez observer le phénomène dans l'exemple <literal role="hg-ext" moreinfo="none">bisect</literal> dans <xref linkend="sec:undo:bisect"/> |
belaran@999 | 489 </para> |
belaran@999 | 490 |
belaran@999 | 491 <para id="x_88">Donc, lorsque vous lisez ces exemples, ne prêtez pas trop |
belaran@999 | 492 d'importance aux dates et heures que vous voyez dans la sortie des |
belaran@999 | 493 commandes. Cependant, <emphasis>soyez</emphasis> confiants que le |
belaran@999 | 494 comportement que vous voyez est consistent et reproductible |
belaran@999 | 495 </para> |
belaran@999 | 496 |
belaran@999 | 497 </sect1> |
belaran@999 | 498 |
belaran@999 | 499 <!-- The next section has disapper from this part of the book. it may be splaced somewhere else... t--> |
belaran@999 | 500 |
belaran@999 | 501 <sect1> |
belaran@999 | 502 <title>Tendances de la gestion de source</title> |
belaran@999 | 503 |
belaran@999 | 504 <para id="x_89">Il y a eu une tendance évidente dans le développement et |
belaran@999 | 505 l'utilisation d'outils de gestion de source depuis les quatre dernières |
belaran@999 | 506 décades, au fur et à mesure que les utilisateurs se sont habitués à |
belaran@999 | 507 leur outils et se sont sentis contraints par leurs limitations. |
belaran@999 | 508 </para> |
belaran@999 | 509 |
belaran@999 | 510 <para id="x_8a">La première génération commença simplement par gérer un |
belaran@999 | 511 fichier unique sur un ordinateur individuel. Cependant, même si ces |
belaran@999 | 512 outils présentaient une grande avancée par rapport à la gestion |
belaran@999 | 513 manuelle des versions, leur modèle de verrouillage et leur utilisation |
belaran@999 | 514 limitée à un seul ordinateur rendaient leur utilisation possible |
belaran@999 | 515 uniquement dans une très petite équipe. |
belaran@999 | 516 </para> |
belaran@999 | 517 |
belaran@999 | 518 <para id="x_8b">La seconde génération a assoupli ces contraintes en |
belaran@999 | 519 adoptant une architecture réseau et centralisée, permettant de gérer |
belaran@999 | 520 plusieurs projets entiers en même temps. Alors que les projets |
belaran@999 | 521 grandirent en taille, ils rencontrèrent de nouveaux problèmes. Avec les |
belaran@999 | 522 clients discutant régulièrement avec le serveurs, la montée en charge |
belaran@999 | 523 devint un réel problème sur les gros projets. Une connexion réseau peu |
belaran@999 | 524 fiable pouvait complètement empêcher les utilisateurs distants de |
belaran@999 | 525 dialoguer avec le serveur. Alors que les projets <emphasis remap="it">Open Source</emphasis> commencèrent à mettre en place des |
belaran@999 | 526 accès en lecture seule disponible anonymement, les utilisateurs sans |
belaran@999 | 527 les privilèges de <quote>commit</quote> réalisèrent qu'ils ne pouvaient |
belaran@999 | 528 pas utiliser les outils pour collaborer naturellement avec le projet, |
belaran@999 | 529 comme ils ne pouvaient pas non plus enregistrer leurs modifications. |
belaran@999 | 530 </para> |
belaran@999 | 531 |
belaran@999 | 532 <para id="x_8c">La génération actuelle des outils de gestion de source |
belaran@999 | 533 est <quote>peer-to-peer</quote> par nature. Tous ces systèmes ont |
belaran@999 | 534 abandonné la dépendance à un serveur central, et ont permis à leur |
belaran@999 | 535 utilisateur de distribuer les données de leur gestion de source à qui |
belaran@999 | 536 en a besoin. La collaboration à travers Internet a transformé la |
belaran@999 | 537 contrainte technologique en une simple question de choix et de |
belaran@999 | 538 consensus. Les outils modernes peuvent maintenant fonctionner en mode |
belaran@999 | 539 déconnecté sans limite et de manière autonome, la connexion au réseau |
belaran@999 | 540 n'étant nécessaire que pour synchroniser les modifications avec les |
belaran@999 | 541 autres dépôts. |
belaran@999 | 542 </para> |
belaran@999 | 543 </sect1> |
belaran@999 | 544 |
belaran@999 | 545 <sect1> |
belaran@999 | 546 <title>Quelques avantages des gestionnaires de source distribués</title> |
belaran@999 | 547 |
belaran@999 | 548 <para id="x_8d">Même si les gestionnaire de source distribués sont depuis |
belaran@999 | 549 plusieurs années assez robustes et aussi utilisables que leurs |
belaran@999 | 550 prédécesseurs, les utilisateurs d'autres outils n'y ont pas encore été |
belaran@999 | 551 sensibilisés. Les gestionnaires de source distribués se distinguent |
belaran@999 | 552 particulièrement de leurs équivalents centralisés de nombreuses |
belaran@999 | 553 manières. |
belaran@999 | 554 </para> |
belaran@999 | 555 |
belaran@999 | 556 <para id="x_8e">Pour un développeur individuel, ils restent beaucoup plus |
belaran@999 | 557 rapides que les outils centralisés. Cela pour une raison simple : un |
belaran@999 | 558 outil centralisé doit toujours dialoguer à travers le réseau pour la |
belaran@999 | 559 plupart des opérations, car presque toutes les métadonnées sont |
belaran@999 | 560 stockées sur la seule copie du serveur central. Un outil distribué |
belaran@999 | 561 stocke toute ses métadonnées localement. À tâche égale, effectuer un |
belaran@999 | 562 échange avec le réseau ajoute un délai aux outils centralisés. Ne |
belaran@999 | 563 sous-estimez pas la valeur d'un outil rapide : vous allez passer |
belaran@999 | 564 beaucoup de temps à interagir avec un logiciel de gestion de source. |
belaran@999 | 565 </para> |
belaran@999 | 566 |
belaran@999 | 567 <para id="x_8f">Les outils distribués sont complètement indépendants des |
belaran@999 | 568 aléas de votre serveur, d'autant plus qu'ils répliquent les métadonnées |
belaran@999 | 569 à beaucoup d'endroits. Si votre serveur central prend feu, vous avez |
belaran@999 | 570 intérêt à ce que les médias de sauvegardes soient fiables, et que votre |
belaran@999 | 571 dernier <quote>backup</quote> soit récent et fonctionne sans problème. |
belaran@999 | 572 Avec un outil distribué, vous avez autant de <quote>backup</quote> que |
belaran@999 | 573 de contributeurs. |
belaran@999 | 574 </para> |
belaran@999 | 575 |
belaran@999 | 576 <para id="x_90">En outre, la fiabilité de votre réseau affectera beaucoup |
belaran@999 | 577 moins les outils distribués. Vous ne pouvez même pas utiliser un outil |
belaran@999 | 578 centralisé sans connexion réseau, à l'exception de quelques commandes, |
belaran@999 | 579 très limitées. Avec un outil distribué, si votre connexion réseau tombe |
belaran@999 | 580 pendant que vous travaillez, vous pouvez ne même pas vous en rendre |
belaran@999 | 581 compte. La seule chose que vous ne serez pas capable de faire sera de |
belaran@999 | 582 communiquer avec des dépôts distants, opération somme toute assez rare |
belaran@999 | 583 en comparaison aux opérations locales. Si vous avez une équipe de |
belaran@999 | 584 collaborateurs très dispersée ceci peut être significatif. |
belaran@999 | 585 </para> |
belaran@999 | 586 |
belaran@999 | 587 <sect2> |
belaran@999 | 588 <title>Avantages pour les projets Open Source</title> |
belaran@999 | 589 |
belaran@999 | 590 <para id="x_91">Si vous prenez goût à un projet <emphasis remap="it">Open Source</emphasis> et que vous décidez de commencer |
belaran@999 | 591 à toucher à son code, et que le projet utilise un gestionnaire de |
belaran@999 | 592 source distribué, vous êtes immédiatement un "pair" avec les |
belaran@999 | 593 personnes formant le <quote>cœur</quote> du projet. S'ils publient |
belaran@999 | 594 leurs dépôts, vous pouvez immédiatement copier leurs historiques de |
belaran@999 | 595 projet, faire des modifications, enregistrer votre travail en |
belaran@999 | 596 utilisant les mêmes outils qu'eux. Par comparaison avec un outil |
belaran@999 | 597 centralisé, vous devez utiliser un logiciel en mode <quote>lecture |
belaran@999 | 598 seule</quote> à moins que quelqu'un ne vous donne les privilèges de |
belaran@999 | 599 <quote>commit</quote> sur le serveur central. Avant ça, vous ne serez |
belaran@999 | 600 pas capable d'enregistrer vos modifications, et vos propres |
belaran@999 | 601 modifications risqueront de se corrompre chaque fois que vous |
belaran@999 | 602 essayerez de mettre à jour à votre espace de travail avec le serveur |
belaran@999 | 603 central. |
belaran@999 | 604 </para> |
belaran@999 | 605 |
belaran@999 | 606 <sect3> |
belaran@999 | 607 <title>Le non-problème du "fork"</title> |
belaran@999 | 608 |
belaran@999 | 609 <para id="x_92">Il a été souvent suggéré que les gestionnaires de |
belaran@999 | 610 source distribués posent un risque pour les projets <emphasis remap="it">Open Source</emphasis> car ils facilitent grandement la |
belaran@999 | 611 création de <quote>fork</quote>. |
belaran@999 | 612 <!--footnote{NdT:Création d'une <ulink url="version alternative du |
belaran@999 | 613 logiciel">version alternative du |
belaran@999 | 614 logiciel</ulink>{http://fr.wikipedia.org/wiki/Fork#Embranchement_d.27un_projet_informatique} |
belaran@999 | 615 --> |
belaran@999 | 616 Un <quote>fork</quote> apparait quand il y des divergences d'opinion |
belaran@999 | 617 ou d'attitude au sein d'un groupe de développeurs qui aboutissent à |
belaran@999 | 618 la décision de ne plus travailler ensemble. Chaque parti s'empare |
belaran@999 | 619 d'une copie plus ou moins complète du code source du projet et |
belaran@999 | 620 continue dans sa propre direction. |
belaran@999 | 621 </para> |
belaran@999 | 622 |
belaran@999 | 623 |
belaran@999 | 624 <para id="x_93">Parfois ces différents partis décident de se |
belaran@999 | 625 réconcilier. Avec un serveur central, l'aspect |
belaran@999 | 626 <emphasis>technique</emphasis> de cette réconciliation est un |
belaran@999 | 627 processus douloureux, et essentiellement manuel. Vous devez décider |
belaran@999 | 628 quelle modification est <quote>la gagnante</quote>, et replacer, par |
belaran@999 | 629 un moyen ou un autre, les modifications de l'autre équipe dans |
belaran@999 | 630 l'arborescence du projet. Ceci implique généralement la perte d'une |
belaran@999 | 631 partie de l'historique d'un des partis, ou même des deux. |
belaran@999 | 632 </para> |
belaran@999 | 633 |
belaran@999 | 634 <para id="x_94">Ce que les outils distribués permettent à ce sujet est |
belaran@999 | 635 probablement la <emphasis>meilleure</emphasis> façon de développer un |
belaran@999 | 636 projet. Chaque modification que vous effectuez est potentiellement un |
belaran@999 | 637 <quote>fork</quote>. La grande force de cette approche est que les |
belaran@999 | 638 gestionnaires de source distribués doivent être vraiment très |
belaran@999 | 639 efficaces pour <emphasis>fusionner (merge)</emphasis> |
belaran@999 | 640 <!-- TODO footnote{NdT:j'ai choisi de traduire ici <emphasis |
belaran@999 | 641 remap="it">merging</emphasis> par <quote>fusionner</quote> pour des |
belaran@999 | 642 raisons de clarté} --> |
belaran@999 | 643 des <quote>forks</quote>, car les <quote>forks</quote>, dans ce |
belaran@999 | 644 contexte, arrivent tout le temps. |
belaran@999 | 645 </para> |
belaran@999 | 646 |
belaran@999 | 647 <para id="x_95">Si chaque altération que n'importe qui effectue, à tout |
belaran@999 | 648 moment, est vue comme un <quote>fork</quote> à fusionner, alors ce |
belaran@999 | 649 que le monde de l'<emphasis remap="it">Open Source</emphasis> voit |
belaran@999 | 650 comme un <quote>fork</quote> devient <emphasis>uniquement</emphasis> |
belaran@999 | 651 une problématique sociale. En fait, les outils de gestions de source |
belaran@999 | 652 distribués <emphasis>réduisent</emphasis> les chances de |
belaran@999 | 653 <quote>fork</quote> : |
belaran@999 | 654 </para> |
belaran@999 | 655 |
belaran@999 | 656 <itemizedlist> |
belaran@999 | 657 <listitem> |
belaran@999 | 658 <para>Ils éliminent la distinction sociale qu'imposent les outils |
belaran@999 | 659 centralisés entre les membres du projets (ceux qui ont accès au |
belaran@999 | 660 <quote>commit</quote>) et ceux de l'extérieur (ce qui ne l'ont |
belaran@999 | 661 pas). |
belaran@999 | 662 </para> |
belaran@999 | 663 <para>Ils rendent plus facile la réconciliation après un |
belaran@999 | 664 <quote>fork</quote> social, car tout ce qu'elle implique est une |
belaran@999 | 665 simple fusion. |
belaran@999 | 666 </para> |
belaran@999 | 667 </listitem> |
belaran@999 | 668 </itemizedlist> |
belaran@999 | 669 |
belaran@999 | 670 <para id="x_98">Certaines personnes font de la résistance envers les |
belaran@999 | 671 gestionnaires de source distribués parce qu'ils veulent garder un |
belaran@999 | 672 contrôle ferme sur leur projet, et ils pensent que les outils |
belaran@999 | 673 centralisés leur fournissent ce contrôle. Néanmoins, si c'est votre |
belaran@999 | 674 cas, sachez que si vous publiez votre dépôt CVS ou Subversion de |
belaran@999 | 675 manière publique, il existe une quantité d'outils disponibles pour |
belaran@999 | 676 récupérer entièrement votre projet et son historique (quoique |
belaran@999 | 677 lentement) et le récréer ailleurs, sans votre contrôle. En fait, |
belaran@999 | 678 votre contrôle sur votre projet est illusoire, vous ne faites |
belaran@999 | 679 qu'interdire à vos collaborateurs de travailler de manière fluide, en |
belaran@999 | 680 disposant d'un miroir ou d'un <quote>fork</quote> de votre |
belaran@999 | 681 historique. |
belaran@999 | 682 </para> |
belaran@999 | 683 |
belaran@999 | 684 </sect3> |
belaran@999 | 685 </sect2> |
belaran@999 | 686 <sect2> |
belaran@999 | 687 <title>Avantages pour les projets commerciaux</title> |
belaran@999 | 688 |
belaran@999 | 689 <para id="x_99">Beaucoup de projets commerciaux sont réalisés par des |
belaran@999 | 690 équipes éparpillées à travers le globe. Les contributeurs qui sont |
belaran@999 | 691 loin du serveur central devront subir des commandes lentes et même |
belaran@999 | 692 parfois peu fiables. Les solutions propriétaires de gestion de source |
belaran@999 | 693 tentent de palier ce problème avec des réplications de sites distants |
belaran@999 | 694 qui sont à la fois coûteuses à mettre en place et lourdes à |
belaran@999 | 695 administrer. Un système distribué ne souffre pas de ce genre de |
belaran@999 | 696 problèmes. En outre, il est très aisé de mettre en place plusieurs |
belaran@999 | 697 serveurs de références, disons un par site, de manière à ce qu'il n'y |
belaran@999 | 698 ait pas de communication redondante entre les dépôts, sur une |
belaran@999 | 699 connexion longue distance souvent onéreuse. |
belaran@999 | 700 </para> |
belaran@999 | 701 |
belaran@999 | 702 <para id="x_9a">Les systèmes de gestion de source supportent |
belaran@999 | 703 généralement assez mal la monté en charge. Il n'est pas rare pour un |
belaran@999 | 704 gestionnaire de source centralisé pourtant onéreux de s'effondrer |
belaran@999 | 705 sous la charge combinée d'une douzaine d'utilisateurs concurrents |
belaran@999 | 706 seulement. Une fois encore, la réponse à cette problématique est |
belaran@999 | 707 généralement encore la mise en place d'un ensemble complexe de |
belaran@999 | 708 serveurs synchronisés par un mécanisme de réplication. Dans le cas |
belaran@999 | 709 d'un gestionnaire de source distribué, la charge du serveur central |
belaran@999 | 710 — si vous avez un— est plusieurs fois inférieure (car |
belaran@999 | 711 toutes les données sont déjà répliquées ailleurs), un simple serveur, |
belaran@999 | 712 pas très cher, peut gérer les besoins d'une plus grande équipe, et la |
belaran@999 | 713 réplication pour balancer la charge devient le travail d'un simple |
belaran@999 | 714 script. |
belaran@999 | 715 </para> |
belaran@999 | 716 |
belaran@999 | 717 <para id="x_9b">Si vous avez des employés sur le terrain, en train de |
belaran@999 | 718 chercher à résoudre un souci sur le site d'un client, ils |
belaran@999 | 719 bénéficieront aussi d'un gestionnaire de source distribué. Cet outil |
belaran@999 | 720 leur permettra de générer des versions personnalisées, d'essayer |
belaran@999 | 721 différentes solutions, en les isolant aisément les unes des autres, |
belaran@999 | 722 et de rechercher efficacement à travers l'historique des sources, la |
belaran@999 | 723 cause des bugs ou des régressions, tout ceci sans avoir besoin de la |
belaran@999 | 724 moindre connexion au réseau de votre compagnie. |
belaran@999 | 725 </para> |
belaran@999 | 726 |
belaran@999 | 727 </sect2> |
belaran@999 | 728 </sect1> |
belaran@999 | 729 <sect1> |
belaran@999 | 730 <title>Pourquoi choisir Mercurial?</title> |
belaran@999 | 731 |
belaran@999 | 732 <para id="x_9c">Mercurial a plusieurs caractéristiques qui en font un |
belaran@999 | 733 choix particulièrement pertinent pour la gestion de source : |
belaran@999 | 734 </para> |
belaran@999 | 735 <itemizedlist> |
belaran@999 | 736 <listitem><para id="x_9d">Il est simple à apprendre et à utiliser.</para></listitem> |
belaran@999 | 737 <listitem><para id="x_9e">Il est léger.</para></listitem> |
belaran@999 | 738 <listitem><para id="x_9f">Il s'adapte très bien à la charge.</para></listitem> |
belaran@999 | 739 <listitem><para id="x_a0">Il se personnalise facilement.</para></listitem> |
belaran@999 | 740 </itemizedlist> |
belaran@999 | 741 |
belaran@999 | 742 <para id="x_a1">Si vous êtes déjà familier d'un outil de gestion de |
belaran@999 | 743 source, vous serez capable de l'utiliser en moins de 5 minutes. Sinon, |
belaran@999 | 744 ça ne sera pas beaucoup plus long. Les commandes utilisées par |
belaran@999 | 745 Mercurial, comme ses fonctionnalités, sont généralement uniformes et |
belaran@999 | 746 cohérentes, et vous pouvez ainsi garder en tête simplement quelques |
belaran@999 | 747 règles générales, plutôt qu'un lot complexe d'exceptions. |
belaran@999 | 748 </para> |
belaran@999 | 749 |
belaran@999 | 750 <para id="x_a2">Sur un petit projet, vous pouvez commencer à travailler |
belaran@999 | 751 avec Mercurial en quelques instants. Ajouter des modifications ou des |
belaran@999 | 752 branches, transférer ces modifications (localement ou via le réseau), |
belaran@999 | 753 et les opérations d'historique ou de statut sont aussi très rapides. |
belaran@999 | 754 Mercurial reste hors de votre chemin grâce à sa simplicité |
belaran@999 | 755 d'utilisation et sa rapidité d'exécution. |
belaran@999 | 756 </para> |
belaran@999 | 757 |
belaran@999 | 758 <para id="x_a3">L'utilité de Mercurial ne se limite pas à de petits |
belaran@999 | 759 projets: il est aussi utilisé par des projets ayant des centaines ou |
belaran@999 | 760 même des milliers de contributeurs, avec plusieurs dizaines de milliers |
belaran@999 | 761 de fichiers, et des centaines de méga octets de code source. |
belaran@999 | 762 </para> |
belaran@999 | 763 |
belaran@999 | 764 <para id="x_a4">Si les fonctionnalités au cœur de Mercurial ne sont pas |
belaran@999 | 765 suffisantes pour vous, il est très aisé d'en construire d'autres. |
belaran@999 | 766 Mercurial est adapté à l'utilisation de scripts, et son implémentation |
belaran@999 | 767 interne en Python, propre et claire, rend encore plus facile l'ajout de |
belaran@999 | 768 fonctionnalités sous forme d'extensions. Il en existe déjà un certain |
belaran@999 | 769 nombre de très populaires et très utiles, dont le périmètre va de la |
belaran@999 | 770 recherche de bugs à l'amélioration des performances. |
belaran@999 | 771 </para> |
belaran@999 | 772 |
belaran@999 | 773 </sect1> |
belaran@999 | 774 <sect1> |
belaran@999 | 775 <title>Mercurial comparé aux autres outils</title> |
belaran@999 | 776 |
belaran@999 | 777 <para id="x_a5">Avant que vous n'alliez plus loin, comprenez bien que |
belaran@999 | 778 cette section reflète mes propres expériences, et elle est donc (j'ose |
belaran@999 | 779 le dire) peu objective. Néanmoins, j'ai utilisé les outils de gestion |
belaran@999 | 780 de source listés ci dessous, dans la plupart des cas, pendant plusieurs |
belaran@999 | 781 années. |
belaran@999 | 782 </para> |
belaran@999 | 783 |
belaran@999 | 784 <sect2> |
belaran@999 | 785 <title>Subversion</title> |
belaran@999 | 786 |
belaran@999 | 787 <para id="x_a6">Subversion est un des outils de gestion de source les |
belaran@999 | 788 plus populaire, il fût développé pour remplacer CVS. Il a une |
belaran@999 | 789 architecture client/server centralisée. |
belaran@999 | 790 </para> |
belaran@999 | 791 |
belaran@999 | 792 <para id="x_a7">Subversion et Mercurial ont des noms de commandes très |
belaran@999 | 793 similaires pour les mêmes opérations, ainsi si vous êtes familier |
belaran@999 | 794 avec l'un, c'est facile d'apprendre l'autre. Ces deux outils sont |
belaran@999 | 795 portables sur les systèmes d'exploitation les plus populaires. |
belaran@999 | 796 </para> |
belaran@999 | 797 |
belaran@999 | 798 <para id="x_a8">Avant la version 1.5, Subversion n'offrait aucune forme |
belaran@999 | 799 de support pour les fusions. Lors de l'écriture de ce livre, ses |
belaran@999 | 800 capacités de fusion étaient nouvelles, et réputées pour être <ulink url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword"> |
belaran@999 | 801 complexes et buguées</ulink>. |
belaran@999 | 802 </para> |
belaran@999 | 803 |
belaran@999 | 804 <para id="x_a9">Mercurial dispose d'un avantage substantiel en terme de |
belaran@999 | 805 performance par rapport à Subversion sur la plupart des opérations |
belaran@999 | 806 que j'ai pu tester. J'ai mesuré une différence de performance allant |
belaran@999 | 807 de deux à six fois plus rapide avec le système de stockage de fichier |
belaran@999 | 808 local de Subversion 1.4.3 (<emphasis>ra_local</emphasis>), qui est la |
belaran@999 | 809 méthode d'accès la plus rapide disponible. Dans un déploiement plus |
belaran@999 | 810 réaliste, impliquant un stockage réseau, Subversion serait encore |
belaran@999 | 811 plus désavantagé. Parce que la plupart des commandes Subversion |
belaran@999 | 812 doivent communiquer avec le serveur et que Subversion n'a pas de |
belaran@999 | 813 mécanisme de réplication, la capacité du serveur et la bande passante |
belaran@999 | 814 sont devenues des goulots d'étranglement pour les projets de taille |
belaran@999 | 815 moyenne ou grande. |
belaran@999 | 816 </para> |
belaran@999 | 817 |
belaran@999 | 818 <para id="x_aa">En outre, Subversion implique une surcharge |
belaran@999 | 819 substantielle dans le stockage local de certaines données, pour |
belaran@999 | 820 éviter des transactions avec le serveur, pour certaines opérations |
belaran@999 | 821 communes, telles que la recherche des fichiers modifiés |
belaran@999 | 822 (<literal moreinfo="none">status</literal>) et l'affichage des modifications par |
belaran@999 | 823 rapport à la révision courante (<literal moreinfo="none">diff</literal>). En |
belaran@999 | 824 conséquence, un répertoire de travail Subversion a souvent la même |
belaran@999 | 825 taille, ou est plus grand, qu'un dépôt Mercurial et son espace de |
belaran@999 | 826 travail, et ceci bien que le dépôt Mercurial contienne l'intégralité |
belaran@999 | 827 de l'historique. |
belaran@999 | 828 </para> |
belaran@999 | 829 |
belaran@999 | 830 <para id="x_ab">Subversion est largement supporté par les outils |
belaran@999 | 831 tierces. Mercurial est actuellement encore en retrait de ce point de |
belaran@999 | 832 vue. L'écart se réduit néanmoins, en effet, certains des outils |
belaran@999 | 833 graphiques sont maintenant supérieurs à leurs équivalents Subversion. |
belaran@999 | 834 Comme Mercurial, Subversion dispose d'un excellent manuel |
belaran@999 | 835 utilisateur. |
belaran@999 | 836 </para> |
belaran@999 | 837 |
belaran@999 | 838 <para id="x_ac">Parce que Subversion ne stocke pas l'historique chez |
belaran@999 | 839 ses clients, il est parfaitement adapté à la gestion de projets qui |
belaran@999 | 840 doivent suivre un ensemble de larges fichiers binaires et opaques. Si |
belaran@999 | 841 vous suivez une cinquantaine de versions d'un fichier incompressible |
belaran@999 | 842 de 10MB, l'occupation disque coté client d'un projet sous Subversion |
belaran@999 | 843 restera à peu près constante. A l'inverse, l'occupation disque du |
belaran@999 | 844 même projet sous n'importe lequel des gestionnaires de source |
belaran@999 | 845 distribués grandira rapidement, proportionnellement aux nombres de |
belaran@999 | 846 versions, car les différences entre chaque révisions seront très |
belaran@999 | 847 grandes. |
belaran@999 | 848 </para> |
belaran@999 | 849 |
belaran@999 | 850 <para id="x_ad">En outre, c'est souvent difficile ou, généralement, |
belaran@999 | 851 impossible de fusionner des différences dans un fichier binaire. La |
belaran@999 | 852 capacité de Subversion de verrouiller des fichiers, pour permettre à |
belaran@999 | 853 l'utilisateur d'être le seul à le mettre à jour |
belaran@999 | 854 (<quote>commit</quote>) temporairement, est un avantage significatif |
belaran@999 | 855 dans un projet doté de beaucoup de fichiers binaires. |
belaran@999 | 856 </para> |
belaran@999 | 857 |
belaran@999 | 858 <para id="x_ae">Mercurial peut importer l'historique depuis un dépôt |
belaran@999 | 859 Subversion. Il peut aussi exporter l'ensemble des révisions d'un |
belaran@999 | 860 projet vers un dépôt Subversion. Ceci rend très facile de |
belaran@999 | 861 <quote>prendre la température</quote> et d'utiliser Mercurial et |
belaran@999 | 862 Subversion en parallèle, avant de décider de migrer vers Mercurial. |
belaran@999 | 863 La conversion de l'historique est incrémentale, donc vous pouvez |
belaran@999 | 864 effectuer une conversion initiale, puis de petites additions par la |
belaran@999 | 865 suite pour ajouter les nouvelle modifications. |
belaran@999 | 866 </para> |
belaran@999 | 867 |
belaran@999 | 868 |
belaran@999 | 869 </sect2> |
belaran@999 | 870 <sect2> |
belaran@999 | 871 <title>Git</title> |
belaran@999 | 872 |
belaran@999 | 873 <para id="x_af">Git est un outil de gestion de source distribué qui fût |
belaran@999 | 874 développé pour gérer le code source de noyau de Linux. Comme |
belaran@999 | 875 Mercurial, sa conception initiale a été inspirée par Monotone. |
belaran@999 | 876 </para> |
belaran@999 | 877 |
belaran@999 | 878 <para id="x_b0">Git dispose d'un ensemble conséquent de commandes, avec |
belaran@999 | 879 plus de 139 commandes individuelles pour la version 1.5.0. Il a aussi |
belaran@999 | 880 la réputation d'être difficile à apprendre. Comparé à Git, le point |
belaran@999 | 881 fort de Mercurial est clairement sa simplicité. |
belaran@999 | 882 </para> |
belaran@999 | 883 |
belaran@999 | 884 <para id="x_b1">En terme de performance, Git est extrêmement rapide. |
belaran@999 | 885 Dans la plupart des cas, il est plus rapide que Mercurial, tout du |
belaran@999 | 886 moins sur Linux, alors que Mercurial peut être plus performant sur |
belaran@999 | 887 d'autres opérations. Néanmoins, sur Windows, les performances et le |
belaran@999 | 888 niveau de support général fourni par Git, au moment de l'écriture de |
belaran@999 | 889 cet ouvrage, est bien derrière celui de Mercurial. |
belaran@999 | 890 </para> |
belaran@999 | 891 |
belaran@999 | 892 <para id="x_b2">Alors que le dépôt Mercurial ne demande aucune |
belaran@999 | 893 maintenance, un dépôt Git exige d'exécuter manuellement et |
belaran@999 | 894 régulièrement la commande <quote>repacks</quote> sur ses métadonnées. |
belaran@999 | 895 Sans ceci, les performances de git se dégradent et la consommation de |
belaran@999 | 896 l'espace disque augmente rapidement. Un serveur qui contient |
belaran@999 | 897 plusieurs dépôts Git qui ne sont pas régulièrement et fréquemment |
belaran@999 | 898 <quote>repacked</quote> deviendra un vrai problème lors des |
belaran@999 | 899 <quote>backups</quote> du disque, et il y eu des cas, où un |
belaran@999 | 900 <quote>backup</quote> journalier pouvait durer plus de 24 heures. Un |
belaran@999 | 901 dépôt fraichement <quote>repacked</quote> sera légèrement plus petit |
belaran@999 | 902 qu'un dépôt Mercurial, mais un dépôt non <quote>repacked</quote> est |
belaran@999 | 903 beaucoup plus grand. |
belaran@999 | 904 </para> |
belaran@999 | 905 |
belaran@999 | 906 <para id="x_b3">Le cœur de Git est écrit en C. La plupart des commandes |
belaran@999 | 907 Git sont implémentées sous forme de scripts Shell ou Perl, et la |
belaran@999 | 908 qualité de ces scripts varie grandement. J'ai plusieurs fois constaté |
belaran@999 | 909 que certains de ces scripts étaient chargés en mémoire aveuglément et |
belaran@999 | 910 que la présence d'erreurs pouvait s'avérer fatal. |
belaran@999 | 911 </para> |
belaran@999 | 912 |
belaran@999 | 913 <para id="x_b4">Mercurial peut importer l'historique d'un dépôt Git.</para> |
belaran@999 | 914 |
belaran@999 | 915 </sect2> |
belaran@999 | 916 <sect2> |
belaran@999 | 917 <title>CVS</title> |
belaran@999 | 918 |
belaran@999 | 919 <para id="x_b5">CVS est probablement l'outil de gestion de source le |
belaran@999 | 920 plus utilisé aujourd'hui dans le monde. À cause de son manque de |
belaran@999 | 921 clarté interne, il n'est plus maintenu depuis plusieurs années. |
belaran@999 | 922 </para> |
belaran@999 | 923 |
belaran@999 | 924 <para id="x_b6">Il a une architecture client/serveur centralisée. Il ne |
belaran@999 | 925 regroupe pas les modifications de fichiers dans une opération de |
belaran@999 | 926 <quote>commit</quote> atomique, ce qui permet à ses utilisateurs de |
belaran@999 | 927 <quote>casser le <emphasis>build</emphasis></quote> assez facilement |
belaran@999 | 928 : une personne peut effectuer une opération de <quote>commit</quote> |
belaran@999 | 929 sans problème puis être bloquée par besoin de fusion, avec comme |
belaran@999 | 930 conséquence néfaste, que les autres utilisateurs ne récupèreront |
belaran@999 | 931 qu'une partie de ses modifications. Ce problème affecte aussi la |
belaran@999 | 932 manière de travailler avec l'historique du projet. Si vous voulez |
belaran@999 | 933 voir toutes les modifications d'une personne du projet, vous devrez |
belaran@999 | 934 injecter manuellement les descriptions et les <emphasis remap="it">timestamps</emphasis> des modifications de chacun des |
belaran@999 | 935 fichiers impliqués (si vous savez au moins quels sont ces fichiers). |
belaran@999 | 936 </para> |
belaran@999 | 937 |
belaran@999 | 938 <para id="x_b7">CVS a une notion étrange des <emphasis remap="it">tags</emphasis> et des branches que je n'essayerai même |
belaran@999 | 939 pas de décrire ici. Il ne supporte pas bien les opérations de |
belaran@999 | 940 renommage d'un fichier ou d'un répertoire, ce qui facilite la |
belaran@999 | 941 corruption de son dépôt. Il n'a presque pas pour ainsi dire de |
belaran@999 | 942 contrôle de cohérence interne, il est donc pratiquement impossible de |
belaran@999 | 943 dire si un dépôt est corrompu ni à quel point. Je ne recommanderai |
belaran@999 | 944 pas CVS pour un projet existant ou nouveau. |
belaran@999 | 945 </para> |
belaran@999 | 946 |
belaran@999 | 947 <para id="x_b8">Mercurial peut importer l'historique d'un projet CVS. |
belaran@999 | 948 Néanmoins, il y a quelques principes à respecter; ce qui est vrai |
belaran@999 | 949 aussi pour les autres outils d'import de projet CVS. À cause de |
belaran@999 | 950 l'absence de <quote>commit</quote> atomique et gestion de version de |
belaran@999 | 951 l'arborescence, il n'est pas possible de reconstruire de manière |
belaran@999 | 952 précise l'ensemble de l'historique. Un travail de |
belaran@999 | 953 <quote>devinette</quote> est donc nécessaire, et les fichiers |
belaran@999 | 954 renommés ne sont pas détectés. Parce qu'une bonne part de |
belaran@999 | 955 l'administration d'un dépôt CVS est effectuée manuellement, et est |
belaran@999 | 956 donc, sujette à erreur, il est courant que les imports CVS |
belaran@999 | 957 rencontrent de nombreux problèmes avec les dépôt corrompus (des |
belaran@999 | 958 <emphasis remap="it">timestamps</emphasis> de révision complètement |
belaran@999 | 959 buggés et des fichiers verrouillés depuis des années sont deux des |
belaran@999 | 960 problèmes les moins intéressants dont je me souvienne). |
belaran@999 | 961 </para> |
belaran@999 | 962 |
belaran@999 | 963 <para id="x_b9">Mercurial peut importer l'historique depuis un dépôt CVS. |
belaran@999 | 964 </para> |
belaran@999 | 965 |
belaran@999 | 966 |
belaran@999 | 967 </sect2> |
belaran@999 | 968 <sect2> |
belaran@999 | 969 <title>Outils propriétaires</title> |
belaran@999 | 970 |
belaran@999 | 971 <para id="x_ba">Perforce a une architecture client/serveur centralisée, |
belaran@999 | 972 sans aucun mécanisme de mise en cache de données coté client. |
belaran@999 | 973 Contrairement à la plupart des outils modernes de gestion de source, |
belaran@999 | 974 Perforce exige de ses utilisateurs d'exécuter une commande pour |
belaran@999 | 975 informer le serveur central de tout fichier qu'ils souhaitent |
belaran@999 | 976 modifier. |
belaran@999 | 977 </para> |
belaran@999 | 978 |
belaran@999 | 979 <para id="x_bb">Les performances de Perforce sont plutôt bonnes pour |
belaran@999 | 980 des petites équipes, mais elles s'effondrent rapidement lorsque le |
belaran@999 | 981 nombre d'utilisateurs augmente au delà de la douzaine. Des |
belaran@999 | 982 installations de Perforce assez larges nécessitent le déploiement de |
belaran@999 | 983 proxies pour supporter la montée en charge associée. |
belaran@999 | 984 </para> |
belaran@999 | 985 |
belaran@999 | 986 </sect2> |
belaran@999 | 987 <sect2> |
belaran@999 | 988 <title>Choisir un outil de gestion de source</title> |
belaran@999 | 989 |
belaran@999 | 990 <para id="x_bc">A l'exception de CVS, tous les outils listés ci-dessus |
belaran@999 | 991 ont des forces qui leur sont propres et qui correspondent à certaines |
belaran@999 | 992 formes de projet. Il n'y a pas un seul meilleur outil de gestion de |
belaran@999 | 993 source qui correspondrait le mieux à toutes les situations. |
belaran@999 | 994 </para> |
belaran@999 | 995 |
belaran@999 | 996 <para id="x_bd">En guise exemple, Subversion est un très bon choix |
belaran@999 | 997 lorsqu'on travaille avec beaucoup de fichiers binaires, qui évoluent |
belaran@999 | 998 régulièrement, grâce à sa nature centralisée et sa capacité à |
belaran@999 | 999 verrouiller des fichiers. |
belaran@999 | 1000 </para> |
belaran@999 | 1001 |
belaran@999 | 1002 <para id="x_be">Personnellement, je préfère Mercurial pour sa |
belaran@999 | 1003 simplicité, ses performances et sa bonne capacité de fusion, et il |
belaran@999 | 1004 m'a très bien rendu service de plusieurs années maintenant. |
belaran@999 | 1005 </para> |
belaran@999 | 1006 |
belaran@999 | 1007 </sect2> |
belaran@999 | 1008 </sect1> |
belaran@999 | 1009 <sect1> |
belaran@999 | 1010 <title>Migrer depuis un outil à Mercurial</title> |
belaran@999 | 1011 |
belaran@999 | 1012 <para id="x_bf">Mercurial est livré avec une extension nommée <literal role="hg-ext" moreinfo="none">convert</literal>, qui peut, de manière incrémentale |
belaran@999 | 1013 importer des révisions depuis différents autres outils de gestion de |
belaran@999 | 1014 source. Par <quote>incrémental</quote>, j'entends que vous pouvez |
belaran@999 | 1015 convertir l'historique entier du projet en une seule fois, puis |
belaran@999 | 1016 relancer l'outil d'import plus tard pour obtenir les modifications |
belaran@999 | 1017 effectuées depuis votre import initial. |
belaran@999 | 1018 </para> |
belaran@999 | 1019 |
belaran@999 | 1020 <para id="x_c0">Les outils de gestion de source supportés par <literal role="hg-ext" moreinfo="none">convert</literal> sont : |
belaran@999 | 1021 </para> |
belaran@999 | 1022 <itemizedlist> |
belaran@999 | 1023 <listitem><para id="x_c1">Subversion</para></listitem> |
belaran@999 | 1024 <listitem><para id="x_c2">CVS</para></listitem> |
belaran@999 | 1025 <listitem><para id="x_c3">Git</para></listitem> |
belaran@999 | 1026 <listitem><para id="x_c4">Darcs</para></listitem> |
belaran@999 | 1027 </itemizedlist> |
belaran@999 | 1028 |
belaran@999 | 1029 <para id="x_c5">En outre, <literal role="hg-ext" moreinfo="none">convert</literal> peut |
belaran@999 | 1030 exporter les modifications depuis Mercurial vers Subversion. Ceci rend |
belaran@999 | 1031 possible d'essayer Subversion en parallèle avant de choisir une |
belaran@999 | 1032 solution définitive, sans aucun risque de perte de données. |
belaran@999 | 1033 </para> |
belaran@999 | 1034 |
belaran@999 | 1035 <para id="x_c6">La commande <command role="hg-ext-conver" moreinfo="none">convert</command> est très simple à utiliser. |
belaran@999 | 1036 Simplement, indiquez le chemin ou l'URL du dépôt de source, en lui |
belaran@999 | 1037 indiquant éventuellement le nom du chemin de destination, et la |
belaran@999 | 1038 conversion se met en route. Après cet import initial, il suffit de |
belaran@999 | 1039 relancer la commande encore une fois pour importer les modifications |
belaran@999 | 1040 effectuées depuis. |
belaran@999 | 1041 </para> |
belaran@999 | 1042 </sect1> |
belaran@999 | 1043 |
belaran@999 | 1044 <sect1> |
belaran@999 | 1045 <title>Une courte histoire de la gestion de source</title> |
belaran@999 | 1046 |
belaran@999 | 1047 <para id="x_c7">Le plus célèbre des anciens outils de gestion de source |
belaran@999 | 1048 est <emphasis remap="it">SCCS</emphasis> (Source Code Control System)}, |
belaran@999 | 1049 que Marc Rochkind conçu dans les laboratoires de recherche de Bell |
belaran@999 | 1050 (<emphasis remap="it">Bell Labs</emphasis>), dans le début des années |
belaran@999 | 1051 70. <emphasis remap="it">SCCS</emphasis> ne fonctionnait que sur des |
belaran@999 | 1052 fichiers individuels, et obligeait chaque personne travaillant sur le |
belaran@999 | 1053 projet d'avoir un accès à un répertoire de travail commun, sur le même |
belaran@999 | 1054 système. Seulement une seule personne pouvait modifier un fichier au |
belaran@999 | 1055 même moment, ce fonctionnement était assuré par l'utilisation de verrou |
belaran@999 | 1056 (<quote>lock</quote>). Il était courant que des personnes verrouillent |
belaran@999 | 1057 des fichiers, et plus tard, oublient de le déverrouiller ; empêchant |
belaran@999 | 1058 n'importe qui d'autre de travailler sur ces fichiers sans l'aide de |
belaran@999 | 1059 l'administrateur... |
belaran@999 | 1060 </para> |
belaran@999 | 1061 |
belaran@999 | 1062 <para id="x_c8">Walter Tichy a développé une alternative libre à |
belaran@999 | 1063 <emphasis remap="it">SCCS</emphasis> au début des années 80, qu'il |
belaran@999 | 1064 nomma <emphasis remap="it">RCS (Revision Control System)</emphasis>. |
belaran@999 | 1065 Comme <emphasis remap="it">SCCS</emphasis>, <emphasis remap="it">RCS</emphasis> demandait aux développeurs de travailler |
belaran@999 | 1066 sur le même répertoire partagé, et de verrouiller les fichiers pour se |
belaran@999 | 1067 prémunir de tout conflit issu de modifications concurrentes. |
belaran@999 | 1068 </para> |
belaran@999 | 1069 |
belaran@999 | 1070 <para id="x_c9">Un peu plus tard dans les années 1980, Dick Grune utilisa |
belaran@999 | 1071 <emphasis remap="it">RCS</emphasis> comme une brique de base pour un |
belaran@999 | 1072 ensemble de scripts <emphasis remap="it">shell</emphasis> qu'il |
belaran@999 | 1073 intitula cmt, avant de la renommer en <emphasis remap="it">CVS |
belaran@999 | 1074 (Concurrent Versions System)</emphasis>. La grande innovation de CVS |
belaran@999 | 1075 était que les développeurs pouvaient travailler simultanément et |
belaran@999 | 1076 indépendamment dans leur propre espace de travail. Ces espaces de |
belaran@999 | 1077 travail privés assuraient que les développeurs ne se marchent pas |
belaran@999 | 1078 mutuellement sur les pieds, comme c'était souvent le cas avec RCS et |
belaran@999 | 1079 SCCS. Tous les développeurs disposaient donc de leur copie de tous les |
belaran@999 | 1080 fichiers du projet, et ils pouvaient donc librement les modifier. Ils |
belaran@999 | 1081 devaient néanmoins effectuer la <quote>fusion</quote> (<emphasis remap="it"><quote>merge</quote></emphasis>) de leurs fichiers, avant |
belaran@999 | 1082 d'effectuer le <quote>commit</quote> de leurs modifications sur le dépôt |
belaran@999 | 1083 central. |
belaran@999 | 1084 </para> |
belaran@999 | 1085 |
belaran@999 | 1086 <para>Brian Berliner reprit les scripts de Grune's et les réécrit en C, |
belaran@999 | 1087 qu'il publia en 1989. Depuis, ce code a été modifié jusqu'à devenir la |
belaran@999 | 1088 version moderne de CVS. CVS a acquis ainsi la capacité de fonctionner |
belaran@999 | 1089 en réseau, transformant son architecture en client/serveur. |
belaran@999 | 1090 L'architecture de CVS est centralisée, seul le serveur a une copie de |
belaran@999 | 1091 l'historique du projet. L'espace de travail client ne contient qu'une |
belaran@999 | 1092 copie de la dernière version du projet, et quelques métadonnées pour |
belaran@999 | 1093 indiquer où le serveur se trouve. CVS a été un grand succès, |
belaran@999 | 1094 aujourd'hui il est probablement l'outil de gestion de contrôle le plus |
belaran@999 | 1095 utilisé au monde. |
belaran@999 | 1096 </para> |
belaran@999 | 1097 |
belaran@999 | 1098 <para>Au début des années 1990, Sun Microsystems développa un premier |
belaran@999 | 1099 outil de gestion de source distribué, nommé TeamWare. Un espace de |
belaran@999 | 1100 travail TeamWare contient une copie complète de l'historique du projet. |
belaran@999 | 1101 TeamWare n'a pas de notion de dépôt central. (CVS utilisait RCS pour le |
belaran@999 | 1102 stockage de l'historique, TeamWare utilisait SCCS). |
belaran@999 | 1103 </para> |
belaran@999 | 1104 |
belaran@999 | 1105 <para>Alors que les années 1990 avançaient, les utilisateurs ont pris |
belaran@999 | 1106 conscience d'un certain nombre de problèmes avec CVS. Il enregistrait |
belaran@999 | 1107 simultanément des modifications sur différents fichiers |
belaran@999 | 1108 individuellement, au lieu de les regrouper dans une seule opération |
belaran@999 | 1109 cohérente et atomique. Il ne gère pas bien sa hiérarchie de fichier, il |
belaran@999 | 1110 est donc assez aisé de créer le chaos en renommant les fichiers et les |
belaran@999 | 1111 répertoires. Pire encore, son code source est difficile à lire et à |
belaran@999 | 1112 maintenir, ce qui agrandit largement le <quote>niveau de |
belaran@999 | 1113 souffrance</quote> associé à la réparation de ces problèmes |
belaran@999 | 1114 d'architecture de manière prohibitive. |
belaran@999 | 1115 </para> |
belaran@999 | 1116 |
belaran@999 | 1117 <para>En 2001, Jim Blandy et Karl Fogel, deux développeurs qui avaient |
belaran@999 | 1118 travaillé sur CVS, initièrent un projet pour le remplacer par un outil |
belaran@999 | 1119 qui aurait une meilleure architecture et un code plus propre. Le |
belaran@999 | 1120 résultat, Subversion, ne quitte pas le modèle centralisé et |
belaran@999 | 1121 client/server de CVS, mais ajoute les opérations de |
belaran@999 | 1122 <quote>commit</quote> atomique sur de multiples fichiers, une meilleure |
belaran@999 | 1123 gestion des espaces de noms, et d'autres fonctionnalités qui en font un |
belaran@999 | 1124 meilleur outil que CVS. Depuis sa première publication, il est |
belaran@999 | 1125 rapidement devenu très populaire. |
belaran@999 | 1126 </para> |
belaran@999 | 1127 |
belaran@999 | 1128 <para>Plus ou moins simultanément, Graydon Hoare a commencé sur |
belaran@999 | 1129 l'ambitieux système de gestion distribué Monotone. Bien que Monotone |
belaran@999 | 1130 corrige plusieurs défauts de CVS tout en offrant une architecture |
belaran@999 | 1131 <quote>peer-to-peer</quote>, il va aussi plus loin que la plupart des |
belaran@999 | 1132 outils de révision de manière assez innovante. Il utilise des |
belaran@999 | 1133 <quote>hashs</quote> cryptographiques comme identifiants, et il a une |
belaran@999 | 1134 notion complète de <quote>confiance</quote> du code issu des |
belaran@999 | 1135 différentes sources. |
belaran@999 | 1136 </para> |
belaran@999 | 1137 |
belaran@999 | 1138 <para>Mercurial est né en 2005. Bien que très influencé par Monotone, |
belaran@999 | 1139 Mercurial se concentre sur la facilité d'utilisation, les performances |
belaran@999 | 1140 et la capacité à monter en charge pour de très gros projets. |
belaran@999 | 1141 </para> |
belaran@999 | 1142 |
belaran@999 | 1143 </sect1> |
belaran@999 | 1144 |
belaran@999 | 1145 </chapter> |
belaran@999 | 1146 |
belaran@999 | 1147 <!-- |
belaran@999 | 1148 local variables: |
belaran@999 | 1149 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 1150 end: |
belaran@999 | 1151 --> |
belaran@999 | 1152 |
belaran@999 | 1153 <!-- BEGIN ch02 --> |
belaran@999 | 1154 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 1155 |
belaran@999 | 1156 <chapter id="chap:tour-basic"> |
belaran@999 | 1157 <?dbhtml filename="a-tour-of-mercurial-the-basics.html"?> |
belaran@999 | 1158 <title>Une rapide présentation de Mercurial : les bases</title> |
belaran@999 | 1159 |
belaran@999 | 1160 <sect1> |
belaran@999 | 1161 <title>Installer Mercurial sur votre système</title> |
belaran@999 | 1162 |
belaran@999 | 1163 <para id="x_1">Des paquetages binaires de Mercurial sont disponibles pour la |
belaran@999 | 1164 plupart des systèmes d'exploitation, ce qui rend facile l'utilisation |
belaran@999 | 1165 immédiate de Mercurial sur votre ordinateur.</para> |
belaran@999 | 1166 |
belaran@999 | 1167 <sect2> |
belaran@999 | 1168 <title>Windows</title> |
belaran@999 | 1169 |
belaran@999 | 1170 <para id="x_c">La meilleur version de Mercurial pour Windows est |
belaran@999 | 1171 TortoiseHg, qui peut être téléchargée ici : <ulink url="http://bitbucket.org/tortoisehg/stable/wiki/Home">http://bitbucket.org/tortoisehg/stable/wiki/Home</ulink>. |
belaran@999 | 1172 Ce logiciel n'a aucune dépendance exterieure; il fonctionne <quote>et |
belaran@999 | 1173 c'est tout</quote>. Il fournit aussi bien les outils en ligne de |
belaran@999 | 1174 commmande qu'une interface graphique.</para> |
belaran@999 | 1175 |
belaran@999 | 1176 </sect2> |
belaran@999 | 1177 |
belaran@999 | 1178 <sect2> |
belaran@999 | 1179 <title>Mac OS X</title> |
belaran@999 | 1180 |
belaran@999 | 1181 <para id="x_a">Lee Cantey publie un installeur de Mercurial pour Mac OS |
belaran@999 | 1182 X sur <ulink url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>.</para> |
belaran@999 | 1183 </sect2> |
belaran@999 | 1184 |
belaran@999 | 1185 <sect2> |
belaran@999 | 1186 <title>Linux</title> |
belaran@999 | 1187 |
belaran@999 | 1188 <para id="x_2">Parce que chaque distribution de Linux a ses propres |
belaran@999 | 1189 outils de gestion de paquets, politiques et rythmes de |
belaran@999 | 1190 développements, il est difficile de donner un ensemble |
belaran@999 | 1191 d'instructions unique pour installer les binaires de Mercurial. La |
belaran@999 | 1192 version de Mercurial avec laquelle vous vous retrouverez dépendra |
belaran@999 | 1193 grandement de l'activité de la personne en charge du paquetage pour |
belaran@999 | 1194 la distribution.</para> |
belaran@999 | 1195 |
belaran@999 | 1196 <para id="x_3">Pour rester simple, je me concentrerai sur |
belaran@999 | 1197 l'installation de Mercurial en ligne de commande, sous les |
belaran@999 | 1198 distributions les plus courantes. La plupart des distributions |
belaran@999 | 1199 fournissent des gestionnaires graphiques de paquetage qui vous |
belaran@999 | 1200 permettront d'installer Mercurial en quelques clicks. Le paquetage |
belaran@999 | 1201 devrait se nommer <literal moreinfo="none">mercurial</literal>.</para> |
belaran@999 | 1202 |
belaran@999 | 1203 <itemizedlist> |
belaran@999 | 1204 <listitem><para id="x_4">Ubuntu et Debian:</para> |
belaran@999 | 1205 <programlisting format="linespecific">apt-get install mercurial</programlisting></listitem> |
belaran@999 | 1206 <listitem><para id="x_5">Fedora:</para> |
belaran@999 | 1207 <programlisting format="linespecific">yum install mercurial</programlisting></listitem> |
belaran@999 | 1208 <listitem><para id="x_6">Gentoo:</para> |
belaran@999 | 1209 <programlisting format="linespecific">emerge mercurial</programlisting></listitem> |
belaran@999 | 1210 <listitem><para id="x_715">OpenSUSE:</para> |
belaran@999 | 1211 <programlisting format="linespecific">zypper install |
belaran@999 | 1212 mercurial</programlisting></listitem> |
belaran@999 | 1213 </itemizedlist> |
belaran@999 | 1214 |
belaran@999 | 1215 </sect2> |
belaran@999 | 1216 <sect2> |
belaran@999 | 1217 <title>Solaris</title> |
belaran@999 | 1218 |
belaran@999 | 1219 <para id="x_09">SunFreeWare, à <ulink url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>, |
belaran@999 | 1220 fournit des paquets précompilés pour Mercurial.</para> |
belaran@999 | 1221 </sect2> |
belaran@999 | 1222 </sect1> |
belaran@999 | 1223 |
belaran@999 | 1224 <sect1> |
belaran@999 | 1225 <title>Commencer à utiliser Mercurial</title> |
belaran@999 | 1226 |
belaran@999 | 1227 <para id="x_e">Pour commencer, nous utiliserons la commande <command role="hg-cmd" moreinfo="none">hg version</command> pour vérifier si Mercurial est |
belaran@999 | 1228 installé proprement. Les informations affichées sur la version ne sont |
belaran@999 | 1229 pas réellement importantes en soit, c'est surtout de savoir si elles |
belaran@999 | 1230 s'affichent qui nous intéresse.</para> |
belaran@999 | 1231 |
belaran@999 | 1232 <!-- BEGIN tour.version --> |
belaran@999 | 1233 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg version</userinput> |
belaran@999 | 1234 Mercurial Distributed SCM (version 1.2.1) |
belaran@999 | 1235 |
belaran@999 | 1236 Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others |
belaran@999 | 1237 This is free software; see the source for copying conditions. There is NO |
belaran@999 | 1238 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
belaran@999 | 1239 </screen> |
belaran@999 | 1240 <!-- END tour.version --> |
belaran@999 | 1241 |
belaran@999 | 1242 |
belaran@999 | 1243 <sect2> |
belaran@999 | 1244 <title>L'aide intégrée</title> |
belaran@999 | 1245 |
belaran@999 | 1246 <para id="x_f">Mercurial fournit un système d'aide intégré, ce qui est |
belaran@999 | 1247 inestimable quand vous vous retrouvez coincé à essayer de vous |
belaran@999 | 1248 rappeler comment lancer une commande. Si vous êtes bloqué, exécutez |
belaran@999 | 1249 simplement <command role="hg-cmd" moreinfo="none">hg help</command>; elle affichera |
belaran@999 | 1250 une brève liste des commandes, avec une description pour chacune. Si |
belaran@999 | 1251 vous demandez de l'aide sur une commande spécifique (voir |
belaran@999 | 1252 ci-dessous), elle affichera des informations plus détaillées.</para> |
belaran@999 | 1253 |
belaran@999 | 1254 <!-- BEGIN tour.help --> |
belaran@999 | 1255 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help init</userinput> |
belaran@999 | 1256 hg init [-e CMD] [--remotecmd CMD] [DEST] |
belaran@999 | 1257 |
belaran@999 | 1258 create a new repository in the given directory |
belaran@999 | 1259 |
belaran@999 | 1260 Initialize a new repository in the given directory. If the given |
belaran@999 | 1261 directory does not exist, it is created. |
belaran@999 | 1262 |
belaran@999 | 1263 If no directory is given, the current directory is used. |
belaran@999 | 1264 |
belaran@999 | 1265 It is possible to specify an ssh:// URL as the destination. |
belaran@999 | 1266 See 'hg help urls' for more information. |
belaran@999 | 1267 |
belaran@999 | 1268 options: |
belaran@999 | 1269 |
belaran@999 | 1270 -e --ssh specify ssh command to use |
belaran@999 | 1271 --remotecmd specify hg command to run on the remote side |
belaran@999 | 1272 |
belaran@999 | 1273 use "hg -v help init" to show global options |
belaran@999 | 1274 </screen> |
belaran@999 | 1275 <!-- END tour.help --> |
belaran@999 | 1276 |
belaran@999 | 1277 |
belaran@999 | 1278 <para id="x_10">Pour un niveau d'informations encore plus détaillé |
belaran@999 | 1279 (ce dont vous aurez rarement besoin), exécuter <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1280 help <option role="hg-opt-global">-v</option></command>. L'option |
belaran@999 | 1281 <option role="hg-opt-global">-v</option> est l'abréviation de |
belaran@999 | 1282 <option role="hg-opt-global">--verbose</option>, et indique à Mercurial |
belaran@999 | 1283 d'ficher plus d'informations que d'habitude.</para> |
belaran@999 | 1284 |
belaran@999 | 1285 </sect2> |
belaran@999 | 1286 </sect1> |
belaran@999 | 1287 <sect1> |
belaran@999 | 1288 <title>Travailler avec un dépôt</title> |
belaran@999 | 1289 |
belaran@999 | 1290 <para id="x_11">Avec Mercurial, tout se déroule au sein du |
belaran@999 | 1291 <emphasis>dépôt</emphasis>. Le dépôt d'un projet contient tous |
belaran@999 | 1292 les fichiers qui <quote>appartiennent</quote> au projet.</para> |
belaran@999 | 1293 |
belaran@999 | 1294 <para id="x_12">Il n'y a rien de particulièrement magique au sujet de |
belaran@999 | 1295 ce dépôt, c'est simplement une arborescence sur votre système de fichiers |
belaran@999 | 1296 que Mercurial traite de manière spéciale. Vous pouvez renommer ou effacer |
belaran@999 | 1297 ce répertoire à n'impporte quel moment, en utilisant la ligne de commande |
belaran@999 | 1298 ou votre explorateur de fichiers.</para> |
belaran@999 | 1299 |
belaran@999 | 1300 <sect2> |
belaran@999 | 1301 <title>Faire une copie locale de votre dépôt</title> |
belaran@999 | 1302 |
belaran@999 | 1303 <para id="x_13"><emphasis>Copier</emphasis> un dépôt est juste un |
belaran@999 | 1304 peu spécial. Bien que vous puissiez utiliser une commande habituelle de |
belaran@999 | 1305 copie pour copier votre dépôt, il vaut mieux utiliser une commande fournie par |
belaran@999 | 1306 Mercurial. Cette commande est appelée <command role="hg-cmd" moreinfo="none">hg clone</command>, |
belaran@999 | 1307 car elle crée une copie identique à un dépôt existant.</para> |
belaran@999 | 1308 |
belaran@999 | 1309 <!-- BEGIN tour.clone --> |
belaran@999 | 1310 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone http://hg.serpentine.com/tutorial/hello</userinput> |
belaran@999 | 1311 destination directory: hello |
belaran@999 | 1312 requesting all changes |
belaran@999 | 1313 adding changesets |
belaran@999 | 1314 adding manifests |
belaran@999 | 1315 adding file changes |
belaran@999 | 1316 added 5 changesets with 5 changes to 2 files |
belaran@999 | 1317 updating working directory |
belaran@999 | 1318 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 1319 </screen> |
belaran@999 | 1320 <!-- END tour.clone --> |
belaran@999 | 1321 |
belaran@999 | 1322 |
belaran@999 | 1323 <para id="x_67c">Un avantage de la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1324 clone</command> est que, comme nous l'avons vu ci dessus, elle nous |
belaran@999 | 1325 permet de faire de cloner les dépôts à travers le réseau. Un autre |
belaran@999 | 1326 est qu'elle se rappelle d'où a été cloné un dépôt, ce qui est utile |
belaran@999 | 1327 quand on veut mettre à jour le clone.</para> |
belaran@999 | 1328 |
belaran@999 | 1329 <para id="x_14">Si votre opération de clonage réussit, vous devriez maintenant |
belaran@999 | 1330 avoir un répertoire local appelé <filename class="directory" moreinfo="none">hello</filename>. |
belaran@999 | 1331 Ce répertoire contiendra quelques fichiers.</para> |
belaran@999 | 1332 |
belaran@999 | 1333 <!-- BEGIN tour.ls --> |
belaran@999 | 1334 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput> |
belaran@999 | 1335 total 4 |
belaran@999 | 1336 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:05 hello |
belaran@999 | 1337 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls hello</userinput> |
belaran@999 | 1338 Makefile hello.c |
belaran@999 | 1339 </screen> |
belaran@999 | 1340 <!-- END tour.ls --> |
belaran@999 | 1341 |
belaran@999 | 1342 |
belaran@999 | 1343 <para id="x_15">Ces fichiers ont le même contenu et historique dans votre dépôt |
belaran@999 | 1344 qu'ils ont dans le dépôt que vous avez cloné.</para> |
belaran@999 | 1345 |
belaran@999 | 1346 <para id="x_16">Chaque dépôt Mercurial est complet, autonome et |
belaran@999 | 1347 indépendant. Il contient sa propre copie privée des fichiers du |
belaran@999 | 1348 projet et de leur historique. Le clone d'un dépôt se souvient de la |
belaran@999 | 1349 localisation du dépôt à partir duquel il a été clôné, mais il ne |
belaran@999 | 1350 communique pas avec ce dernier, ou un autre, à moins que vous ne lui |
belaran@999 | 1351 demandiez.</para> |
belaran@999 | 1352 |
belaran@999 | 1353 <para id="x_17">Ce que tout ceci signifie pour le moment est que nous |
belaran@999 | 1354 sommes libres d'expérimenter avec ce dépôt, confiants dans le fait |
belaran@999 | 1355 qu'il s'agit d'un <quote>bac à sable</quote> qui n'affectera personne |
belaran@999 | 1356 d'autre.</para> |
belaran@999 | 1357 |
belaran@999 | 1358 </sect2> |
belaran@999 | 1359 <sect2> |
belaran@999 | 1360 <title>Quel est le contenu d'un dépôt ?</title> |
belaran@999 | 1361 |
belaran@999 | 1362 <para id="x_18">Prêtons plus attention un instant au contenu d'un dépôt. |
belaran@999 | 1363 Nous voyons qu'il contient un répertoire nommé <filename class="directory" moreinfo="none">.hg |
belaran@999 | 1364 </filename>. C'est ici que Mercurial conserve toutes ses |
belaran@999 | 1365 métadonnées.</para> |
belaran@999 | 1366 |
belaran@999 | 1367 <!-- BEGIN tour.ls-a --> |
belaran@999 | 1368 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello</userinput> |
belaran@999 | 1369 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -a</userinput> |
belaran@999 | 1370 . .. .hg Makefile hello.c |
belaran@999 | 1371 </screen> |
belaran@999 | 1372 <!-- END tour.ls-a --> |
belaran@999 | 1373 |
belaran@999 | 1374 |
belaran@999 | 1375 <para id="x_19">Le contenu du répertoire <filename class="directory" moreinfo="none">.hg |
belaran@999 | 1376 </filename> et ses sous répertoires sont les seuls propres à Mercurial. |
belaran@999 | 1377 Tous les autres fichiers et répertoires dans le dépôt sont à vous, et |
belaran@999 | 1378 vous pouvez en faire ce que vous voulez.</para> |
belaran@999 | 1379 |
belaran@999 | 1380 <para id="x_1a">Pour introduire un peu de terminologie, le répertoire |
belaran@999 | 1381 <filename class="directory" moreinfo="none">.hg</filename> est un <quote>vrai</quote> |
belaran@999 | 1382 dépôt, et tous les fichiers et les répertoires qui coexistent avec lui, |
belaran@999 | 1383 sont désignés sous le nom <emphasis>espace de travail</emphasis>. Une |
belaran@999 | 1384 manière facile de se rappeler cette distinction est de retenir que le |
belaran@999 | 1385 <emphasis>dépôt</emphasis> contient l'<emphasis>historique</emphasis> |
belaran@999 | 1386 de votre projet, alors que l'<emphasis>espace de travail</emphasis> |
belaran@999 | 1387 contient un "<emphasis>snapshot</emphasis>" de votre projet à un certain |
belaran@999 | 1388 point de son historique.</para> |
belaran@999 | 1389 |
belaran@999 | 1390 </sect2> |
belaran@999 | 1391 </sect1> |
belaran@999 | 1392 <sect1> |
belaran@999 | 1393 <title>Une promenade dans l'historique</title> |
belaran@999 | 1394 |
belaran@999 | 1395 <para id="x_1b">Une des premières choses que vous aurez envie |
belaran@999 | 1396 de faire avec un nouveau dépôt, sera de comprendre son historique. |
belaran@999 | 1397 La commande <command role="hg-cmd" moreinfo="none">hg log</command> vous donne une |
belaran@999 | 1398 vue de l'historique.</para> |
belaran@999 | 1399 |
belaran@999 | 1400 <!-- BEGIN tour.log --> |
belaran@999 | 1401 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput> |
belaran@999 | 1402 changeset: 4:2278160e78d4 |
belaran@999 | 1403 tag: tip |
belaran@999 | 1404 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1405 date: Sat Aug 16 22:16:53 2008 +0200 |
belaran@999 | 1406 summary: Trim comments. |
belaran@999 | 1407 |
belaran@999 | 1408 changeset: 3:0272e0d5a517 |
belaran@999 | 1409 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1410 date: Sat Aug 16 22:08:02 2008 +0200 |
belaran@999 | 1411 summary: Get make to generate the final binary from a .o file. |
belaran@999 | 1412 |
belaran@999 | 1413 changeset: 2:fef857204a0c |
belaran@999 | 1414 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1415 date: Sat Aug 16 22:05:04 2008 +0200 |
belaran@999 | 1416 summary: Introduce a typo into hello.c. |
belaran@999 | 1417 |
belaran@999 | 1418 changeset: 1:82e55d328c8c |
belaran@999 | 1419 user: mpm@selenic.com |
belaran@999 | 1420 date: Fri Aug 26 01:21:28 2005 -0700 |
belaran@999 | 1421 summary: Create a makefile |
belaran@999 | 1422 |
belaran@999 | 1423 changeset: 0:0a04b987be5a |
belaran@999 | 1424 user: mpm@selenic.com |
belaran@999 | 1425 date: Fri Aug 26 01:20:50 2005 -0700 |
belaran@999 | 1426 summary: Create a standard "hello, world" program |
belaran@999 | 1427 |
belaran@999 | 1428 </screen> |
belaran@999 | 1429 <!-- END tour.log --> |
belaran@999 | 1430 |
belaran@999 | 1431 |
belaran@999 | 1432 <para id="x_1c">Par défaut, cette commande affiche à l'écran un bref paragraphe pour chaque |
belaran@999 | 1433 révision enregistrée pour ce projet. Dans la terminologie de Mercurial, nous |
belaran@999 | 1434 appelons chacun de ces évènements enregistrés un <emphasis>changeset</emphasis>, parce |
belaran@999 | 1435 qu'il contient un ensemble de modifications sur plusieurs fichiers.</para> |
belaran@999 | 1436 |
belaran@999 | 1437 <para id="x_1d">La commande <command role="hg-cmd" moreinfo="none">hg log</command> affiche |
belaran@999 | 1438 ainsi ces informations :</para> |
belaran@999 | 1439 |
belaran@999 | 1440 <itemizedlist> |
belaran@999 | 1441 <listitem><para id="x_1e"><literal moreinfo="none">changeset</literal> : Ce champ contient |
belaran@999 | 1442 un nombre, séparé par deux points (:), d'une chaine hexadécimale. Il |
belaran@999 | 1443 s'agit en fait d'<emphasis>identifiants</emphasis> d'un changeset. Il y a |
belaran@999 | 1444 deux identifiants car le numéro de la révision est plus court et plus à |
belaran@999 | 1445 facile à saisir qu'une séquence hexadécimale.</para> |
belaran@999 | 1446 </listitem> |
belaran@999 | 1447 <listitem><para id="x_1f"><literal moreinfo="none">user</literal> : L'identité de la personne |
belaran@999 | 1448 qui a créée ce %%% laisser le terme anglais car il sera affiché |
belaran@999 | 1449 changeset. C'est un champ libre de forme, mais la plupart du |
belaran@999 | 1450 temps il contient le nom et l'email de la personne.</para> |
belaran@999 | 1451 </listitem> |
belaran@999 | 1452 <listitem><para id="x_20"><literal moreinfo="none">date</literal> : La date et l'heure à |
belaran@999 | 1453 laquelle le \textit{changeset} a été créé, ainsi que le fuseau horaire dans |
belaran@999 | 1454 lequelle il a été créé. (La date et l'heure sont locales à ce |
belaran@999 | 1455 \textit{fuseau}, elles indiquent donc quelle date et heure il était |
belaran@999 | 1456 pour la personne qui a créé ce changeset.</para> |
belaran@999 | 1457 </listitem> |
belaran@999 | 1458 <listitem><para id="x_21"><literal moreinfo="none">résumé</literal>: La première ligne du |
belaran@999 | 1459 message que le créateur a associé à son changeset pour le décrire.</para> |
belaran@999 | 1460 </listitem> |
belaran@999 | 1461 <listitem><para id="x_67d">Certains changesets, comme le premier de la |
belaran@999 | 1462 liste ci-dessus ont un champ <literal moreinfo="none">tag</literal>. Le tag est une autre |
belaran@999 | 1463 façon d'identifier un changeset en lui donnant un nom simple à retenir. |
belaran@999 | 1464 (Le tag nommé <literal moreinfo="none">tip</literal> est spécial : il fait toujours |
belaran@999 | 1465 référence aux derniers changements dans le dépôt.)</para></listitem> |
belaran@999 | 1466 </itemizedlist> |
belaran@999 | 1467 |
belaran@999 | 1468 <para id="x_22">Par défaut, la commande <command role="hg-cmd" moreinfo="none">hg log</command> |
belaran@999 | 1469 n'affiche qu'un résumé, il manque beaucoup de détails.</para> |
belaran@999 | 1470 |
belaran@999 | 1471 <para id="x_23">La figure <xref linkend="fig:tour-basic:history"/> fournit une |
belaran@999 | 1472 représentation graphique de l'historique du dépôt <filename class="directory" moreinfo="none">hello |
belaran@999 | 1473 </filename>, pour rendre plus facile de voir dans quelle direction |
belaran@999 | 1474 l'historique se <quote>déroule</quote>. Nous reviendrons régulièrement |
belaran@999 | 1475 sur cette représentation dans ce chapitre et ceux qui suivent.</para> |
belaran@999 | 1476 |
belaran@999 | 1477 |
belaran@999 | 1478 <figure id="fig:tour-basic:history" float="0"> |
belaran@999 | 1479 <title>Graphical history of the <filename class="directory" moreinfo="none">hello</filename> repository</title> |
belaran@999 | 1480 <mediaobject> |
belaran@999 | 1481 <imageobject><imagedata fileref="figs/tour-history.png"/></imageobject> |
belaran@999 | 1482 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 1483 </mediaobject> |
belaran@999 | 1484 </figure> |
belaran@999 | 1485 |
belaran@999 | 1486 |
belaran@999 | 1487 <sect2> |
belaran@999 | 1488 <title>Changesets, révisions, et collaboration</title> |
belaran@999 | 1489 |
belaran@999 | 1490 <para id="x_25">Comme l'anglais est réputé pour être un langage maladroit, |
belaran@999 | 1491 et que l'informatique est la source de bien des erreurs de terminologie |
belaran@999 | 1492 (pourquoi utiliser un seul terme quand quatre feront l'affaire ?), la |
belaran@999 | 1493 gestion de version a une variété de mots et de phrases qui veulent dire |
belaran@999 | 1494 la même chose. Si vous discutez d'historique de Mercurial avec d'autres |
belaran@999 | 1495 personnes, vous constaterez que souvent, le mot <quote>changeset</quote> |
belaran@999 | 1496 est contracté simplement en <quote>change</quote> ou (à l'écrit) |
belaran@999 | 1497 <quote>cset</quote>, et même parfois un changeset |
belaran@999 | 1498 <quote>révision</quote>, abrégé en <quote>rev</quote>.</para> |
belaran@999 | 1499 |
belaran@999 | 1500 <para id="x_26">Bien que le <emphasis>mot</emphasis> que vous utilisez pour |
belaran@999 | 1501 désigner le concept de changeset importe peu, l'<emphasis>identifiant</emphasis> |
belaran@999 | 1502 que vous utilisez pour désigner un <emphasis>changeset</emphasis> spécifique |
belaran@999 | 1503 a une grande importance. Rappelez vous que le champ changeset affiché par la |
belaran@999 | 1504 commande <command role="hg-cmd" moreinfo="none">hg log</command> identifie un changeset à |
belaran@999 | 1505 la fois avec un numéro de révision et une séquence hexadécimale.</para> |
belaran@999 | 1506 |
belaran@999 | 1507 <itemizedlist> |
belaran@999 | 1508 <listitem><para id="x_27">Le numéro de révision est <emphasis>seulement |
belaran@999 | 1509 valable dans ce dépôt</emphasis>,</para></listitem> |
belaran@999 | 1510 <listitem><para id="x_28">La séquence hexadécimale est un |
belaran@999 | 1511 <emphasis>identifiant permanent, et invariant</emphasis> qui |
belaran@999 | 1512 pourra toujours être associé au changeset exact de <emphasis>chaque</emphasis> |
belaran@999 | 1513 copie de votre dépôt.</para></listitem></itemizedlist> |
belaran@999 | 1514 |
belaran@999 | 1515 <para id="x_29">La distinction est importante. Si vous envoyez un email |
belaran@999 | 1516 à quelqu'un en parlant de la <quote>révision 33</quote>, il est très |
belaran@999 | 1517 probable que sa révision 33 <emphasis>ne sera pas la même</emphasis> |
belaran@999 | 1518 que la votre. La raison de ceci est que le numéro de révision dépend |
belaran@999 | 1519 de l'ordre dans lequel les modifications sont arrivées dans le dépôt, |
belaran@999 | 1520 et il n'y a aucune garantie que les mêmes changements soient arrivés |
belaran@999 | 1521 dans le même ordre dans différents dépôts. Trois modifications |
belaran@999 | 1522 <literal moreinfo="none">a,b,c</literal> peuvent aisément apparaitre dans un dépôt |
belaran@999 | 1523 comme <literal moreinfo="none">0,1,2</literal>, et dans un autre comme <literal moreinfo="none">0,2,1 |
belaran@999 | 1524 </literal>.</para> |
belaran@999 | 1525 |
belaran@999 | 1526 <para id="x_2a">Mercurial utilise les numéros de révision uniquement comme des raccourcis |
belaran@999 | 1527 pratiques. Si vous devez discuter d'un \textit{changeset} avec quelqu'un, |
belaran@999 | 1528 ou identifer un \textit{changeset} pour une quelconque raison (par exemple, |
belaran@999 | 1529 un rapport de \textit{bug}), utilisez la séquence hexadécimale.</para> |
belaran@999 | 1530 |
belaran@999 | 1531 </sect2> |
belaran@999 | 1532 <sect2> |
belaran@999 | 1533 <title>Afficher une révision spécifique</title> |
belaran@999 | 1534 |
belaran@999 | 1535 <para id="x_2b">Pour réduire la sortie de <command role="hg-cmd" moreinfo="none">hg log |
belaran@999 | 1536 </command> à une seule révision, utilisez l'option <option role="hg-opt-log">-r |
belaran@999 | 1537 </option> (ou <option role="hg-opt-log">--rev</option>). Vous pouvez utiliser |
belaran@999 | 1538 le numéro de révision ou la séquence hexadécimale comme identifiant, et |
belaran@999 | 1539 demander autant de révisions que vous le souhaitez.</para> |
belaran@999 | 1540 |
belaran@999 | 1541 <!-- BEGIN tour.log-r --> |
belaran@999 | 1542 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 3</userinput> |
belaran@999 | 1543 changeset: 3:0272e0d5a517 |
belaran@999 | 1544 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1545 date: Sat Aug 16 22:08:02 2008 +0200 |
belaran@999 | 1546 summary: Get make to generate the final binary from a .o file. |
belaran@999 | 1547 |
belaran@999 | 1548 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 0272e0d5a517</userinput> |
belaran@999 | 1549 changeset: 3:0272e0d5a517 |
belaran@999 | 1550 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1551 date: Sat Aug 16 22:08:02 2008 +0200 |
belaran@999 | 1552 summary: Get make to generate the final binary from a .o file. |
belaran@999 | 1553 |
belaran@999 | 1554 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 1 -r 4</userinput> |
belaran@999 | 1555 changeset: 1:82e55d328c8c |
belaran@999 | 1556 user: mpm@selenic.com |
belaran@999 | 1557 date: Fri Aug 26 01:21:28 2005 -0700 |
belaran@999 | 1558 summary: Create a makefile |
belaran@999 | 1559 |
belaran@999 | 1560 changeset: 4:2278160e78d4 |
belaran@999 | 1561 tag: tip |
belaran@999 | 1562 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1563 date: Sat Aug 16 22:16:53 2008 +0200 |
belaran@999 | 1564 summary: Trim comments. |
belaran@999 | 1565 |
belaran@999 | 1566 </screen> |
belaran@999 | 1567 <!-- END tour.log-r --> |
belaran@999 | 1568 |
belaran@999 | 1569 |
belaran@999 | 1570 <para id="x_2c">Si vous voulez voir l'historique de plusieurs révisions |
belaran@999 | 1571 sans avoir à les énumérer, vous pouvez utiliser la <emphasis>intervalle |
belaran@999 | 1572 de numérotation</emphasis> qui vous permet d'exprimer l'idée <quote>je |
belaran@999 | 1573 veux toutes les révisions entre $a$ et $b$, inclus</quote></para> |
belaran@999 | 1574 |
belaran@999 | 1575 <!-- BEGIN tour.log.range --> |
belaran@999 | 1576 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r 2:4</userinput> |
belaran@999 | 1577 changeset: 2:fef857204a0c |
belaran@999 | 1578 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1579 date: Sat Aug 16 22:05:04 2008 +0200 |
belaran@999 | 1580 summary: Introduce a typo into hello.c. |
belaran@999 | 1581 |
belaran@999 | 1582 changeset: 3:0272e0d5a517 |
belaran@999 | 1583 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1584 date: Sat Aug 16 22:08:02 2008 +0200 |
belaran@999 | 1585 summary: Get make to generate the final binary from a .o file. |
belaran@999 | 1586 |
belaran@999 | 1587 changeset: 4:2278160e78d4 |
belaran@999 | 1588 tag: tip |
belaran@999 | 1589 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1590 date: Sat Aug 16 22:16:53 2008 +0200 |
belaran@999 | 1591 summary: Trim comments. |
belaran@999 | 1592 |
belaran@999 | 1593 </screen> |
belaran@999 | 1594 <!-- END tour.log.range --> |
belaran@999 | 1595 |
belaran@999 | 1596 |
belaran@999 | 1597 <para id="x_2d">Mercurial respecte aussi l'ordre dans lequel vous spécifiez |
belaran@999 | 1598 les révisions, ainsi <command role="hg-cmd" moreinfo="none">hg log -r 2:4</command> |
belaran@999 | 1599 affichera <literal moreinfo="none">2,3,4</literal> alors que <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1600 log -r 4:2</command> affichera <literal moreinfo="none">4,3,2</literal>.</para> |
belaran@999 | 1601 |
belaran@999 | 1602 </sect2> |
belaran@999 | 1603 <sect2> |
belaran@999 | 1604 <title>Informations détaillées</title> |
belaran@999 | 1605 |
belaran@999 | 1606 <para id="x_2e">Le résumé affiché par <command role="hg-cmd" moreinfo="none">hg log</command> |
belaran@999 | 1607 est suffisant si vous savez déjà ce que vous cherchez. En |
belaran@999 | 1608 revanche, vous aurez probablement besoin de voir une description |
belaran@999 | 1609 complète du changement, ou une liste des fichiers modifiés si vous |
belaran@999 | 1610 cherchez à déterminer qu'un changeset est bien celui que vous |
belaran@999 | 1611 recherchez. L'option \hgopt{-v} de la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1612 log</command> (ou <option role="hp-opt-global">--verbose</option>) vous |
belaran@999 | 1613 donne ces informations supplémentaires.</para> |
belaran@999 | 1614 |
belaran@999 | 1615 <!-- BEGIN tour.log-v --> |
belaran@999 | 1616 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -r 3</userinput> |
belaran@999 | 1617 changeset: 3:0272e0d5a517 |
belaran@999 | 1618 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1619 date: Sat Aug 16 22:08:02 2008 +0200 |
belaran@999 | 1620 files: Makefile |
belaran@999 | 1621 description: |
belaran@999 | 1622 Get make to generate the final binary from a .o file. |
belaran@999 | 1623 |
belaran@999 | 1624 |
belaran@999 | 1625 </screen> |
belaran@999 | 1626 <!-- END tour.log-v --> |
belaran@999 | 1627 |
belaran@999 | 1628 |
belaran@999 | 1629 <para id="x_2f">Si vous voulez voir à la fois la description |
belaran@999 | 1630 et le contenu d'une modification, ajouter l'option <option role="hg-opt-log">-p</option> (ou <option role="hg-opt-log"> |
belaran@999 | 1631 --patch</option>). Ceci affiche le contenu d'une modification |
belaran@999 | 1632 comme un <emphasis>diff unifié</emphasis> |
belaran@999 | 1633 <!-- \footnote{NdT: \textit{unified diff}} --> |
belaran@999 | 1634 (si vous n'avez jamais vu de diff unifié avant, consultez la |
belaran@999 | 1635 section <xref linkend="sec:mq:patch"/> pour un rapide |
belaran@999 | 1636 survol).</para> |
belaran@999 | 1637 |
belaran@999 | 1638 <!-- BEGIN tour.log-vp --> |
belaran@999 | 1639 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -v -p -r 2</userinput> |
belaran@999 | 1640 changeset: 2:fef857204a0c |
belaran@999 | 1641 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 1642 date: Sat Aug 16 22:05:04 2008 +0200 |
belaran@999 | 1643 files: hello.c |
belaran@999 | 1644 description: |
belaran@999 | 1645 Introduce a typo into hello.c. |
belaran@999 | 1646 |
belaran@999 | 1647 |
belaran@999 | 1648 diff -r 82e55d328c8c -r fef857204a0c hello.c |
belaran@999 | 1649 --- a/hello.c Fri Aug 26 01:21:28 2005 -0700 |
belaran@999 | 1650 +++ b/hello.c Sat Aug 16 22:05:04 2008 +0200 |
belaran@999 | 1651 @@ -11,6 +11,6 @@ |
belaran@999 | 1652 |
belaran@999 | 1653 int main(int argc, char **argv) |
belaran@999 | 1654 { |
belaran@999 | 1655 - printf("hello, world!\n"); |
belaran@999 | 1656 + printf("hello, world!\"); |
belaran@999 | 1657 return 0; |
belaran@999 | 1658 } |
belaran@999 | 1659 |
belaran@999 | 1660 </screen> |
belaran@999 | 1661 <!-- END tour.log-vp --> |
belaran@999 | 1662 |
belaran@999 | 1663 |
belaran@999 | 1664 <para id="x_67e">L'option <option role="hg-opt-log">-p</option> est |
belaran@999 | 1665 incroyablement utile, il est donc important dans s'en rappeller.</para> |
belaran@999 | 1666 |
belaran@999 | 1667 </sect2> |
belaran@999 | 1668 </sect1> |
belaran@999 | 1669 <sect1> |
belaran@999 | 1670 <title>Tout sur les options de commandes</title> |
belaran@999 | 1671 |
belaran@999 | 1672 <para id="x_30">Avant d'aller plus loin sur le fonctionnement |
belaran@999 | 1673 des commandes de Mercurial, étudions un moment comment elles |
belaran@999 | 1674 fonctionnent de manière générale. Vous trouverez ça probablement |
belaran@999 | 1675 utile pour la suite de notre parcours.</para> |
belaran@999 | 1676 |
belaran@999 | 1677 <para id="x_31">Mercurial utilise une approche directe et cohérente |
belaran@999 | 1678 pour interpréter les options que vous passez aux commandes. Il suit une |
belaran@999 | 1679 convention commune à la plupart des systèmes Unix et Linux modernes.</para> |
belaran@999 | 1680 |
belaran@999 | 1681 <itemizedlist> |
belaran@999 | 1682 <listitem><para id="x_32">Chaque option a un nom complet. Par exemple, |
belaran@999 | 1683 comme nous l'avons déjà vu, la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1684 log</command> accepte l'option <option role="hg-opt-log">--rev |
belaran@999 | 1685 </option>.</para> |
belaran@999 | 1686 </listitem> |
belaran@999 | 1687 <listitem><para id="x_33">La plupart des options disposent de |
belaran@999 | 1688 noms abrégés. Aussi, au lieu d'utiliser <option role="hg-opt-log">--rev |
belaran@999 | 1689 </option>, vous pouvez utiliser <option role="hg-opt-log">-r</option>. |
belaran@999 | 1690 (Les options qui n'ont pas de noms abrégés sont généralement |
belaran@999 | 1691 rarement utilisées).</para> |
belaran@999 | 1692 </listitem> |
belaran@999 | 1693 <listitem><para id="x_34">Les noms complets commencent par deux |
belaran@999 | 1694 tirets (i.e. <option role="hg-opt-log">--rev</option>), |
belaran@999 | 1695 alors que les options courtes commencent avec un seul (i.e. |
belaran@999 | 1696 <option role="hg-opt-log">-r</option>).</para> |
belaran@999 | 1697 </listitem> |
belaran@999 | 1698 <listitem><para id="x_35">Les noms des options sont cohérents |
belaran@999 | 1699 entre les commandes. Par exemple, chaque commande qui accepte |
belaran@999 | 1700 un changeset ID ou un numéro de révision accepte aussi <option role="hg-opt-log">-r</option> et <option role="hg-opt-log">--rev |
belaran@999 | 1701 </option> comme arguments.</para> |
belaran@999 | 1702 </listitem> |
belaran@999 | 1703 </itemizedlist> |
belaran@999 | 1704 |
belaran@999 | 1705 <para id="x_36">Dans les exemples de ce livre, j'utilise les noms abrégés |
belaran@999 | 1706 plutôt que les noms complets. Ceci est une préférence personnelle, pas |
belaran@999 | 1707 une recommandation.</para> |
belaran@999 | 1708 |
belaran@999 | 1709 <para id="x_37">La plupart des commandes qui affichent une quelconque sortie |
belaran@999 | 1710 à l'écran, afficheront davantage avec l'option <option role="hg-opt-global"> |
belaran@999 | 1711 -v</option> (ou <option role="hg-opt-global">--verbose</option>), et |
belaran@999 | 1712 moins avec l'option <option role="hg-opt-global">-q</option> (ou |
belaran@999 | 1713 <option role="hg-opt-global">--quiet</option>).</para> |
belaran@999 | 1714 |
belaran@999 | 1715 <note> |
belaran@999 | 1716 <title>Option naming consistency</title> |
belaran@999 | 1717 |
belaran@999 | 1718 <para id="x_680">Presque toujours, les commandes de Mercurial utilisent |
belaran@999 | 1719 des noms d'options cohérentes pour référer à des concepts identiques. |
belaran@999 | 1720 Par exemple, si une commande concerne les changesets, vous les |
belaran@999 | 1721 identifierez toujours avec l'option <option role="hg-opt-log">-r</option>. |
belaran@999 | 1722 Cette utilisation cohérente des noms d'options permet de mémoriser plus |
belaran@999 | 1723 facilement quelles options accepte une commande.</para> |
belaran@999 | 1724 </note> |
belaran@999 | 1725 |
belaran@999 | 1726 |
belaran@999 | 1727 </sect1> |
belaran@999 | 1728 <sect1> |
belaran@999 | 1729 <title>Faire et vérifier des modifications</title> |
belaran@999 | 1730 |
belaran@999 | 1731 <para id="x_38">Maintenant que nous avons une bonne idée des |
belaran@999 | 1732 commandes pour consulter l'historique de Mercurial, regardons |
belaran@999 | 1733 comment faire des modifications et les examiner.</para> |
belaran@999 | 1734 |
belaran@999 | 1735 <para id="x_39">La première chose que nous allons faire c'est isoler notre |
belaran@999 | 1736 expérience dans un dépôt à part. Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg clone</command>, mais nous n'avons pas besoin de faire |
belaran@999 | 1737 une copie de dépôt distant. Comme nous avons déjà une copie locale, nous |
belaran@999 | 1738 pouvons juste faire un clone de celle-ci à la place. C'est beaucoup plus |
belaran@999 | 1739 rapide que de faire une copie à travers le réseau, et un dépôt cloné |
belaran@999 | 1740 localement prend également moins d'espace disque<footnote> |
belaran@999 | 1741 <para id="x_681">L'économie d'espace disque apparait clairement quand les |
belaran@999 | 1742 dépôts source et destination sont sur le même système de fichier, où, dans |
belaran@999 | 1743 ce cas, Mercurial utilisera des liens physiques pour effectuer des partages |
belaran@999 | 1744 copie-lors-des-écritures de ses métadonnées internes. Si cette explication |
belaran@999 | 1745 ne signifie rien pour vous, ne vous inquietez pas : tout ceci se passe de |
belaran@999 | 1746 manière transparente et automatiquement. Vous n'avez pas du tout besoin de |
belaran@999 | 1747 comprendre ceci.</para></footnote>.</para> |
belaran@999 | 1748 |
belaran@999 | 1749 <!-- BEGIN tour.reclone --> |
belaran@999 | 1750 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 1751 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-hello</userinput> |
belaran@999 | 1752 updating working directory |
belaran@999 | 1753 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 1754 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput> |
belaran@999 | 1755 </screen> |
belaran@999 | 1756 <!-- END tour.reclone --> |
belaran@999 | 1757 |
belaran@999 | 1758 |
belaran@999 | 1759 <para id="x_3a">On notera au passage qu'il est souvent considéré comme |
belaran@999 | 1760 une bonne pratique de conserver une copie <quote>immaculée</quote> |
belaran@999 | 1761 du dépôt distant, à partir de laquelle vous pourrez faire des |
belaran@999 | 1762 copies locales temporaires pour créer des <quote>bacs à sable</quote> |
belaran@999 | 1763 pour chaque tâche sur laquelle vous souhaitez travailler. Ceci |
belaran@999 | 1764 vous permet de travailler sur plusieurs choses en parallèle, |
belaran@999 | 1765 chacune isolée les unes des autres en attendant que ces tâches |
belaran@999 | 1766 soient finies et que vous soyez prêt à les réintégrer. Parce |
belaran@999 | 1767 que les copies locales sont peu coûteuses, il est très rapide |
belaran@999 | 1768 de créer ou détruire des dépôts dès que vous n'en avez plus |
belaran@999 | 1769 besoin.</para> |
belaran@999 | 1770 |
belaran@999 | 1771 <para id="x_3b">Dans notre dépôt <filename class="directory" moreinfo="none">my-hello</filename>, nous avons un fichier |
belaran@999 | 1772 <filename moreinfo="none">hello.c</filename> qui contient le classique <quote>hello, |
belaran@999 | 1773 world</quote>.</para> |
belaran@999 | 1774 |
belaran@999 | 1775 <!-- BEGIN tour.cat1 --> |
belaran@999 | 1776 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> |
belaran@999 | 1777 /* |
belaran@999 | 1778 * Placed in the public domain by Bryan O'Sullivan. This program is |
belaran@999 | 1779 * not covered by patents in the United States or other countries. |
belaran@999 | 1780 */ |
belaran@999 | 1781 |
belaran@999 | 1782 #include <stdio.h> |
belaran@999 | 1783 |
belaran@999 | 1784 int main(int argc, char **argv) |
belaran@999 | 1785 { |
belaran@999 | 1786 printf("hello, world!\"); |
belaran@999 | 1787 return 0; |
belaran@999 | 1788 } |
belaran@999 | 1789 </screen> |
belaran@999 | 1790 <!-- END tour.cat1 --> |
belaran@999 | 1791 |
belaran@999 | 1792 |
belaran@999 | 1793 <para id="x_682">Editons ce fichier pour qu'il affiche une autre ligne |
belaran@999 | 1794 sur la sortie standard.</para> |
belaran@999 | 1795 |
belaran@999 | 1796 <!-- BEGIN tour.cat2 --> |
belaran@999 | 1797 <screen format="linespecific"># ... edit edit edit ... |
belaran@999 | 1798 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> |
belaran@999 | 1799 /* |
belaran@999 | 1800 * Placed in the public domain by Bryan O'Sullivan. This program is |
belaran@999 | 1801 * not covered by patents in the United States or other countries. |
belaran@999 | 1802 */ |
belaran@999 | 1803 |
belaran@999 | 1804 #include <stdio.h> |
belaran@999 | 1805 |
belaran@999 | 1806 int main(int argc, char **argv) |
belaran@999 | 1807 { |
belaran@999 | 1808 printf("hello, world!\"); |
belaran@999 | 1809 printf("hello again!\n"); |
belaran@999 | 1810 return 0; |
belaran@999 | 1811 } |
belaran@999 | 1812 </screen> |
belaran@999 | 1813 <!-- END tour.cat2 --> |
belaran@999 | 1814 |
belaran@999 | 1815 |
belaran@999 | 1816 <para id="x_3c">La commande Mercurial <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1817 status</command> nous dira ce que Mercurial sait des fichiers du |
belaran@999 | 1818 dépôts.</para> |
belaran@999 | 1819 |
belaran@999 | 1820 <!-- BEGIN tour.status --> |
belaran@999 | 1821 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput> |
belaran@999 | 1822 Makefile hello.c |
belaran@999 | 1823 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 1824 M hello.c |
belaran@999 | 1825 </screen> |
belaran@999 | 1826 <!-- END tour.status --> |
belaran@999 | 1827 |
belaran@999 | 1828 |
belaran@999 | 1829 <para id="x_3d">La commande <command role="hg-cmd" moreinfo="none">hg status</command> |
belaran@999 | 1830 n'affichera pas le contenu des fichiers, mais une ligne commençant par |
belaran@999 | 1831 <quote><literal moreinfo="none">M</literal></quote> pour <filename moreinfo="none">hello.c</filename>. |
belaran@999 | 1832 A moins que vous lui demandiez, la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1833 status</command> n'affichera aucune information sur les fichiers que |
belaran@999 | 1834 vous n'avez pas modifiés.</para> |
belaran@999 | 1835 |
belaran@999 | 1836 <para id="x_3e">Le <quote><literal moreinfo="none">M</literal></quote> indique que |
belaran@999 | 1837 Mercurial a remarqué que nous avons modifié le fichier |
belaran@999 | 1838 <filename moreinfo="none">hello.c</filename>. Nous n'avons pas besoin |
belaran@999 | 1839 <emphasis>d'informer</emphasis> Mercurial que nous allons modifier un |
belaran@999 | 1840 fichier avant de commencer à le faire, ou que nous avons modifié un |
belaran@999 | 1841 fichier après avoir commencé à le faire, il est capable de découvrir ça |
belaran@999 | 1842 tout seul. </para> |
belaran@999 | 1843 |
belaran@999 | 1844 <para id="x_3f">C'est déjà pratique de savoir que nous avons modifié le |
belaran@999 | 1845 fichier <filename moreinfo="none">hello.c</filename>, mais nous préférerions savoir |
belaran@999 | 1846 exactement <emphasis>ce que</emphasis> nous avons changé. Pour ceci, nous |
belaran@999 | 1847 utilisons la commande <command role="hg-cmd" moreinfo="none">hg diff</command>.</para> |
belaran@999 | 1848 |
belaran@999 | 1849 <!-- BEGIN tour.diff --> |
belaran@999 | 1850 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> |
belaran@999 | 1851 diff -r 2278160e78d4 hello.c |
belaran@999 | 1852 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200 |
belaran@999 | 1853 +++ b/hello.c Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 1854 @@ -8,5 +8,6 @@ |
belaran@999 | 1855 int main(int argc, char **argv) |
belaran@999 | 1856 { |
belaran@999 | 1857 printf("hello, world!\"); |
belaran@999 | 1858 + printf("hello again!\n"); |
belaran@999 | 1859 return 0; |
belaran@999 | 1860 } |
belaran@999 | 1861 </screen> |
belaran@999 | 1862 <!-- END tour.diff --> |
belaran@999 | 1863 |
belaran@999 | 1864 |
belaran@999 | 1865 <tip> |
belaran@999 | 1866 <title>Comprendre les patches</title> |
belaran@999 | 1867 |
belaran@999 | 1868 <para id="x_683">Penser à jeter un oeil à <xref linkend="sec:mq:patch"/> si vous n'arrivez pas à lire la sortie |
belaran@999 | 1869 ci-dessus.</para> |
belaran@999 | 1870 </tip> |
belaran@999 | 1871 </sect1> |
belaran@999 | 1872 <sect1> |
belaran@999 | 1873 <title>Enregister vos modifications dans une nouvelle révision</title> |
belaran@999 | 1874 |
belaran@999 | 1875 <para id="x_40">Nous pouvons modifier des fichiers, compiler et tester |
belaran@999 | 1876 nos modifications, et utiliser les commandes <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 1877 status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command> pour |
belaran@999 | 1878 voir les modifications effectuées, jusqu'à ce que nous soyons assez |
belaran@999 | 1879 satisfaits pour décider d'enregistrer notre travail dans un |
belaran@999 | 1880 \textit{changeset}.</para> |
belaran@999 | 1881 |
belaran@999 | 1882 <para id="x_41">La commande <command role="hg-cmd" moreinfo="none">hg commit</command> |
belaran@999 | 1883 vous laisse créer une nouvelle révision, nous désignerons généralement |
belaran@999 | 1884 cette opération par <quote>faire un commit</quote> ou |
belaran@999 | 1885 <quote>committer</quote>.</para> |
belaran@999 | 1886 |
belaran@999 | 1887 <sect2> |
belaran@999 | 1888 <title>Définir le nom d'utilisateur</title> |
belaran@999 | 1889 |
belaran@999 | 1890 <para id="x_42">Quand vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg commit</command> pour la première fois, il n'est |
belaran@999 | 1891 pas garanti qu'elle réussisse du premier coup. En effet, Mercurial |
belaran@999 | 1892 enregistre votre nom et votre adresse avec chaque modification que |
belaran@999 | 1893 vous effectuez, de manière à ce que vous soyez capable (ou d'autres |
belaran@999 | 1894 le soient) de savoir qui a fait quelle modification. Mercurial essaye |
belaran@999 | 1895 automatiquement de découvrir un nom d'utilisateur qui ait un minimum |
belaran@999 | 1896 de sens pour effectuer l'opération de commit avec. Il va essayer |
belaran@999 | 1897 chacune des méthodes suivantes, dans l'ordre :</para> |
belaran@999 | 1898 |
belaran@999 | 1899 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 1900 <listitem><para id="x_43">Si vous spécifiez l'option <option role="hg-opt-commit">-u</option> avec la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, suivi d'un nom |
belaran@999 | 1901 d'utilisateur, ceci aura toujours la priorité sur les autres |
belaran@999 | 1902 méthodes ci dessous.</para></listitem> |
belaran@999 | 1903 <listitem><para id="x_44">Si vous avez défini une variable |
belaran@999 | 1904 d'environnement <envar>HGUSER</envar>, c'est cette valeur qui est |
belaran@999 | 1905 alors utilisée.</para></listitem> |
belaran@999 | 1906 <listitem><para id="x_45">Si vous créez un fichier nommé <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire |
belaran@999 | 1907 \textit{home}, avec une entrée <envar role="rc-item-ui">username</envar>, c'est la valeur associée |
belaran@999 | 1908 qui sera utilisée. Pour voir à quoi ressemble le contenu de ce |
belaran@999 | 1909 fichier regardez la section <xref linkend="sec:tour-basic:username"/> |
belaran@999 | 1910 ci-dessous.</para></listitem> |
belaran@999 | 1911 <listitem><para id="x_46">Si vous avez défini une variable |
belaran@999 | 1912 d'environnement <envar>EMAIL</envar> celle ci sera utilisée |
belaran@999 | 1913 ensuite.</para></listitem> |
belaran@999 | 1914 <listitem><para id="x_47">Enfin, Mercurial interrogera votre système |
belaran@999 | 1915 pour trouver votre nom d'utilisateur local ainsi que le nom de la |
belaran@999 | 1916 machine hôte, et il fabriquera un nom d'utilisateur à partir de |
belaran@999 | 1917 ces données. Comme il arrive souvent que ce genre de noms soit |
belaran@999 | 1918 totalement inutile, il vous préviendra en affichant un message |
belaran@999 | 1919 d'avertissement.</para></listitem> |
belaran@999 | 1920 </orderedlist> |
belaran@999 | 1921 |
belaran@999 | 1922 <para id="x_48">Si tous ces mécanismes échouent, Mercurial n'exécutera |
belaran@999 | 1923 pas la commande, affichant un message d'erreur. Dans ce cas, il ne |
belaran@999 | 1924 vous laissera pas effectuer de commit tant que vous n'aurez pas |
belaran@999 | 1925 défini un nom d'utilisateur.</para> |
belaran@999 | 1926 |
belaran@999 | 1927 <para id="x_49">Vous devriez penser à utiliser la variable |
belaran@999 | 1928 d'environement <envar>HGUSER</envar> et l'option <option role="hg-opt-commit">-u</option> comme moyen pour |
belaran@999 | 1929 <emphasis>changer</emphasis> le nom d'utilisateur par défaut. Pour |
belaran@999 | 1930 une utilisation normale, la manière la plus simple et robuste |
belaran@999 | 1931 d'opérer est de créer un fichier <filename role="special" moreinfo="none">.hgrc</filename>, voir ci-dessous pour les détails |
belaran@999 | 1932 à ce sujet.</para> |
belaran@999 | 1933 |
belaran@999 | 1934 <sect3 id="sec:tour-basic:username"> |
belaran@999 | 1935 <title>Créer un fichier de configuration pour Mercurial</title> |
belaran@999 | 1936 |
belaran@999 | 1937 <para id="x_4a">Pour définir un nom d'utilisateur, utilisez votre |
belaran@999 | 1938 éditeur de texte favori pour créer un fichier <filename role="special" moreinfo="none">.hgrc</filename> dans votre répertoire home. |
belaran@999 | 1939 Mercurial va utiliser ce fichier pour retrouver votre |
belaran@999 | 1940 configuration personnelle. Le contenu initial devrait |
belaran@999 | 1941 ressembler à ceci :</para> |
belaran@999 | 1942 |
belaran@999 | 1943 <tip> |
belaran@999 | 1944 <title><quote>Home directory</quote> sous Windows</title> |
belaran@999 | 1945 |
belaran@999 | 1946 <para id="x_716">Quand on parle de répertoire home, sur une version |
belaran@999 | 1947 anglaise d'une installation de Windows, il s'agira habituellement |
belaran@999 | 1948 d'un répertoire nommée comme votre nom dans <filename moreinfo="none">C:\Documents |
belaran@999 | 1949 and Settings</filename>. Vous pouvez trouver de quelle répertoire |
belaran@999 | 1950 il s'agit en lançant une fenêtre d'interpréteur de commande et en |
belaran@999 | 1951 exécutant la commande suivante :</para> |
belaran@999 | 1952 |
belaran@999 | 1953 <screen format="linespecific"><prompt moreinfo="none">C:\</prompt> <userinput moreinfo="none">echo |
belaran@999 | 1954 %UserProfile</userinput></screen> |
belaran@999 | 1955 </tip> |
belaran@999 | 1956 |
belaran@999 | 1957 <programlisting format="linespecific"># This is a Mercurial configuration file. |
belaran@999 | 1958 [ui] |
belaran@999 | 1959 username = Firstname Lastname <email.address@domain.net></programlisting> |
belaran@999 | 1960 |
belaran@999 | 1961 <para id="x_4b">La ligne avec <literal moreinfo="none">[ui]</literal> commence une |
belaran@999 | 1962 <emphasis>section</emphasis> du fichier de configuration, ainsi la ligne |
belaran@999 | 1963 <quote><literal moreinfo="none">username = ...</literal></quote> signifie <quote> |
belaran@999 | 1964 définir la valeur de l'élément <literal moreinfo="none">username</literal> dans la |
belaran@999 | 1965 section <literal moreinfo="none">ui</literal></quote>. Une section continue jusqu'à ce |
belaran@999 | 1966 qu'une nouvelle commence, ou que la fin du fichier soit atteinte. |
belaran@999 | 1967 Mercurial ignore les lignes vides et traite tout texte situé à la suite |
belaran@999 | 1968 d'un <quote><literal moreinfo="none">#</literal></quote> jusqu'à la fin de la ligne |
belaran@999 | 1969 comme un commentaire.</para> |
belaran@999 | 1970 |
belaran@999 | 1971 </sect3> |
belaran@999 | 1972 <sect3> |
belaran@999 | 1973 <title>Choisir un nom d'utilisateur</title> |
belaran@999 | 1974 |
belaran@999 | 1975 <para id="x_4c">Vous pouvez utiliser n'importe quelle valeur |
belaran@999 | 1976 pour votre <literal moreinfo="none">username</literal>, car cette information |
belaran@999 | 1977 est destinée à d'autres personnes et non à être interprétée |
belaran@999 | 1978 par Mercurial. La convention que la plupart des personnes |
belaran@999 | 1979 suivent est d'utiliser leurs noms suivies de leurs adresses emails, |
belaran@999 | 1980 comme montré ci-dessus :</para> |
belaran@999 | 1981 <note> |
belaran@999 | 1982 <para id="x_4d">Le mécanisme interne du serveur web intégré à Mercurial, |
belaran@999 | 1983 masque les adresses emails, pour rendre plus difficile leurs |
belaran@999 | 1984 récupérations par les outils utilisés par les spammmers. |
belaran@999 | 1985 Ceci réduit la probabilité que de recevoir encore plus de |
belaran@999 | 1986 spam si vous vous publiez un dépôt sur internet.</para> |
belaran@999 | 1987 </note> |
belaran@999 | 1988 </sect3> |
belaran@999 | 1989 </sect2> |
belaran@999 | 1990 <sect2> |
belaran@999 | 1991 <title>Rédiger un message de \textit{commit}</title> |
belaran@999 | 1992 |
belaran@999 | 1993 <para id="x_4e">Lorsqu'on effectue une opération de commit, Mercurial |
belaran@999 | 1994 lance automatiquement un éditeur de texte pour permettre de saisir |
belaran@999 | 1995 un message qui décrira les modifications effectuées dans cette |
belaran@999 | 1996 révision. Ce message est nommé le <emphasis>message de commit</emphasis>. |
belaran@999 | 1997 Ce sera un enregistrement pour tout lecteur expliquant le pourquoi |
belaran@999 | 1998 et le comment de vos modifications, et il sera affiché par la |
belaran@999 | 1999 commande <command role="hg-cmd" moreinfo="none">hg log</command>.</para> |
belaran@999 | 2000 |
belaran@999 | 2001 <!-- BEGIN tour.commit --> |
belaran@999 | 2002 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit</userinput> |
belaran@999 | 2003 </screen> |
belaran@999 | 2004 <!-- END tour.commit --> |
belaran@999 | 2005 |
belaran@999 | 2006 |
belaran@999 | 2007 <para id="x_4f">L'éditeur que la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2008 commit</command> déclenche ne contiendra qu'une ligne vide suivi |
belaran@999 | 2009 d'un certain nombre de lignes commençant par <quote><literal moreinfo="none">HG: |
belaran@999 | 2010 </literal></quote>.</para> |
belaran@999 | 2011 |
belaran@999 | 2012 <programlisting format="linespecific"> |
belaran@999 | 2013 This is where I type my commit comment. |
belaran@999 | 2014 |
belaran@999 | 2015 HG: Enter commit message. Lines beginning with 'HG:' are removed. |
belaran@999 | 2016 HG: -- |
belaran@999 | 2017 HG: user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2018 HG: branch 'default' |
belaran@999 | 2019 HG: changed hello.c</programlisting> |
belaran@999 | 2020 |
belaran@999 | 2021 |
belaran@999 | 2022 <para id="x_50">Mercurial ignore les lignes qui commencent |
belaran@999 | 2023 avec <quote><literal moreinfo="none">HG:</literal></quote>, il ne les |
belaran@999 | 2024 utilise que pour nous indiquer quels fichiers modifiés il se |
belaran@999 | 2025 prépare à \textit{commiter}. Modifier ou effacer ces lignes n'a |
belaran@999 | 2026 aucune conséquence sur l'opération de commit. |
belaran@999 | 2027 </para> |
belaran@999 | 2028 |
belaran@999 | 2029 </sect2> |
belaran@999 | 2030 <sect2> |
belaran@999 | 2031 <title>Rédiger un message \textit{approprié}</title> |
belaran@999 | 2032 |
belaran@999 | 2033 <para id="x_51">Comme <command role="hg-cmd" moreinfo="none">hg log</command> n'affiche |
belaran@999 | 2034 que la première ligne du message de commit par défaut, il est souvent |
belaran@999 | 2035 considéré comme une bonne pratique de rédiger des messages de commit |
belaran@999 | 2036 qui tiennent sur une seule ligne. Voilà un exemple concret de message |
belaran@999 | 2037 de commit qui <emphasis>ne suit pas</emphasis> cette directive, et |
belaran@999 | 2038 qui a donc un résumé peu lisible.</para> |
belaran@999 | 2039 |
belaran@999 | 2040 <programlisting format="linespecific"> |
belaran@999 | 2041 changeset: 73:584af0e231be |
belaran@999 | 2042 user: Censored Person <censored.person@example.org> |
belaran@999 | 2043 date: Tue Sep 26 21:37:07 2006 -0700 |
belaran@999 | 2044 summary: include buildmeister/commondefs. Add an exports and install |
belaran@999 | 2045 </programlisting> |
belaran@999 | 2046 |
belaran@999 | 2047 <para id="x_52">A ce sujet, il faut noter qu'il n'existe pas de règle |
belaran@999 | 2048 absolue dans ce domaine. Mercurial lui-même n'interprète pas les |
belaran@999 | 2049 contenus des messages de commit, ainsi votre projet est libre de |
belaran@999 | 2050 concevoir différentes politiques de mise en page des messages.</para> |
belaran@999 | 2051 |
belaran@999 | 2052 <para id="x_53">Ma préférence personnelle va au message court, mais |
belaran@999 | 2053 informatif, qui offre des précisions supplémentaires par rapport à ce |
belaran@999 | 2054 que pourrait m'apprendre une commande <command role="hg-cmd" moreinfo="none">hg log |
belaran@999 | 2055 --patch</command>.</para> |
belaran@999 | 2056 |
belaran@999 | 2057 <para id="x_55">Si vous exécutez la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2058 commit</command> sans aucun argument, elle enregistre tous les |
belaran@999 | 2059 changements qui ont été fait, et qui sont indiqué par les commandes |
belaran@999 | 2060 <command role="hg-cmd" moreinfo="none">hg status</command> et <command role="hg-cmd" moreinfo="none">hg diff</command>.</para> |
belaran@999 | 2061 |
belaran@999 | 2062 <note> |
belaran@999 | 2063 <title>Une surprise pour les utilisateurs habitués à Subversion</title> |
belaran@999 | 2064 |
belaran@999 | 2065 <para id="x_717">Comme n'importe quel autre commande de Mercurial, si |
belaran@999 | 2066 vous soumettez pas de manière explicite les noms des fichiers à |
belaran@999 | 2067 committer à la commande <command role="hg-cmd" moreinfo="none">hg commit</command>, elle |
belaran@999 | 2068 va travailler sur l'ensemble du répertoire de travail. Soyez conscient |
belaran@999 | 2069 de ceci si vous venez du monde Subversion ou CVS, car vous pourriez |
belaran@999 | 2070 attendre qu'elle opère uniquement le répertoire courant et ses sous |
belaran@999 | 2071 répertoires.</para> |
belaran@999 | 2072 </note> |
belaran@999 | 2073 </sect2> |
belaran@999 | 2074 <sect2> |
belaran@999 | 2075 <title>Annuler un \textit{commit}</title> |
belaran@999 | 2076 |
belaran@999 | 2077 <para id="x_54">Si, en rédigeant le message, vous décidez que |
belaran@999 | 2078 finalement vous ne voulez pas effectuer ce commit, il suffit |
belaran@999 | 2079 de quitter simplement l'éditeur sans sauver. Ceci n'aura aucune |
belaran@999 | 2080 conséquence sur le dépôt ou les fichiers du répertoire de |
belaran@999 | 2081 travail.</para> |
belaran@999 | 2082 </sect2> |
belaran@999 | 2083 |
belaran@999 | 2084 <sect2> |
belaran@999 | 2085 <title>Admirer votre travail</title> |
belaran@999 | 2086 |
belaran@999 | 2087 <para id="x_56">Une fois que votre \textit{commit} est terminé, vous |
belaran@999 | 2088 pouvez utiliser la commande <command role="hg-cmd" moreinfo="none">hg tip</command> |
belaran@999 | 2089 pour afficher le \textit{changeset} que vous venez de créer. Cette |
belaran@999 | 2090 commande produit une sortie à l'écran qui est identique à celle du |
belaran@999 | 2091 <command role="hg-cmd" moreinfo="none">hg log</command>, mais qui n'affiche que la |
belaran@999 | 2092 dernière révision du dépôt.</para> |
belaran@999 | 2093 |
belaran@999 | 2094 <!-- BEGIN tour.tip --> |
belaran@999 | 2095 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -vp</userinput> |
belaran@999 | 2096 changeset: 5:c94f208d1dfb |
belaran@999 | 2097 tag: tip |
belaran@999 | 2098 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2099 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2100 files: hello.c |
belaran@999 | 2101 description: |
belaran@999 | 2102 Added an extra line of output |
belaran@999 | 2103 |
belaran@999 | 2104 |
belaran@999 | 2105 diff -r 2278160e78d4 -r c94f208d1dfb hello.c |
belaran@999 | 2106 --- a/hello.c Sat Aug 16 22:16:53 2008 +0200 |
belaran@999 | 2107 +++ b/hello.c Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2108 @@ -8,5 +8,6 @@ |
belaran@999 | 2109 int main(int argc, char **argv) |
belaran@999 | 2110 { |
belaran@999 | 2111 printf("hello, world!\"); |
belaran@999 | 2112 + printf("hello again!\n"); |
belaran@999 | 2113 return 0; |
belaran@999 | 2114 } |
belaran@999 | 2115 |
belaran@999 | 2116 </screen> |
belaran@999 | 2117 <!-- END tour.tip --> |
belaran@999 | 2118 |
belaran@999 | 2119 |
belaran@999 | 2120 <para id="x_57">On fait couramment référence à la dernière révision |
belaran@999 | 2121 du dépôt comme étant la <emphasis>révision tip</emphasis>, ou plus |
belaran@999 | 2122 simplement le <emphasis>tip</emphasis>.</para> |
belaran@999 | 2123 |
belaran@999 | 2124 <para id="x_684">Au passage, la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2125 tip</command> accepte la plupart des options qu'accepte |
belaran@999 | 2126 <command role="hg-cmd" moreinfo="none">hg log</command>. Ainsi <option role="hg-opt-global">-v</option> ci dessus implique <quote>soit |
belaran@999 | 2127 verbeux</quote>, <option role="hg-opt-tip">-p</option> |
belaran@999 | 2128 veux dire <quote>affiche le patch</quote>. L'utilisation de l'option |
belaran@999 | 2129 <option role="hg-opt-tip">-p</option> pour afficher un patch est un |
belaran@999 | 2130 autre exemple de la cohérence des commandes évoquée plus tôt.</para> |
belaran@999 | 2131 |
belaran@999 | 2132 </sect2> |
belaran@999 | 2133 </sect1> |
belaran@999 | 2134 <sect1> |
belaran@999 | 2135 <title>Partager ses modifications</title> |
belaran@999 | 2136 |
belaran@999 | 2137 <para id="x_58">Nous avons mentionné plus haut que les dépôts |
belaran@999 | 2138 de Mercurial sont autosuffisants. Ce qui signifie que la nouvelle |
belaran@999 | 2139 révision que vous venez de créer existe seulement dans votre |
belaran@999 | 2140 répertoire <filename class="directory" moreinfo="none">my-hello</filename>. Étudions |
belaran@999 | 2141 comment propager cette modification dans d'autres dépôts.</para> |
belaran@999 | 2142 |
belaran@999 | 2143 <sect2 id="sec:tour:pull"> |
belaran@999 | 2144 <title>Récupérer les modifications d'autres dépôts</title> |
belaran@999 | 2145 |
belaran@999 | 2146 <para id="x_59">Pour commencer, construisons un clone de notre dépôt |
belaran@999 | 2147 <filename class="directory" moreinfo="none">hello</filename> qui ne contiendra pas |
belaran@999 | 2148 le changement que nous venons d'effectuer. Nous l'appellerons notre |
belaran@999 | 2149 dépôt temporaire <filename class="directory" moreinfo="none">hello-pull</filename>.</para> |
belaran@999 | 2150 |
belaran@999 | 2151 <!-- BEGIN tour.clone-pull --> |
belaran@999 | 2152 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 2153 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-pull</userinput> |
belaran@999 | 2154 updating working directory |
belaran@999 | 2155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2156 </screen> |
belaran@999 | 2157 <!-- END tour.clone-pull --> |
belaran@999 | 2158 |
belaran@999 | 2159 |
belaran@999 | 2160 <para id="x_5a">Nous allons utiliser la commande <command role="hg-cmd" moreinfo="none">hg pull</command> pour envoyer les modifications |
belaran@999 | 2161 depuis <filename class="directory" moreinfo="none">my-hello</filename> dans <filename class="directory" moreinfo="none">hello-pull</filename>. Néanmoins, récupérer |
belaran@999 | 2162 aveuglement des modifications depuis un dépôt a quelque chose d'un |
belaran@999 | 2163 peu effrayant. Mercurial propose donc une commande <command role="hg-cmd" moreinfo="none">hg incoming</command> qui permet de savoir quelles |
belaran@999 | 2164 modifications la commande <command role="hg-cmd" moreinfo="none">hg pull</command> |
belaran@999 | 2165 <emphasis>pourrait</emphasis> entraîner dans notre dépôt, et ceci |
belaran@999 | 2166 sans effectuer réellement de modification dessus.</para> |
belaran@999 | 2167 |
belaran@999 | 2168 <!-- BEGIN tour.incoming --> |
belaran@999 | 2169 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hello-pull</userinput> |
belaran@999 | 2170 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg incoming ../my-hello</userinput> |
belaran@999 | 2171 comparing with ../my-hello |
belaran@999 | 2172 searching for changes |
belaran@999 | 2173 changeset: 5:c94f208d1dfb |
belaran@999 | 2174 tag: tip |
belaran@999 | 2175 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2176 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2177 summary: Added an extra line of output |
belaran@999 | 2178 |
belaran@999 | 2179 </screen> |
belaran@999 | 2180 <!-- END tour.incoming --> |
belaran@999 | 2181 |
belaran@999 | 2182 |
belaran@999 | 2183 <para id="x_5c">Apporter les modifications rapatriées dans un dépôt se |
belaran@999 | 2184 résume donc à exécuter la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2185 pull</command>, et préciser depuis quel dépôt effectuer le <command role="hg-cmd" moreinfo="none">hg pull</command>.</para> |
belaran@999 | 2186 |
belaran@999 | 2187 <!-- BEGIN tour.pull --> |
belaran@999 | 2188 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 2189 changeset: 4:2278160e78d4 |
belaran@999 | 2190 tag: tip |
belaran@999 | 2191 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2192 date: Sat Aug 16 22:16:53 2008 +0200 |
belaran@999 | 2193 summary: Trim comments. |
belaran@999 | 2194 |
belaran@999 | 2195 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput> |
belaran@999 | 2196 pulling from ../my-hello |
belaran@999 | 2197 searching for changes |
belaran@999 | 2198 adding changesets |
belaran@999 | 2199 adding manifests |
belaran@999 | 2200 adding file changes |
belaran@999 | 2201 added 1 changesets with 1 changes to 1 files |
belaran@999 | 2202 (run 'hg update' to get a working copy) |
belaran@999 | 2203 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 2204 changeset: 5:c94f208d1dfb |
belaran@999 | 2205 tag: tip |
belaran@999 | 2206 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2207 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2208 summary: Added an extra line of output |
belaran@999 | 2209 |
belaran@999 | 2210 </screen> |
belaran@999 | 2211 <!-- END tour.pull --> |
belaran@999 | 2212 |
belaran@999 | 2213 |
belaran@999 | 2214 <para id="x_5d">Comme vous le voyez avec une sortie avant et après de la |
belaran@999 | 2215 commande <command role="hg-cmd" moreinfo="none">hg tip</command>, nous avons réussi à |
belaran@999 | 2216 récupérer aisément les modifications dans notre dépôt. Il reste néanmoins |
belaran@999 | 2217 quelque chose à faire avant de placer ces modifications dans l'espace de |
belaran@999 | 2218 travail.</para> |
belaran@999 | 2219 |
belaran@999 | 2220 <tip> |
belaran@999 | 2221 <title>Récupérer des changements précis</title> |
belaran@999 | 2222 |
belaran@999 | 2223 <para id="x_5b">Il est possible à cause du délai entre l'exécution de la |
belaran@999 | 2224 commande <command role="hg-cmd" moreinfo="none">hg incoming</command> et l'exécution de |
belaran@999 | 2225 la commande <command role="hg-cmd" moreinfo="none">hg pull</command>, que vous ne |
belaran@999 | 2226 puissiez pas voir toutes les modifications que vous rapporterez d'un |
belaran@999 | 2227 autre dépôt. Supposons que vous récupériez les modifications d'un dépôt |
belaran@999 | 2228 situé quelque part sur le réseau. Alors que vous regardez le résultat de |
belaran@999 | 2229 la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>, et avant que |
belaran@999 | 2230 vous ne décidiez de récupérer ces modifications, quelqu'un peut ajouter |
belaran@999 | 2231 de nouvelles révisions dans le dépôt distant. Ce qui signifie que vous |
belaran@999 | 2232 récupérez plus de révision que ce que vous aviez regardées en utilisant |
belaran@999 | 2233 la commande <command role="hg-cmd" moreinfo="none">hg incoming</command>.</para> |
belaran@999 | 2234 |
belaran@999 | 2235 <para id="x_718">Si vous voulez seulement récupérer ce que vous aviez |
belaran@999 | 2236 vérifier à l'aide de la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2237 incoming</command>, ou que pour d'autres raisons vous souhaitiez ne |
belaran@999 | 2238 récupérer qu'un sous ensemble des révisions supplémentaires |
belaran@999 | 2239 disponibles, indiquant simplement les modifications que vous souhaitez |
belaran@999 | 2240 récupérer par leurs ID de révision, soit <command moreinfo="none">hg pull |
belaran@999 | 2241 -r7e95bb</command>. </para> |
belaran@999 | 2242 </tip> |
belaran@999 | 2243 |
belaran@999 | 2244 </sect2> |
belaran@999 | 2245 <sect2> |
belaran@999 | 2246 <title>Mise à jour de l'espace de travail</title> |
belaran@999 | 2247 |
belaran@999 | 2248 <para id="x_5e">Nous avons jusqu'à maintenant grossièrement défini la |
belaran@999 | 2249 relation entre un dépôt et un espace de travail. La commande <command role="hg-cmd" moreinfo="none">hg pull</command> que nous avons exécutée dans la section |
belaran@999 | 2250 <xref linkend="sec:tour:pull"/> a apporté des modifications, que nous |
belaran@999 | 2251 avons vérifiées, dans notre dépôt, mais il n'y a aucune trace de ces |
belaran@999 | 2252 modifications dans notre espace de travail. En effet, <command role="hg-cmd" moreinfo="none">hg pull</command> ne touche pas (par défaut) à l'espace |
belaran@999 | 2253 de travail. C'est la commande <command role="hg-cmd" moreinfo="none">hg update</command> |
belaran@999 | 2254 qui s'en charge.</para> |
belaran@999 | 2255 |
belaran@999 | 2256 <!-- BEGIN tour.update --> |
belaran@999 | 2257 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput> |
belaran@999 | 2258 printf("hello, world!\"); |
belaran@999 | 2259 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update tip</userinput> |
belaran@999 | 2260 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2261 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">grep printf hello.c</userinput> |
belaran@999 | 2262 printf("hello, world!\"); |
belaran@999 | 2263 printf("hello again!\n"); |
belaran@999 | 2264 </screen> |
belaran@999 | 2265 <!-- END tour.update --> |
belaran@999 | 2266 |
belaran@999 | 2267 |
belaran@999 | 2268 <para id="x_5f">Il peut sembler un peu étrange que la commande <command role="hg-cmd" moreinfo="none">hg pull</command> ne mette pas à jour l'espace de travail |
belaran@999 | 2269 automatiquement. Il y a en fait une très bonne raison à cela : vous |
belaran@999 | 2270 pouvez utilisez la commande <command role="hg-cmd" moreinfo="none">hg update</command> |
belaran@999 | 2271 pour mettre à jour votre espace de travail à l'état dans lequel il était |
belaran@999 | 2272 à <emphasis>n'importe quelle révision</emphasis> de l'historique du dépôt. |
belaran@999 | 2273 Si vous aviez un espace de travail contenant une ancienne |
belaran@999 | 2274 révision—pour chercher l'origine d'un bug, par exemple—et |
belaran@999 | 2275 que vous effectuiez un <command role="hg-cmd" moreinfo="none">hg pull</command> qui |
belaran@999 | 2276 mettrait à jour automatiquement votre espace de travail, vous ne seriez |
belaran@999 | 2277 probablement pas très satisfait.</para> |
belaran@999 | 2278 |
belaran@999 | 2279 <para id="x_60">Néanmoins, comme les opérations de pull sont très souvent |
belaran@999 | 2280 suivies d'un update, Mercurial vous permet de combiner les |
belaran@999 | 2281 deux aisément en passant l'option <option role="hg-opt-pull">-u</option> |
belaran@999 | 2282 à la commande <command role="hg-cmd" moreinfo="none">hg pull</command>.</para> |
belaran@999 | 2283 |
belaran@999 | 2284 <para id="x_61">Si vous étudiez de nouveau la sortie de la commande <command role="hg-cmd" moreinfo="none">hg pull</command> dans la section <xref linkend="sec:tour:pull"/> quand nous l'avons exécutée sans l'option |
belaran@999 | 2285 <option role="hg-opt-pull">-u</option>, vous pouvez constater qu'elle a |
belaran@999 | 2286 affiché un rappel assez utile : vous devez encore effectuer une |
belaran@999 | 2287 opération pour mettre à jour votre espace de travail.</para> |
belaran@999 | 2288 |
belaran@999 | 2289 <para id="x_62">Pour découvrir sur quelle révision de l'espace de |
belaran@999 | 2290 travail on se trouve, utilisez la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2291 parents</command>.</para> |
belaran@999 | 2292 |
belaran@999 | 2293 <!-- BEGIN tour.parents --> |
belaran@999 | 2294 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 2295 changeset: 5:c94f208d1dfb |
belaran@999 | 2296 tag: tip |
belaran@999 | 2297 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2298 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2299 summary: Added an extra line of output |
belaran@999 | 2300 |
belaran@999 | 2301 </screen> |
belaran@999 | 2302 <!-- END tour.parents --> |
belaran@999 | 2303 |
belaran@999 | 2304 |
belaran@999 | 2305 <para id="x_63">Si vous regardez de nouveau le dessin <xref linkend="fig:tour-basic:history"/>, vous verrez les flèches reliant |
belaran@999 | 2306 entre elles les révisions. Le nœud d'où la flèche |
belaran@999 | 2307 <emphasis>part</emphasis> est dans chaque cas un parent, |
belaran@999 | 2308 et le nœud où la flèche <emphasis>arrive</emphasis> est un |
belaran@999 | 2309 enfant.</para> |
belaran@999 | 2310 |
belaran@999 | 2311 <para id="x_64">Pour mettre à jour l'espace de travail d'une révision |
belaran@999 | 2312 particulière, indiquez un numéro de révision ou un \textit{changeset |
belaran@999 | 2313 ID} à la commande <command role="hg-cmd" moreinfo="none">hg update</command>.</para> |
belaran@999 | 2314 |
belaran@999 | 2315 <!-- BEGIN tour.older --> |
belaran@999 | 2316 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update 2</userinput> |
belaran@999 | 2317 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2318 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 2319 changeset: 2:fef857204a0c |
belaran@999 | 2320 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2321 date: Sat Aug 16 22:05:04 2008 +0200 |
belaran@999 | 2322 summary: Introduce a typo into hello.c. |
belaran@999 | 2323 |
belaran@999 | 2324 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput> |
belaran@999 | 2325 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2326 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 2327 changeset: 5:c94f208d1dfb |
belaran@999 | 2328 tag: tip |
belaran@999 | 2329 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2330 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2331 summary: Added an extra line of output |
belaran@999 | 2332 |
belaran@999 | 2333 </screen> |
belaran@999 | 2334 <!-- END tour.older --> |
belaran@999 | 2335 |
belaran@999 | 2336 |
belaran@999 | 2337 <para id="x_65">Si vous ne précisez pas de manière explicite de numéro |
belaran@999 | 2338 de révision la commande <command role="hg-cmd" moreinfo="none">hg update</command> |
belaran@999 | 2339 mettra à jour votre espace de travail avec le contenu de la révison |
belaran@999 | 2340 \textit{tip}, comme montré dans l'exemple ci dessus lors du second |
belaran@999 | 2341 appel à <command role="hg-cmd" moreinfo="none">hg update</command>.</para> |
belaran@999 | 2342 |
belaran@999 | 2343 </sect2> |
belaran@999 | 2344 <sect2> |
belaran@999 | 2345 <title>Transférer les modifications vers un autre dépôt</title> |
belaran@999 | 2346 |
belaran@999 | 2347 <para id="x_66">Mercurial vous laisse transférer les modifications vers |
belaran@999 | 2348 un autre dépôt, depuis votre dépôt actuel. Comme dans l'exemple du |
belaran@999 | 2349 <command role="hg-cmd" moreinfo="none">hg pull</command> ci-dessus, nous allons créer |
belaran@999 | 2350 un dépôt temporaire vers lequel transférer nos modifications.</para> |
belaran@999 | 2351 |
belaran@999 | 2352 <!-- BEGIN tour.clone-push --> |
belaran@999 | 2353 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 2354 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello hello-push</userinput> |
belaran@999 | 2355 updating working directory |
belaran@999 | 2356 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2357 </screen> |
belaran@999 | 2358 <!-- END tour.clone-push --> |
belaran@999 | 2359 |
belaran@999 | 2360 |
belaran@999 | 2361 <para id="x_67">La commande <command role="hg-cmd" moreinfo="none">hg outgoing</command> |
belaran@999 | 2362 nous indique quels changements nous allons transférer vers l'autre |
belaran@999 | 2363 serveur.</para> |
belaran@999 | 2364 |
belaran@999 | 2365 <!-- BEGIN tour.outgoing --> |
belaran@999 | 2366 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-hello</userinput> |
belaran@999 | 2367 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing ../hello-push</userinput> |
belaran@999 | 2368 comparing with ../hello-push |
belaran@999 | 2369 searching for changes |
belaran@999 | 2370 changeset: 5:c94f208d1dfb |
belaran@999 | 2371 tag: tip |
belaran@999 | 2372 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2373 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2374 summary: Added an extra line of output |
belaran@999 | 2375 |
belaran@999 | 2376 </screen> |
belaran@999 | 2377 <!-- END tour.outgoing --> |
belaran@999 | 2378 |
belaran@999 | 2379 |
belaran@999 | 2380 <para id="x_68">Et la commande <command role="hg-cmd" moreinfo="none">hg push</command> |
belaran@999 | 2381 effectue réellement le transfert.</para> |
belaran@999 | 2382 |
belaran@999 | 2383 <!-- BEGIN tour.push --> |
belaran@999 | 2384 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput> |
belaran@999 | 2385 pushing to ../hello-push |
belaran@999 | 2386 searching for changes |
belaran@999 | 2387 adding changesets |
belaran@999 | 2388 adding manifests |
belaran@999 | 2389 adding file changes |
belaran@999 | 2390 added 1 changesets with 1 changes to 1 files |
belaran@999 | 2391 </screen> |
belaran@999 | 2392 <!-- END tour.push --> |
belaran@999 | 2393 |
belaran@999 | 2394 |
belaran@999 | 2395 <para id="x_69">Comme avec <command role="hg-cmd" moreinfo="none">hg pull</command>, la |
belaran@999 | 2396 commande <command role="hg-cmd" moreinfo="none">hg push</command> ne met pas à jour |
belaran@999 | 2397 le répertoire de travail du dépôt dans lequel il transfère les |
belaran@999 | 2398 modifications. À l'inverse de <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2399 pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> ne fournit |
belaran@999 | 2400 pas d'option <literal moreinfo="none">-u</literal> pour forcer la mise à jour de |
belaran@999 | 2401 l'espace de travail cible. Cette asymétrie est délibéré : le dépot |
belaran@999 | 2402 vers lequel nous transférons peut très bien être un serveur distant |
belaran@999 | 2403 et partagé par plusieurs personnes. Si nous devions mettre à jour son |
belaran@999 | 2404 répertoire de travail alors que quelqu'un d'autre travaille dessus, |
belaran@999 | 2405 nous risquerions de perturber son travail.</para> |
belaran@999 | 2406 |
belaran@999 | 2407 <para id="x_6a">Qu'est ce qui se passe lorsque vous essayez de récupérer |
belaran@999 | 2408 ou de transférer vos modifications et que le dépôt cible a déjà reçu |
belaran@999 | 2409 ces modifications ? Rien de bien excitant.</para> |
belaran@999 | 2410 |
belaran@999 | 2411 <!-- BEGIN tour.push.nothing --> |
belaran@999 | 2412 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push ../hello-push</userinput> |
belaran@999 | 2413 pushing to ../hello-push |
belaran@999 | 2414 searching for changes |
belaran@999 | 2415 no changes found |
belaran@999 | 2416 </screen> |
belaran@999 | 2417 <!-- END tour.push.nothing --> |
belaran@999 | 2418 |
belaran@999 | 2419 |
belaran@999 | 2420 </sect2> |
belaran@999 | 2421 |
belaran@999 | 2422 <sect2> |
belaran@999 | 2423 <title>Emplacements par défaut</title> |
belaran@999 | 2424 |
belaran@999 | 2425 <para id="x_719">Quand nous faisons un clone d'un dépôt, Mercurial |
belaran@999 | 2426 enregistre l'emplacement du dépôt d'origine dans le fichier |
belaran@999 | 2427 <filename moreinfo="none">.hg/hgrc</filename> de notre nouveau dépôt. Si nous ne |
belaran@999 | 2428 fournissons pas d'emplacement à la commande <command moreinfo="none">hg |
belaran@999 | 2429 pull</command> ou à la commande <command moreinfo="none">hg push</command>, ces |
belaran@999 | 2430 commandes utiliseront alors cet emplacement comme valeur par défaut. |
belaran@999 | 2431 Les commandes <command moreinfo="none">hg incoming</command> et <command moreinfo="none">hg |
belaran@999 | 2432 outgoing</command> feront de même.</para> |
belaran@999 | 2433 |
belaran@999 | 2434 <para id="x_71a">Si vous regardez le fichier |
belaran@999 | 2435 <filename moreinfo="none">.hg/hgrc</filename>, vous constaterez que son contenu |
belaran@999 | 2436 ressemble à ce qui suit.</para> |
belaran@999 | 2437 |
belaran@999 | 2438 <programlisting format="linespecific">[paths] |
belaran@999 | 2439 default = http://www.selenic.com/repo/hg</programlisting> |
belaran@999 | 2440 |
belaran@999 | 2441 <para id="x_71b">Il est possible—et souvent |
belaran@999 | 2442 pratique—d'avoir un emplacement par défaut pour les commandes |
belaran@999 | 2443 <command moreinfo="none">hg push</command> et <command moreinfo="none">hg outgoing</command> |
belaran@999 | 2444 différent de celui des commandes <command moreinfo="none">hg pull</command> et |
belaran@999 | 2445 <command moreinfo="none">hg incoming</command>. C'est faisable en ajoutant une entrée |
belaran@999 | 2446 <literal moreinfo="none">default-push</literal> à la section |
belaran@999 | 2447 <literal moreinfo="none">[paths]</literal> du <filename moreinfo="none">.hg/hgrc</filename>, comme |
belaran@999 | 2448 suit.</para> |
belaran@999 | 2449 |
belaran@999 | 2450 <programlisting format="linespecific">[paths] |
belaran@999 | 2451 default = http://www.selenic.com/repo/hg |
belaran@999 | 2452 default-push = http://hg.example.com/hg</programlisting> |
belaran@999 | 2453 |
belaran@999 | 2454 </sect2> |
belaran@999 | 2455 <sect2> |
belaran@999 | 2456 <title>Partager ses modifications à travers le réseau</title> |
belaran@999 | 2457 |
belaran@999 | 2458 <para id="x_6b">Les commandes que nous avons étudiées dans les sections |
belaran@999 | 2459 précédentes ne sont pas limitées aux dépôts locaux. Chacune fonctionne |
belaran@999 | 2460 de la même manière à travers une connexion réseau, il suffit de lui |
belaran@999 | 2461 passer une URL à la place d'un chemin de fichier local.</para> |
belaran@999 | 2462 |
belaran@999 | 2463 <!-- BEGIN tour.outgoing.net --> |
belaran@999 | 2464 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg outgoing http://hg.serpentine.com/tutorial/hello</userinput> |
belaran@999 | 2465 comparing with http://hg.serpentine.com/tutorial/hello |
belaran@999 | 2466 searching for changes |
belaran@999 | 2467 changeset: 5:c94f208d1dfb |
belaran@999 | 2468 tag: tip |
belaran@999 | 2469 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2470 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2471 summary: Added an extra line of output |
belaran@999 | 2472 |
belaran@999 | 2473 </screen> |
belaran@999 | 2474 <!-- END tour.outgoing.net --> |
belaran@999 | 2475 |
belaran@999 | 2476 |
belaran@999 | 2477 <para id="x_6c">Dans cet exemple, nous allons voir quels changements |
belaran@999 | 2478 nous pourrions transférer vers le dépôt distant, mais le dépôt est, |
belaran@999 | 2479 de manière tout à fait compréhensible, pas configuré pour accepter |
belaran@999 | 2480 des modifications d'utilisateurs anonymes.</para> |
belaran@999 | 2481 |
belaran@999 | 2482 <!-- BEGIN tour.push.net --> |
belaran@999 | 2483 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push http://hg.serpentine.com/tutorial/hello</userinput> |
belaran@999 | 2484 pushing to http://hg.serpentine.com/tutorial/hello |
belaran@999 | 2485 searching for changes |
belaran@999 | 2486 ssl required |
belaran@999 | 2487 </screen> |
belaran@999 | 2488 <!-- END tour.push.net --> |
belaran@999 | 2489 |
belaran@999 | 2490 |
belaran@999 | 2491 </sect2> |
belaran@999 | 2492 |
belaran@999 | 2493 </sect1> |
belaran@999 | 2494 |
belaran@999 | 2495 <sect1> |
belaran@999 | 2496 <title>Commencer un nouveau projet</title> |
belaran@999 | 2497 |
belaran@999 | 2498 <para id="x_71c">Il est tout aussi aisé de commencer un nouveau projet |
belaran@999 | 2499 que de travailler sur un qui existe déjà. La commande <command moreinfo="none">hg |
belaran@999 | 2500 init</command> crée un nouveau dépôt Mercurial vide.</para> |
belaran@999 | 2501 |
belaran@999 | 2502 <!-- BEGIN ch01/new.init --> |
belaran@999 | 2503 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myproject</userinput> |
belaran@999 | 2504 </screen> |
belaran@999 | 2505 <!-- END ch01/new.init --> |
belaran@999 | 2506 |
belaran@999 | 2507 |
belaran@999 | 2508 <para id="x_71d">Ceci crée simplement un répertoire nommé |
belaran@999 | 2509 <filename moreinfo="none">myproject</filename> dans le répertoire courant.</para> |
belaran@999 | 2510 |
belaran@999 | 2511 <!-- BEGIN ch01/new.ls --> |
belaran@999 | 2512 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -l</userinput> |
belaran@999 | 2513 total 12 |
belaran@999 | 2514 -rw-r--r-- 1 rpelisse rpelisse 47 Aug 16 14:04 goodbye.c |
belaran@999 | 2515 -rw-r--r-- 1 rpelisse rpelisse 45 Aug 16 14:04 hello.c |
belaran@999 | 2516 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 myproject |
belaran@999 | 2517 </screen> |
belaran@999 | 2518 <!-- END ch01/new.ls --> |
belaran@999 | 2519 |
belaran@999 | 2520 |
belaran@999 | 2521 <para id="x_71e">Nous pouvons dire que <filename moreinfo="none">myproject</filename> est |
belaran@999 | 2522 un dépôt Mercurial car il contient un répertoire |
belaran@999 | 2523 <filename moreinfo="none">.hg</filename>.</para> |
belaran@999 | 2524 |
belaran@999 | 2525 <!-- BEGIN ch01/new.ls2 --> |
belaran@999 | 2526 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls -al myproject</userinput> |
belaran@999 | 2527 total 12 |
belaran@999 | 2528 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 . |
belaran@999 | 2529 drwx------ 3 rpelisse rpelisse 4096 Aug 16 14:04 .. |
belaran@999 | 2530 drwxr-xr-x 3 rpelisse rpelisse 4096 Aug 16 14:04 .hg |
belaran@999 | 2531 </screen> |
belaran@999 | 2532 <!-- END ch01/new.ls2 --> |
belaran@999 | 2533 |
belaran@999 | 2534 |
belaran@999 | 2535 <para id="x_71f">Si vous voulons ajouter quelques fichiers préexistants |
belaran@999 | 2536 dans ce dépôt, il suffit de les recopier dans le répertoire de travail, |
belaran@999 | 2537 et demander à Mercurial de commencer à les suivre en utilisant la |
belaran@999 | 2538 commande <command moreinfo="none">hg add</command>.</para> |
belaran@999 | 2539 |
belaran@999 | 2540 <!-- BEGIN ch01/new.add --> |
belaran@999 | 2541 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput> |
belaran@999 | 2542 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../hello.c .</userinput> |
belaran@999 | 2543 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp ../goodbye.c .</userinput> |
belaran@999 | 2544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add</userinput> |
belaran@999 | 2545 adding goodbye.c |
belaran@999 | 2546 adding hello.c |
belaran@999 | 2547 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 2548 A goodbye.c |
belaran@999 | 2549 A hello.c |
belaran@999 | 2550 </screen> |
belaran@999 | 2551 <!-- END ch01/new.add --> |
belaran@999 | 2552 |
belaran@999 | 2553 |
belaran@999 | 2554 <para id="x_720">Une fois que nous sommes satisfaits de notre projet, |
belaran@999 | 2555 nous pouvons commencer à ajouter nos révisions.</para> |
belaran@999 | 2556 |
belaran@999 | 2557 <!-- BEGIN ch01/new.commit --> |
belaran@999 | 2558 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Initial commit'</userinput> |
belaran@999 | 2559 </screen> |
belaran@999 | 2560 <!-- END ch01/new.commit --> |
belaran@999 | 2561 |
belaran@999 | 2562 |
belaran@999 | 2563 <para id="x_721">Il ne prend que quelques instants pour commencer à |
belaran@999 | 2564 utiliser Mercurial sur un nouveau projet, ce qui fait aussi de ses |
belaran@999 | 2565 points forts. Travailler avec une gestion de révision devient très |
belaran@999 | 2566 facile, nous pouvons même l'utiliser pour les plus petits projets où |
belaran@999 | 2567 nous aurions probablement jamais penser utiliser un outils aussi |
belaran@999 | 2568 complexe.</para> |
belaran@999 | 2569 </sect1> |
belaran@999 | 2570 </chapter> |
belaran@999 | 2571 |
belaran@999 | 2572 <!-- |
belaran@999 | 2573 local variables: |
belaran@999 | 2574 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 2575 end: |
belaran@999 | 2576 --> |
belaran@999 | 2577 |
belaran@999 | 2578 <!-- BEGIN ch03 --> |
belaran@999 | 2579 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 2580 |
belaran@999 | 2581 <chapter id="chap:tour-merge"> |
belaran@999 | 2582 <?dbhtml filename="a-tour-of-mercurial-merging-work.html"?> |
belaran@999 | 2583 <title>Un rapide tour de Mercurial: fusionner les travaux</title> |
belaran@999 | 2584 |
belaran@999 | 2585 <para id="x_338">Nous avons maintenant étudié comment cloner un dépôt, effectuer |
belaran@999 | 2586 des changements dedans, et récupérer ou transférer depuis un |
belaran@999 | 2587 autre dépôt. La prochaine étape est donc de <emphasis>fusionner</emphasis> les |
belaran@999 | 2588 modifications de différents dépôts.</para> |
belaran@999 | 2589 |
belaran@999 | 2590 <sect1> |
belaran@999 | 2591 <title>Fusionner différents travaux</title> |
belaran@999 | 2592 <para id="x_339">La fusion est un aspect fondamental lorsqu'on |
belaran@999 | 2593 travaille iavec un gestionnaire de source distribué.</para> |
belaran@999 | 2594 |
belaran@999 | 2595 <itemizedlist> |
belaran@999 | 2596 <listitem> |
belaran@999 | 2597 <para id="x_33a">Alice et Bob ont chacun une copie personnelle du dépôt d'un |
belaran@999 | 2598 projet sur lequel ils collaborent. Alice corrige un bug |
belaran@999 | 2599 dans son dépôt, et Bob ajoute une nouvelle fonctionnalité dans le |
belaran@999 | 2600 sien. Ils veulent un dépôt partagé avec à la fois le correctif du |
belaran@999 | 2601 bug et la nouvelle fonctionnalité.</para> |
belaran@999 | 2602 </listitem> |
belaran@999 | 2603 <listitem> |
belaran@999 | 2604 <para id="x_33b">Je travaille régulièrement sur plusieurs tâches différentes sur |
belaran@999 | 2605 un seul projet en même temps, chacun isolé dans son propre dépôt. |
belaran@999 | 2606 Travailler ainsi signifie que je dois régulièrement fusionner une |
belaran@999 | 2607 partie de mon code avec celui des autres.</para> |
belaran@999 | 2608 </listitem> |
belaran@999 | 2609 </itemizedlist> |
belaran@999 | 2610 |
belaran@999 | 2611 <para id="x_33c">Parce que la fusion est une opération si commune à réaliser, |
belaran@999 | 2612 Mercurial la rend facile. Étudions ensemble le déroulement des |
belaran@999 | 2613 opérations. Nous commencerons encore par faire un clone d'un autre |
belaran@999 | 2614 dépôt (vous voyez que l'on fait ça tout le temps ?) puis nous ferons |
belaran@999 | 2615 quelques modifications dessus.</para> |
belaran@999 | 2616 |
belaran@999 | 2617 <!-- BEGIN tour.merge.clone --> |
belaran@999 | 2618 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 2619 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hello my-new-hello</userinput> |
belaran@999 | 2620 updating working directory |
belaran@999 | 2621 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2622 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-new-hello</userinput> |
belaran@999 | 2623 # Make some simple edits to hello.c. |
belaran@999 | 2624 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">my-text-editor hello.c</userinput> |
belaran@999 | 2625 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'A new hello for a new day.'</userinput> |
belaran@999 | 2626 </screen> |
belaran@999 | 2627 <!-- END tour.merge.clone --> |
belaran@999 | 2628 |
belaran@999 | 2629 |
belaran@999 | 2630 <para id="x_33d">Nous devrions avoir maintenant deux copies de |
belaran@999 | 2631 <filename moreinfo="none">hello.c</filename> avec des contenus différents. Les |
belaran@999 | 2632 historiques de ces deux dépôts ont aussi divergés, comme illustré dans |
belaran@999 | 2633 la figure <xref linkend="fig:tour-merge:sep-repos"/>.</para> |
belaran@999 | 2634 |
belaran@999 | 2635 <!-- BEGIN tour.merge.cat1 --> |
belaran@999 | 2636 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> |
belaran@999 | 2637 /* |
belaran@999 | 2638 * Placed in the public domain by Bryan O'Sullivan. This program is |
belaran@999 | 2639 * not covered by patents in the United States or other countries. |
belaran@999 | 2640 */ |
belaran@999 | 2641 |
belaran@999 | 2642 #include <stdio.h> |
belaran@999 | 2643 |
belaran@999 | 2644 int main(int argc, char **argv) |
belaran@999 | 2645 { |
belaran@999 | 2646 printf("once more, hello.\n"); |
belaran@999 | 2647 printf("hello, world!\"); |
belaran@999 | 2648 printf("hello again!\n"); |
belaran@999 | 2649 return 0; |
belaran@999 | 2650 } |
belaran@999 | 2651 </screen> |
belaran@999 | 2652 <!-- END tour.merge.cat1 --> |
belaran@999 | 2653 |
belaran@999 | 2654 |
belaran@999 | 2655 <para id="x_722">Et ici est notre légèrement différente version du |
belaran@999 | 2656 dépôt.</para> |
belaran@999 | 2657 |
belaran@999 | 2658 <!-- BEGIN tour.merge.cat2 --> |
belaran@999 | 2659 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat ../my-hello/hello.c</userinput> |
belaran@999 | 2660 /* |
belaran@999 | 2661 * Placed in the public domain by Bryan O'Sullivan. This program is |
belaran@999 | 2662 * not covered by patents in the United States or other countries. |
belaran@999 | 2663 */ |
belaran@999 | 2664 |
belaran@999 | 2665 #include <stdio.h> |
belaran@999 | 2666 |
belaran@999 | 2667 int main(int argc, char **argv) |
belaran@999 | 2668 { |
belaran@999 | 2669 printf("hello, world!\"); |
belaran@999 | 2670 printf("hello again!\n"); |
belaran@999 | 2671 return 0; |
belaran@999 | 2672 } |
belaran@999 | 2673 </screen> |
belaran@999 | 2674 <!-- END tour.merge.cat2 --> |
belaran@999 | 2675 |
belaran@999 | 2676 |
belaran@999 | 2677 <figure id="fig:tour-merge:sep-repos" float="0"> |
belaran@999 | 2678 <title>Historique divergent des dépôts <filename class="directory" moreinfo="none">my-hello</filename> et <filename class="directory" moreinfo="none">my-new-hello</filename>.</title> |
belaran@999 | 2679 <mediaobject> |
belaran@999 | 2680 <imageobject><imagedata fileref="figs/tour-merge-sep-repos.png"/></imageobject> |
belaran@999 | 2681 <textobject><phrase>XXX ajoute un test</phrase></textobject> |
belaran@999 | 2682 </mediaobject> |
belaran@999 | 2683 </figure> |
belaran@999 | 2684 |
belaran@999 | 2685 <para id="x_33f">Nous savons déjà que récupérer les modifications depuis |
belaran@999 | 2686 notre dépôt <filename class="directory" moreinfo="none">my-hello</filename> n'aura |
belaran@999 | 2687 aucun effet sur l'espace de travail.</para> |
belaran@999 | 2688 |
belaran@999 | 2689 <!-- BEGIN tour.merge.pull --> |
belaran@999 | 2690 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-hello</userinput> |
belaran@999 | 2691 pulling from ../my-hello |
belaran@999 | 2692 searching for changes |
belaran@999 | 2693 adding changesets |
belaran@999 | 2694 adding manifests |
belaran@999 | 2695 adding file changes |
belaran@999 | 2696 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 2697 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 2698 </screen> |
belaran@999 | 2699 <!-- END tour.merge.pull --> |
belaran@999 | 2700 |
belaran@999 | 2701 |
belaran@999 | 2702 <para id="x_340">Néanmoins, la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2703 pull</command> nous indique quelque chose au sujet des |
belaran@999 | 2704 <quote>heads</quote>.</para> |
belaran@999 | 2705 |
belaran@999 | 2706 <sect2> |
belaran@999 | 2707 <title>Les révisions 'heads'</title> |
belaran@999 | 2708 |
belaran@999 | 2709 <para id="x_341">Rappellez vous que Mercurial enregistre quelle révision |
belaran@999 | 2710 est le parent de chaque révision. Si une révision a un parent, nous |
belaran@999 | 2711 l'appelons un enfant(child) ou un descendant de ce parent. Une |
belaran@999 | 2712 "head" est une révision qui n'a donc pas d'enfant. La révision tip |
belaran@999 | 2713 est donc une "head", car c'est la révision la plus récente du dépôt |
belaran@999 | 2714 qui n'a pas d'enfant. Il y a des moments où un dépôt peut contenir |
belaran@999 | 2715 plusieurs "head".</para> |
belaran@999 | 2716 |
belaran@999 | 2717 <figure id="fig:tour-merge:pull" float="0"> |
belaran@999 | 2718 <title>Contenu du dépôt après une récupération ("pull") depuis le |
belaran@999 | 2719 dépôt <filename class="directory" moreinfo="none">my-hello</filename> vers le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename></title> |
belaran@999 | 2720 <mediaobject> |
belaran@999 | 2721 <imageobject> |
belaran@999 | 2722 <imagedata fileref="tour-merge-pull"/> |
belaran@999 | 2723 </imageobject> |
belaran@999 | 2724 <textobject><phrase>XXX ajoute un texte</phrase></textobject> |
belaran@999 | 2725 </mediaobject> |
belaran@999 | 2726 </figure> |
belaran@999 | 2727 |
belaran@999 | 2728 <para id="x_343">Dans la figure <xref linkend="fig:tour-merge:pull"/>, |
belaran@999 | 2729 vous pouvez constater l'effet d'un \textit{pull} depuis le dépôt |
belaran@999 | 2730 <filename class="directory" moreinfo="none">my-hello</filename> dans le dépôt |
belaran@999 | 2731 <filename class="directory" moreinfo="none">my-new-hello</filename>. L'historique qui |
belaran@999 | 2732 était déjà présent dans le dépôt <filename class="directory" moreinfo="none">my-new-hello</filename> reste intact, mais une |
belaran@999 | 2733 nouvelle révision a été ajoutée. En vous reportant à la figure <xref linkend="fig:tour-merge:sep-repos"/>, vous pouvez voir que le |
belaran@999 | 2734 <emphasis>ID de révision (changeset ID)</emphasis> reste le même dans |
belaran@999 | 2735 le nouveau dépôt, mais que le <emphasis>numéro de |
belaran@999 | 2736 révision</emphasis> reste le même. (Ceci est un parfait exemple de |
belaran@999 | 2737 pourquoi il n'est fiable d'utiliser les numéros de révision lorsque |
belaran@999 | 2738 l'on discute d'un \textit{changeset}.) Vous pouvez voir les "heads" |
belaran@999 | 2739 présentes dans le dépôt en utilisant la commande <command role="hg-cmd" moreinfo="none">hg heads</command>.</para> |
belaran@999 | 2740 |
belaran@999 | 2741 <!-- BEGIN tour.merge.heads --> |
belaran@999 | 2742 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> |
belaran@999 | 2743 changeset: 6:c94f208d1dfb |
belaran@999 | 2744 tag: tip |
belaran@999 | 2745 parent: 4:2278160e78d4 |
belaran@999 | 2746 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2747 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2748 summary: Added an extra line of output |
belaran@999 | 2749 |
belaran@999 | 2750 changeset: 5:5f06f94fbeca |
belaran@999 | 2751 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2752 date: Sun Aug 16 14:05:31 2009 +0000 |
belaran@999 | 2753 summary: A new hello for a new day. |
belaran@999 | 2754 |
belaran@999 | 2755 </screen> |
belaran@999 | 2756 <!-- END tour.merge.heads --> |
belaran@999 | 2757 |
belaran@999 | 2758 </sect2> |
belaran@999 | 2759 |
belaran@999 | 2760 <sect2> |
belaran@999 | 2761 <title>Effectuer la fusion</title> |
belaran@999 | 2762 |
belaran@999 | 2763 <para id="x_344">Que se passe-t-il quand vous essayez d'utiliser la |
belaran@999 | 2764 commande <command role="hg-cmd" moreinfo="none">hg update</command> pour mettre à |
belaran@999 | 2765 jour votre espace de travail au nouveau "tip"</para> |
belaran@999 | 2766 |
belaran@999 | 2767 <!-- BEGIN tour.merge.update --> |
belaran@999 | 2768 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput> |
belaran@999 | 2769 abort: crosses branches (use 'hg merge' or 'hg update -C') |
belaran@999 | 2770 </screen> |
belaran@999 | 2771 <!-- END tour.merge.update --> |
belaran@999 | 2772 |
belaran@999 | 2773 |
belaran@999 | 2774 |
belaran@999 | 2775 <para id="x_345">Mercurial nous prévient que la commande <command role="hg-cmd" moreinfo="none">hg update</command> n'effectuera pas |
belaran@999 | 2776 la fusion, il ne veut pas mettre à jour l'espace de travail quand il |
belaran@999 | 2777 estime que nous pourrions avoir besoin d'une fusion, à moins de lui |
belaran@999 | 2778 forcer la main. À la place, il faut utiliser la commande <command role="hg-cmd" moreinfo="none">hg merge</command> pour fusionner les deux |
belaran@999 | 2779 "heads".</para> |
belaran@999 | 2780 |
belaran@999 | 2781 <para id="x_723">Pour commencer une fusion (merge) entre deux "heads", |
belaran@999 | 2782 nous utilisons la commande <command role="hg-cmd" moreinfo="none">hg merge</command>.</para> |
belaran@999 | 2783 |
belaran@999 | 2784 <!-- BEGIN tour.merge.merge --> |
belaran@999 | 2785 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 2786 merging hello.c |
belaran@999 | 2787 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 2788 (branch merge, don't forget to commit) |
belaran@999 | 2789 </screen> |
belaran@999 | 2790 <!-- END tour.merge.merge --> |
belaran@999 | 2791 |
belaran@999 | 2792 |
belaran@999 | 2793 <para id="x_347">Nous résolvons les conflits dans le fichier |
belaran@999 | 2794 <filename moreinfo="none">hello.c</filename>. Ceci met à jour le répertoire de travail |
belaran@999 | 2795 de sorte qu'il ne contienne les modifications ne provenance des |
belaran@999 | 2796 <emphasis>deux</emphasis> "heads", ce qui est indiqué par la |
belaran@999 | 2797 la sortie de la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 2798 parents</command> et le contenu du fichier |
belaran@999 | 2799 <filename moreinfo="none">hello.c</filename>.</para> |
belaran@999 | 2800 |
belaran@999 | 2801 <!-- BEGIN tour.merge.parents --> |
belaran@999 | 2802 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 2803 changeset: 5:5f06f94fbeca |
belaran@999 | 2804 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2805 date: Sun Aug 16 14:05:31 2009 +0000 |
belaran@999 | 2806 summary: A new hello for a new day. |
belaran@999 | 2807 |
belaran@999 | 2808 changeset: 6:c94f208d1dfb |
belaran@999 | 2809 tag: tip |
belaran@999 | 2810 parent: 4:2278160e78d4 |
belaran@999 | 2811 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2812 date: Sun Aug 16 14:05:26 2009 +0000 |
belaran@999 | 2813 summary: Added an extra line of output |
belaran@999 | 2814 |
belaran@999 | 2815 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat hello.c</userinput> |
belaran@999 | 2816 /* |
belaran@999 | 2817 * Placed in the public domain by Bryan O'Sullivan. This program is |
belaran@999 | 2818 * not covered by patents in the United States or other countries. |
belaran@999 | 2819 */ |
belaran@999 | 2820 |
belaran@999 | 2821 #include <stdio.h> |
belaran@999 | 2822 |
belaran@999 | 2823 int main(int argc, char **argv) |
belaran@999 | 2824 { |
belaran@999 | 2825 printf("once more, hello.\n"); |
belaran@999 | 2826 printf("hello, world!\"); |
belaran@999 | 2827 printf("hello again!\n"); |
belaran@999 | 2828 return 0; |
belaran@999 | 2829 } |
belaran@999 | 2830 </screen> |
belaran@999 | 2831 <!-- END tour.merge.parents --> |
belaran@999 | 2832 |
belaran@999 | 2833 </sect2> |
belaran@999 | 2834 |
belaran@999 | 2835 <sect2> |
belaran@999 | 2836 <title>Effectuer l'ajout (commit) du résultat de la fusion</title> |
belaran@999 | 2837 |
belaran@999 | 2838 <para id="x_348">Dès l'instant où vous avez effectué une fusion |
belaran@999 | 2839 (merge), <command role="hg-cmd" moreinfo="none">hg parents</command> vous |
belaran@999 | 2840 affichera deux parents, avant que vous n'exécutiez la commande |
belaran@999 | 2841 <command role="hg-cmd" moreinfo="none">hg commit</command> sur le résultat de la |
belaran@999 | 2842 fusion.</para> |
belaran@999 | 2843 |
belaran@999 | 2844 <!-- BEGIN tour.merge.commit --> |
belaran@999 | 2845 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merged changes'</userinput> |
belaran@999 | 2846 </screen> |
belaran@999 | 2847 <!-- END tour.merge.commit --> |
belaran@999 | 2848 |
belaran@999 | 2849 |
belaran@999 | 2850 <para id="x_349">Nous avons maintenant un nouveau tip, remarquer qu'il |
belaran@999 | 2851 contient <emphasis>à la fois</emphasis> nos anciennes "heads" et leurs |
belaran@999 | 2852 parents. Ce sont les mêmes révisions que nous avions affichées avec |
belaran@999 | 2853 la commande <command role="hg-cmd" moreinfo="none">hg parents</command>.</para> |
belaran@999 | 2854 |
belaran@999 | 2855 <!-- BEGIN tour.merge.tip --> |
belaran@999 | 2856 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 2857 changeset: 7:b8e1e756ef55 |
belaran@999 | 2858 tag: tip |
belaran@999 | 2859 parent: 5:5f06f94fbeca |
belaran@999 | 2860 parent: 6:c94f208d1dfb |
belaran@999 | 2861 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 2862 date: Sun Aug 16 14:05:33 2009 +0000 |
belaran@999 | 2863 summary: Merged changes |
belaran@999 | 2864 |
belaran@999 | 2865 </screen> |
belaran@999 | 2866 <!-- END tour.merge.tip --> |
belaran@999 | 2867 |
belaran@999 | 2868 |
belaran@999 | 2869 <para id="x_34a">Dans la figure <xref linkend="fig:tour-merge:merge"/>, |
belaran@999 | 2870 vous pouvez voir une représentation de ce qui se passe dans l'espace |
belaran@999 | 2871 de travail pendant la fusion, et comment ceci affecte le dépôt lors |
belaran@999 | 2872 du "commit". Pendant la fusion, l'espace de travail, qui a deux |
belaran@999 | 2873 révisions (changesets) comme parents, voit ces derniers devenir le parent |
belaran@999 | 2874 d'une nouvelle révision (changeset).</para> |
belaran@999 | 2875 |
belaran@999 | 2876 <figure id="fig:tour-merge:merge" float="0"> |
belaran@999 | 2877 <title>Working directory and repository during merge, and |
belaran@999 | 2878 following commit</title> |
belaran@999 | 2879 <mediaobject> |
belaran@999 | 2880 <imageobject> |
belaran@999 | 2881 <imagedata fileref="figs/tour-merge-merge.png"/> |
belaran@999 | 2882 </imageobject> |
belaran@999 | 2883 <textobject><phrase>XXX ajoute texte</phrase></textobject> |
belaran@999 | 2884 </mediaobject> |
belaran@999 | 2885 </figure> |
belaran@999 | 2886 |
belaran@999 | 2887 </sect2> |
belaran@999 | 2888 </sect1> |
belaran@999 | 2889 |
belaran@999 | 2890 <sect1> |
belaran@999 | 2891 <title>Fusionner les modifications en conflit</title> |
belaran@999 | 2892 |
belaran@999 | 2893 <para id="x_34b">La plupart des fusions sont assez simple à réaliser, mais |
belaran@999 | 2894 parfois vous vous retrouverez à fusionner des fichiers où la modification |
belaran@999 | 2895 touche la même portion de code, au sein d'un même fichier. À moins |
belaran@999 | 2896 que ces modification ne soient identiques, ceci aboutira à un |
belaran@999 | 2897 <emphasis>conflit</emphasis>, et vous devrez décider comment réconcilier |
belaran@999 | 2898 les différentes modifications dans un tout cohérent.</para> |
belaran@999 | 2899 |
belaran@999 | 2900 <figure id="fig:tour-merge:conflict" float="0"> |
belaran@999 | 2901 <title>Modifications en conflits dans un document</title> |
belaran@999 | 2902 <mediaobject> |
belaran@999 | 2903 <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject> |
belaran@999 | 2904 <textobject><phrase>XXX ajoute texte</phrase></textobject> |
belaran@999 | 2905 </mediaobject> |
belaran@999 | 2906 </figure> |
belaran@999 | 2907 |
belaran@999 | 2908 <para id="x_34d">La figure <xref linkend="fig:tour-merge:conflict"/> |
belaran@999 | 2909 illustre un cas de modifications conflictuelles dans un document. Nous |
belaran@999 | 2910 avons commencé avec une version simple de ce fichier, puis nous avons |
belaran@999 | 2911 ajouté des modifications, pendant que quelqu'un d'autre modifiait le même |
belaran@999 | 2912 texte. Notre tâche dans la résolution du conflit est de décider à quoi le |
belaran@999 | 2913 fichier devrait ressembler.</para> |
belaran@999 | 2914 |
belaran@999 | 2915 <para id="x_34e">Mercurial n'a pas de mécanisme interne pour gérer |
belaran@999 | 2916 les conflits. À la place, il exécute un programme externe appelé |
belaran@999 | 2917 <command moreinfo="none">hgmerge</command>. Il s'agit d'un script shell qui est |
belaran@999 | 2918 embarqué par Mercurial, vous pouvez le modifier si vous le voulez. |
belaran@999 | 2919 Ce qu'il fait par défaut est d'essayer de trouver un des différents |
belaran@999 | 2920 outils de fusion qui seront probablement installés sur le système. |
belaran@999 | 2921 Il commence par les outils totalement automatiques, et si ils |
belaran@999 | 2922 échouent (parce que la résolution du conflit nécessite une |
belaran@999 | 2923 intervention humaine) ou si ils sont absents, le script tente |
belaran@999 | 2924 d'exécuter certains outils graphiques de fusion.</para> |
belaran@999 | 2925 |
belaran@999 | 2926 <para id="x_34f">Il est aussi possible de demander à Mercurial d'exécuter |
belaran@999 | 2927 un autre programme ou un autre script en définissant la variable |
belaran@999 | 2928 d'environnement <envar>HGMERGE</envar> avec le nom |
belaran@999 | 2929 du programme de votre choix.</para> |
belaran@999 | 2930 |
belaran@999 | 2931 <sect2> |
belaran@999 | 2932 <title>Utiliser un outil graphique de fusion</title> |
belaran@999 | 2933 |
belaran@999 | 2934 <para id="x_350">Mon outil de fusion préféré est |
belaran@999 | 2935 <command moreinfo="none">kdiff3</command>, que j'utilise ici pour illustrer les |
belaran@999 | 2936 fonctionnalités classiques des outils graphiques de fusion. Vous pouvez |
belaran@999 | 2937 voir une capture d'écran de l'utilisation de <command moreinfo="none">kdiff3</command> |
belaran@999 | 2938 dans la figure <xref linkend="fig:tour-merge:kdiff3"/>. Cet outil |
belaran@999 | 2939 effectue une <emphasis>fusion \textit{three-way</emphasis>}, car il y a |
belaran@999 | 2940 trois différentes versions du fichier qui nous intéresse. Le fichier |
belaran@999 | 2941 découpe la partie supérieure de la fenêtre en trois panneaux:</para> |
belaran@999 | 2942 <itemizedlist> |
belaran@999 | 2943 <listitem><para id="x_351">A gauche on la version de |
belaran@999 | 2944 <emphasis>base</emphasis> du fichier, soit la plus récente version |
belaran@999 | 2945 des deux versions qu'on souhaite fusionner.</para></listitem> |
belaran@999 | 2946 <listitem><para id="x_352">Au centre, il y a <quote>notre</quote> |
belaran@999 | 2947 version du fichier, avec le contenu que nous avons modifié.</para></listitem> |
belaran@999 | 2948 <listitem><para id="x_353">Sur la droite, on trouve |
belaran@999 | 2949 <quote>leur</quote> version du fichier, celui qui contient la |
belaran@999 | 2950 révision que nous souhaitons intégré.</para> |
belaran@999 | 2951 </listitem></itemizedlist> |
belaran@999 | 2952 <para id="x_354">Dans le panneau en dessous, on trouve le |
belaran@999 | 2953 <emphasis>résultat</emphasis> actuel de notre fusion. Notre tâche |
belaran@999 | 2954 consiste donc à remplacement tous les textes en rouges, |
belaran@999 | 2955 qui indiquent des conflits non résolus, avec une fusion manuelle et |
belaran@999 | 2956 pertinente de <quote>notre</quote> version et de la <quote>leur</quote>. |
belaran@999 | 2957 </para> |
belaran@999 | 2958 |
belaran@999 | 2959 <para id="x_355">Tous les quatre panneaux sont <emphasis>accrochés ensemble</emphasis>, |
belaran@999 | 2960 si nous déroulons les ascenseurs verticalement ou horizontalement dans chacun |
belaran@999 | 2961 d'entre eux, les autres sont mis à jour avec la section correspondante dans leurs |
belaran@999 | 2962 fichiers respectifs.</para> |
belaran@999 | 2963 |
belaran@999 | 2964 <figure id="fig:tour-merge:kdiff3" float="0"> |
belaran@999 | 2965 <title>Utiliser <command moreinfo="none">kdiff3</command> pour fusionner les |
belaran@999 | 2966 différentes version d'un fichier.</title> |
belaran@999 | 2967 <mediaobject> |
belaran@999 | 2968 <imageobject> |
belaran@999 | 2969 <imagedata width="100%" fileref="figs/kdiff3.png"/></imageobject> |
belaran@999 | 2970 <textobject> |
belaran@999 | 2971 <phrase>XXX ajoute texte</phrase> |
belaran@999 | 2972 </textobject> |
belaran@999 | 2973 </mediaobject> |
belaran@999 | 2974 </figure> |
belaran@999 | 2975 |
belaran@999 | 2976 <para id="x_357">Pour chaque portion de fichier posant problème, nous |
belaran@999 | 2977 pouvons choisir de résoudre le conflit en utilisant une combinaison de |
belaran@999 | 2978 texte depuis la version de base, la notre, ou la leur. Nous pouvons |
belaran@999 | 2979 aussi éditer manuellement les fichiers à tout moment, si c'est nécessaire.</para> |
belaran@999 | 2980 |
belaran@999 | 2981 <para id="x_358">Il y a <emphasis>beaucoup</emphasis> d'outils de |
belaran@999 | 2982 fusion disponibles, bien trop pour en parler de tous ici. Leurs |
belaran@999 | 2983 disponibilités varient selon les plate formes ainsi que leurs |
belaran@999 | 2984 avantages et inconvénients. La plupart sont optimisé pour |
belaran@999 | 2985 la fusion de fichier contenant un texte plat, certains sont spécialisé |
belaran@999 | 2986 dans un format de fichier précis (généralement XML).</para> |
belaran@999 | 2987 </sect2> |
belaran@999 | 2988 |
belaran@999 | 2989 <sect2> |
belaran@999 | 2990 <title>Un exemple concret</title> |
belaran@999 | 2991 |
belaran@999 | 2992 <para id="x_359">Dans cet exemple, nous allons reproduire la |
belaran@999 | 2993 modification de l'historique du fichier de la figure <xref linkend="fig:tour-merge:conflict"/> ci dessus. Commençons par créer |
belaran@999 | 2994 un dépôt avec une version de base de notre document.</para> |
belaran@999 | 2995 |
belaran@999 | 2996 <!-- BEGIN tour-merge-conflict.wife --> |
belaran@999 | 2997 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> |
belaran@999 | 2998 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> |
belaran@999 | 2999 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Mariam Abacha, the wife of former</userinput> |
belaran@999 | 3000 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> |
belaran@999 | 3001 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> |
belaran@999 | 3002 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add letter.txt</userinput> |
belaran@999 | 3003 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, first draft'</userinput> |
belaran@999 | 3004 </screen> |
belaran@999 | 3005 <!-- END tour-merge-conflict.wife --> |
belaran@999 | 3006 |
belaran@999 | 3007 |
belaran@999 | 3008 <para id="x_35a">Créons un clone de ce dépôt et faisons une |
belaran@999 | 3009 modification dans le fichier.</para> |
belaran@999 | 3010 |
belaran@999 | 3011 <!-- BEGIN tour-merge-conflict.cousin --> |
belaran@999 | 3012 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 3013 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-cousin</userinput> |
belaran@999 | 3014 updating working directory |
belaran@999 | 3015 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 3016 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-cousin</userinput> |
belaran@999 | 3017 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> |
belaran@999 | 3018 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> |
belaran@999 | 3019 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Shehu Musa Abacha, cousin to the former</userinput> |
belaran@999 | 3020 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> |
belaran@999 | 3021 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> |
belaran@999 | 3022 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with cousin'</userinput> |
belaran@999 | 3023 </screen> |
belaran@999 | 3024 <!-- END tour-merge-conflict.cousin --> |
belaran@999 | 3025 |
belaran@999 | 3026 |
belaran@999 | 3027 <para id="x_35b">Et un autre clone, pour simuler que quelqu'un d'autre effectue une |
belaran@999 | 3028 modification sur le fichier. (Ceci pour suggérer qu'il n'est pas rare |
belaran@999 | 3029 de devoir effectuer des fusions (merges) avec vos propres travaux quand |
belaran@999 | 3030 vous isolez les tâches dans des dépôts distincts. En effet, vous |
belaran@999 | 3031 aurez alors à trouver et résoudre certains conflits).</para> |
belaran@999 | 3032 |
belaran@999 | 3033 <!-- BEGIN tour-merge-conflict.son --> |
belaran@999 | 3034 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 3035 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam scam-son</userinput> |
belaran@999 | 3036 updating working directory |
belaran@999 | 3037 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 3038 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-son</userinput> |
belaran@999 | 3039 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> |
belaran@999 | 3040 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> |
belaran@999 | 3041 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Alhaji Abba Abacha, son of the former</userinput> |
belaran@999 | 3042 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> |
belaran@999 | 3043 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> |
belaran@999 | 3044 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m '419 scam, with son'</userinput> |
belaran@999 | 3045 </screen> |
belaran@999 | 3046 <!-- END tour-merge-conflict.son --> |
belaran@999 | 3047 |
belaran@999 | 3048 |
belaran@999 | 3049 <para id="x_35c">Maintenant que ces deux versions différentes du même fichier sont |
belaran@999 | 3050 créées, nous allons configurer l'environnement de manière appropriée pour |
belaran@999 | 3051 exécuter notre fusion (merge).</para> |
belaran@999 | 3052 |
belaran@999 | 3053 <!-- BEGIN tour-merge-conflict.pull --> |
belaran@999 | 3054 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 3055 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone scam-cousin scam-merge</userinput> |
belaran@999 | 3056 updating working directory |
belaran@999 | 3057 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 3058 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd scam-merge</userinput> |
belaran@999 | 3059 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../scam-son</userinput> |
belaran@999 | 3060 pulling from ../scam-son |
belaran@999 | 3061 searching for changes |
belaran@999 | 3062 adding changesets |
belaran@999 | 3063 adding manifests |
belaran@999 | 3064 adding file changes |
belaran@999 | 3065 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 3066 not updating, since new heads added |
belaran@999 | 3067 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 3068 </screen> |
belaran@999 | 3069 <!-- END tour-merge-conflict.pull --> |
belaran@999 | 3070 |
belaran@999 | 3071 |
belaran@999 | 3072 <para id="x_35d">Dans cette exemple, je n'utiliserais pas la commande Mercurial |
belaran@999 | 3073 habituelle <command moreinfo="none">hgmerge</command> pour effectuer le |
belaran@999 | 3074 fusion (merge), car il me faudrait abandonner ce joli petit exemple automatisé |
belaran@999 | 3075 pour utiliser un outil graphique. À la place, je vais définir la |
belaran@999 | 3076 variable d'environnement <envar>HGMERGE</envar> pour indiquer à |
belaran@999 | 3077 Mercurial d'utiliser la commande non-interactive <command moreinfo="none">merge</command>. |
belaran@999 | 3078 Cette dernière est embarquée par de nombreux systèmes <quote>à la Unix</quote>. |
belaran@999 | 3079 Si vous exécutez cet exemple depuis votre ordinateur, ne vous |
belaran@999 | 3080 occupez pas de définir <envar>HGMERGE</envar>.</para> |
belaran@999 | 3081 |
belaran@999 | 3082 <!-- BEGIN tour-merge-conflict.merge --> |
belaran@999 | 3083 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=merge</userinput> |
belaran@999 | 3084 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 3085 merging letter.txt |
belaran@999 | 3086 merge: warning: conflicts during merge |
belaran@999 | 3087 merging letter.txt failed! |
belaran@999 | 3088 0 files updated, 0 files merged, 0 files removed, 1 files unresolved |
belaran@999 | 3089 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon |
belaran@999 | 3090 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat letter.txt</userinput> |
belaran@999 | 3091 Greetings! |
belaran@999 | 3092 <<<<<<< /tmp/tour-merge-conflictk3twLJ/scam-merge/letter.txt |
belaran@999 | 3093 I am Shehu Musa Abacha, cousin to the former |
belaran@999 | 3094 ======= |
belaran@999 | 3095 I am Alhaji Abba Abacha, son of the former |
belaran@999 | 3096 >>>>>>> /tmp/letter.txt~other.4O623C |
belaran@999 | 3097 Nigerian dictator Sani Abacha. |
belaran@999 | 3098 </screen> |
belaran@999 | 3099 <!-- END tour-merge-conflict.merge --> |
belaran@999 | 3100 |
belaran@999 | 3101 |
belaran@999 | 3102 |
belaran@999 | 3103 <para id="x_35f">Parce que <command moreinfo="none">merge</command> ne peut pas résoudre |
belaran@999 | 3104 les modifications conflictuelles, il laisse des <emphasis>marqueurs de |
belaran@999 | 3105 différences</emphasis> à l'intérieur du fichier qui a des conflits, |
belaran@999 | 3106 indiquant clairement quelles lignes sont en conflits, et si elles |
belaran@999 | 3107 viennent de notre fichier ou du fichier externe. |
belaran@999 | 3108 </para> |
belaran@999 | 3109 |
belaran@999 | 3110 <para id="x_360">Mercurial peut distinguer, à la manière dont la |
belaran@999 | 3111 commande <command moreinfo="none">merge</command> se termine, qu'elle n'a pas été |
belaran@999 | 3112 capable d'effectuer la fusion (merge), alors il nous indique que nous |
belaran@999 | 3113 devons effectuer de nouveau cette opération. Ceci peut être très utile |
belaran@999 | 3114 si, par exemple, nous exécutons un outil graphique de fusion et que |
belaran@999 | 3115 nous le quittons sans nous rendre compte qu'il reste des conflits ou |
belaran@999 | 3116 simplement par erreur.</para> |
belaran@999 | 3117 |
belaran@999 | 3118 <para id="x_361">Si la fusion (merge) automatique ou manuelle échoue, |
belaran@999 | 3119 il n'y a rien pour nous empêcher de <quote>corriger le tir</quote> en |
belaran@999 | 3120 modifiant nous même les fichiers, et enfin effectuer le "commit" du |
belaran@999 | 3121 fichier:</para> |
belaran@999 | 3122 |
belaran@999 | 3123 <!-- BEGIN tour-merge-conflict.commit --> |
belaran@999 | 3124 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > letter.txt <<EOF</userinput> |
belaran@999 | 3125 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Greetings!</userinput> |
belaran@999 | 3126 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">I am Bryan O'Sullivan, no relation of the former</userinput> |
belaran@999 | 3127 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">Nigerian dictator Sani Abacha.</userinput> |
belaran@999 | 3128 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> |
belaran@999 | 3129 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -m letter.txt</userinput> |
belaran@999 | 3130 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Send me your money'</userinput> |
belaran@999 | 3131 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 3132 changeset: 3:0954bda76c6b |
belaran@999 | 3133 tag: tip |
belaran@999 | 3134 parent: 1:1ac156b6e708 |
belaran@999 | 3135 parent: 2:7ee20631b33b |
belaran@999 | 3136 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 3137 date: Sun Aug 16 14:05:34 2009 +0000 |
belaran@999 | 3138 summary: Send me your money |
belaran@999 | 3139 |
belaran@999 | 3140 </screen> |
belaran@999 | 3141 <!-- END tour-merge-conflict.commit --> |
belaran@999 | 3142 |
belaran@999 | 3143 |
belaran@999 | 3144 <note> |
belaran@999 | 3145 <title>Où est la <command moreinfo="none">hg resolve</command> ?</title> |
belaran@999 | 3146 |
belaran@999 | 3147 <para id="x_724">La commande <command moreinfo="none">hg resolve</command> a été |
belaran@999 | 3148 introduit dans la version 1.1 de Mercurial, qui a été publié en |
belaran@999 | 3149 décembre 2008. Si vous utilisez une version plus anciennne de |
belaran@999 | 3150 Mercurial (exécutez la command <command moreinfo="none">hg version</command> pour en |
belaran@999 | 3151 avoir le coeur net), cette commande ne sera pas disponible. Si votre |
belaran@999 | 3152 version de Mercurial est plus ancienne que la 1.1, vous devriez très |
belaran@999 | 3153 fortement considérer une mise à jour à une version plus récente avant |
belaran@999 | 3154 d'essayer de régler des fusions complexes.</para> |
belaran@999 | 3155 </note> |
belaran@999 | 3156 </sect2> |
belaran@999 | 3157 </sect1> |
belaran@999 | 3158 |
belaran@999 | 3159 <sect1 id="sec:tour-merge:fetch"> |
belaran@999 | 3160 <title>Simplification de la séquence pull-merge-commit</title> |
belaran@999 | 3161 |
belaran@999 | 3162 <para id="x_362">La procédure pour effectuer la fusion indiquée |
belaran@999 | 3163 ci-dessus est simple, mais requiert le lancement de trois commandes à la |
belaran@999 | 3164 suite.</para> |
belaran@999 | 3165 |
belaran@999 | 3166 <programlisting format="linespecific">hg pull -u |
belaran@999 | 3167 hg merge |
belaran@999 | 3168 hg commit -m 'Merged remote changes'</programlisting> |
belaran@999 | 3169 |
belaran@999 | 3170 <para id="x_363">Lors du "commit" final, vous devez également saisir un |
belaran@999 | 3171 message, qui aura vraisemblablement assez peu d'intérêt.</para> |
belaran@999 | 3172 |
belaran@999 | 3173 <para id="x_364">Il serait assez sympathique de pouvoir réduire le |
belaran@999 | 3174 nombre d'opérations nécessaire, si possible. De fait Mercurial est |
belaran@999 | 3175 fourni avec une extension appelé <literal role="hg-ext" moreinfo="none">fetch</literal> |
belaran@999 | 3176 qui fait justement cela.</para> |
belaran@999 | 3177 |
belaran@999 | 3178 <para id="x_365">Mercurial fourni un mécanisme d'extension flexible qui permet à chacun |
belaran@999 | 3179 d'étendre ces fonctionnalités, tout en conservant le cœur de Mercurial |
belaran@999 | 3180 léger et facile à utiliser. Certains extensions ajoutent de nouvelles |
belaran@999 | 3181 commandes que vous pouvez utiliser en ligne de commande, alors que |
belaran@999 | 3182 d'autres travaillent <quote>en coulisse,</quote> par exemple en ajoutant des |
belaran@999 | 3183 possibilités au serveur.</para> |
belaran@999 | 3184 |
belaran@999 | 3185 <para id="x_366">L'extension <literal role="hg-ext" moreinfo="none">fetch</literal> |
belaran@999 | 3186 ajoute une nouvelle commande nommée, sans surprise, <command role="hg-cmd" moreinfo="none">hg fetch</command>. Cette extension résulte en une |
belaran@999 | 3187 combinaison de <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg update</command> and <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3188 merge</command>. Elle commence par récupérer les modifications d'un |
belaran@999 | 3189 autre dépôt dans le dépôt courant. Si elle trouve que les |
belaran@999 | 3190 modifications ajoutent une nouvelle "head", elle effectue un "merge", |
belaran@999 | 3191 et ensuite "commit" le résultat du "merge" avec un message généré |
belaran@999 | 3192 automatiquement. Si aucune "head" n'ont été ajouté, elle met à jour le |
belaran@999 | 3193 répertoire de travail au niveau de la nouvelle révision tip.</para> |
belaran@999 | 3194 |
belaran@999 | 3195 <para id="x_367">Activer l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> est facile. Modifiez votre <filename role="special" moreinfo="none">.hgrc</filename>, et soit allez à la section <literal role="rc-extensions" moreinfo="none">extensions</literal> soit créer une section |
belaran@999 | 3196 <literal role="rc-extensions" moreinfo="none">extensions</literal>. Ensuite ajoutez |
belaran@999 | 3197 une ligne qui consiste simplement en <quote>\Verb+fetch =</quote>.</para> |
belaran@999 | 3198 |
belaran@999 | 3199 <programlisting format="linespecific">[extensions] |
belaran@999 | 3200 fetch =</programlisting> |
belaran@999 | 3201 |
belaran@999 | 3202 <para id="x_368">(Normalement, sur la partie droite de |
belaran@999 | 3203 <quote><literal moreinfo="none">=</literal></quote> devrait apparaître le chemin de |
belaran@999 | 3204 l'extension, mais étant donné que l'extension <literal role="hg-ext" moreinfo="none">fetch</literal> fait partie de la distribution standard, |
belaran@999 | 3205 Mercurial sait où la trouver.) </para> |
belaran@999 | 3206 |
belaran@999 | 3207 </sect1> |
belaran@999 | 3208 |
belaran@999 | 3209 <sect1> |
belaran@999 | 3210 <title>Renommer, copier, et fusionner (merge)</title> |
belaran@999 | 3211 |
belaran@999 | 3212 <para id="x_729">En cours de la vie d'un projet, nous allons souvent |
belaran@999 | 3213 vouloir changer la disposition de ses fichiers et de ses répertoires. |
belaran@999 | 3214 Ceci peut être aussi simple que de changer le nom d'un seul fichier, |
belaran@999 | 3215 et aussi compliqué que de restructurer une hiérarchie entiere de fichier |
belaran@999 | 3216 au sein du projet.</para> |
belaran@999 | 3217 |
belaran@999 | 3218 <para id="x_72a">Mercurial permet de faire ce genre de modification de |
belaran@999 | 3219 manière fluide, à condition de l'informer de ce que nous faisons. Si |
belaran@999 | 3220 vous voulez renommenr un ficher, vous devriez utiliser les commande |
belaran@999 | 3221 <command moreinfo="none">hg rename</command><footnote> |
belaran@999 | 3222 <para id="x_72b">Si vous un utilisateur de Unix, vous serez content |
belaran@999 | 3223 de savoir que la commande <command moreinfo="none">hg rename</command> command |
belaran@999 | 3224 peut être abrégée en <command moreinfo="none">hg mv</command>.</para> |
belaran@999 | 3225 </footnote> pour changer son nom, ainsi Mercurial peut ensuite prendre |
belaran@999 | 3226 la bonne décision, plus tard, en cas de fusionv (merge).</para> |
belaran@999 | 3227 |
belaran@999 | 3228 <para id="x_72c">Nous étudierojns en détail l'utilisation de ces commandes, |
belaran@999 | 3229 en détail, dans le chapitre <xref linkend="chap:daily.copy"/>.</para> |
belaran@999 | 3230 </sect1> |
belaran@999 | 3231 </chapter> |
belaran@999 | 3232 |
belaran@999 | 3233 <!-- |
belaran@999 | 3234 local variables: |
belaran@999 | 3235 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 3236 end: |
belaran@999 | 3237 --> |
belaran@999 | 3238 |
belaran@999 | 3239 <!-- BEGIN ch04 --> |
belaran@999 | 3240 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 3241 |
belaran@999 | 3242 <chapter id="chap:concepts"> |
belaran@999 | 3243 <?dbhtml filename="behind-the-scenes.html"?> |
belaran@999 | 3244 <title>Derrière le décor</title> |
belaran@999 | 3245 |
belaran@999 | 3246 <para id="x_2e8">À la différence de beaucoup d'outils de gestion de versions, |
belaran@999 | 3247 les concepts sur lesquels se base Mercurial sont assez simples pour |
belaran@999 | 3248 qu'il soit facile de comprendre comment le logiciel fonctionne. |
belaran@999 | 3249 Bien que leur connaissance ne soit pas nécéssaire, je trouve utile |
belaran@999 | 3250 d'avoir un <quote>modèle mental</quote> de ce qui se passe.</para> |
belaran@999 | 3251 |
belaran@999 | 3252 <para id="x_2e9">En effet, cette compréhension m'apporte la confiance que |
belaran@999 | 3253 Mercurial a été développé avec soin pour être à la fois |
belaran@999 | 3254 <emphasis>sûr</emphasis> et <emphasis>efficace</emphasis>. De surcroît, |
belaran@999 | 3255 si il m'est facile de garder en tête ce que le logiciel fait lorsque |
belaran@999 | 3256 j'accompli des tâches de révision, j'aurai moins de risques d'être |
belaran@999 | 3257 surpris par son comportement.</para> |
belaran@999 | 3258 |
belaran@999 | 3259 <para id="x_2ea">Dans ce chapitre, nous décrirons tout d'abord les concepts |
belaran@999 | 3260 essentiels de l'architecture de Mercurial, pour ensuite discuter quelques |
belaran@999 | 3261 uns des détails intéressants de son implémentation.</para> |
belaran@999 | 3262 |
belaran@999 | 3263 <sect1> |
belaran@999 | 3264 <title>Conservation de l'historique sous Mercurial</title> |
belaran@999 | 3265 <sect2> |
belaran@999 | 3266 <title>Suivi de l'historique pour un seul fichier</title> |
belaran@999 | 3267 |
belaran@999 | 3268 <para id="x_2eb">Lorsque Mercurial effectue un suivi des modifications |
belaran@999 | 3269 faites à un fichier, il conserve l'historique pour ce fichier dans un |
belaran@999 | 3270 <emphasis>filelog</emphasis> sous forme de métadonnées. Chaque entrée |
belaran@999 | 3271 dans le filelog contient assez d'informations pour reconstituer une |
belaran@999 | 3272 révision du fichier correspondant. Les filelogs sont des fichiers |
belaran@999 | 3273 stockés dans le répertoire <filename role="special" class="directory" moreinfo="none">.hg/store/data</filename>. Un filelog contient |
belaran@999 | 3274 des informations de deux types: les données de révision, et un index |
belaran@999 | 3275 pour permettre à Mercurial une recherche efficace d'une révision |
belaran@999 | 3276 donnée.</para> |
belaran@999 | 3277 |
belaran@999 | 3278 <para id="x_2ec">Lorsqu'un fichier devient trop gros ou a un long |
belaran@999 | 3279 historique, son filelog se voit stocker dans un fichier de données |
belaran@999 | 3280 (avec un suffixe <quote><literal moreinfo="none">.d</literal></quote>) et un fichier |
belaran@999 | 3281 index (avec un suffixe<quote><literal moreinfo="none">.i</literal></quote>) |
belaran@999 | 3282 distincts. La relation entre un fichier dans le répertoire de travail |
belaran@999 | 3283 et le filelog couvrant le suivi de son historique dans le dépôt est |
belaran@999 | 3284 illustré à la figure <xref linkend="fig:concepts:filelog"/>.</para> |
belaran@999 | 3285 |
belaran@999 | 3286 <figure id="fig:concepts:filelog" float="0"> |
belaran@999 | 3287 <title>Relations entre les fichiers dans le répertoire de travail et |
belaran@999 | 3288 leurs filelogs dans le dépôt</title> |
belaran@999 | 3289 <mediaobject> <imageobject><imagedata fileref="figs/filelog.png"/></imageobject> |
belaran@999 | 3290 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3291 </mediaobject> </figure> |
belaran@999 | 3292 |
belaran@999 | 3293 </sect2> |
belaran@999 | 3294 <sect2> |
belaran@999 | 3295 <title>Gestion des fichiers suivis</title> |
belaran@999 | 3296 |
belaran@999 | 3297 <para id="x_2ee">Mercurial a recours à une structure nommée |
belaran@999 | 3298 <emphasis>manifest</emphasis> pour rassembler les informations sur |
belaran@999 | 3299 les fichiers dont il gère le suivi. Chaque entrée dans ce manifest |
belaran@999 | 3300 contient des informations sur les fichiers présents dans une révision |
belaran@999 | 3301 donnée. Une entrée store la liste des fichiers faisant partie de la |
belaran@999 | 3302 révision, la version de chaque fichier, et quelques autres |
belaran@999 | 3303 métadonnées sur ces fichiers.</para> |
belaran@999 | 3304 |
belaran@999 | 3305 </sect2> |
belaran@999 | 3306 <sect2> |
belaran@999 | 3307 <title>Recording changeset information</title> |
belaran@999 | 3308 |
belaran@999 | 3309 <para id="x_2ef">The <emphasis>changelog</emphasis> contains |
belaran@999 | 3310 information about each changeset. Each revision records who |
belaran@999 | 3311 committed a change, the changeset comment, other pieces of |
belaran@999 | 3312 changeset-related information, and the revision of the manifest to |
belaran@999 | 3313 use.</para> |
belaran@999 | 3314 |
belaran@999 | 3315 </sect2> |
belaran@999 | 3316 <sect2> |
belaran@999 | 3317 <title>Relationships between revisions</title> |
belaran@999 | 3318 |
belaran@999 | 3319 <para id="x_2f0">Within a changelog, a manifest, or a filelog, each |
belaran@999 | 3320 revision stores a pointer to its immediate parent (or to its |
belaran@999 | 3321 two parents, if it's a merge revision). As I mentioned above, |
belaran@999 | 3322 there are also relationships between revisions |
belaran@999 | 3323 <emphasis>across</emphasis> these structures, and they are |
belaran@999 | 3324 hierarchical in nature.</para> |
belaran@999 | 3325 |
belaran@999 | 3326 <para id="x_2f1">For every changeset in a repository, there is exactly one |
belaran@999 | 3327 revision stored in the changelog. Each revision of the |
belaran@999 | 3328 changelog contains a pointer to a single revision of the |
belaran@999 | 3329 manifest. A revision of the manifest stores a pointer to a |
belaran@999 | 3330 single revision of each filelog tracked when that changeset |
belaran@999 | 3331 was created. These relationships are illustrated in |
belaran@999 | 3332 <xref linkend="fig:concepts:metadata"/>.</para> |
belaran@999 | 3333 |
belaran@999 | 3334 <figure id="fig:concepts:metadata" float="0"> |
belaran@999 | 3335 <title>Metadata relationships</title> |
belaran@999 | 3336 <mediaobject> |
belaran@999 | 3337 <imageobject><imagedata fileref="figs/metadata.png"/></imageobject> |
belaran@999 | 3338 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3339 </mediaobject> |
belaran@999 | 3340 </figure> |
belaran@999 | 3341 |
belaran@999 | 3342 <para id="x_2f3">As the illustration shows, there is |
belaran@999 | 3343 <emphasis>not</emphasis> a <quote>one to one</quote> |
belaran@999 | 3344 relationship between revisions in the changelog, manifest, or |
belaran@999 | 3345 filelog. If a file that |
belaran@999 | 3346 Mercurial tracks hasn't changed between two changesets, the |
belaran@999 | 3347 entry for that file in the two revisions of the manifest will |
belaran@999 | 3348 point to the same revision of its filelog<footnote> |
belaran@999 | 3349 <para id="x_725">It is possible (though unusual) for the manifest to |
belaran@999 | 3350 remain the same between two changesets, in which case the |
belaran@999 | 3351 changelog entries for those changesets will point to the |
belaran@999 | 3352 same revision of the manifest.</para> |
belaran@999 | 3353 </footnote>.</para> |
belaran@999 | 3354 |
belaran@999 | 3355 </sect2> |
belaran@999 | 3356 </sect1> |
belaran@999 | 3357 <sect1> |
belaran@999 | 3358 <title>Safe, efficient storage</title> |
belaran@999 | 3359 |
belaran@999 | 3360 <para id="x_2f4">The underpinnings of changelogs, manifests, and filelogs are |
belaran@999 | 3361 provided by a single structure called the |
belaran@999 | 3362 <emphasis>revlog</emphasis>.</para> |
belaran@999 | 3363 |
belaran@999 | 3364 <sect2> |
belaran@999 | 3365 <title>Efficient storage</title> |
belaran@999 | 3366 |
belaran@999 | 3367 <para id="x_2f5">The revlog provides efficient storage of revisions using a |
belaran@999 | 3368 <emphasis>delta</emphasis> mechanism. Instead of storing a |
belaran@999 | 3369 complete copy of a file for each revision, it stores the |
belaran@999 | 3370 changes needed to transform an older revision into the new |
belaran@999 | 3371 revision. For many kinds of file data, these deltas are |
belaran@999 | 3372 typically a fraction of a percent of the size of a full copy |
belaran@999 | 3373 of a file.</para> |
belaran@999 | 3374 |
belaran@999 | 3375 <para id="x_2f6">Some obsolete revision control systems can only work with |
belaran@999 | 3376 deltas of text files. They must either store binary files as |
belaran@999 | 3377 complete snapshots or encoded into a text representation, both |
belaran@999 | 3378 of which are wasteful approaches. Mercurial can efficiently |
belaran@999 | 3379 handle deltas of files with arbitrary binary contents; it |
belaran@999 | 3380 doesn't need to treat text as special.</para> |
belaran@999 | 3381 |
belaran@999 | 3382 </sect2> |
belaran@999 | 3383 <sect2 id="sec:concepts:txn"> |
belaran@999 | 3384 <title>Safe operation</title> |
belaran@999 | 3385 |
belaran@999 | 3386 <para id="x_2f7">Mercurial only ever <emphasis>appends</emphasis> data to |
belaran@999 | 3387 the end of a revlog file. It never modifies a section of a |
belaran@999 | 3388 file after it has written it. This is both more robust and |
belaran@999 | 3389 efficient than schemes that need to modify or rewrite |
belaran@999 | 3390 data.</para> |
belaran@999 | 3391 |
belaran@999 | 3392 <para id="x_2f8">In addition, Mercurial treats every write as part of a |
belaran@999 | 3393 <emphasis>transaction</emphasis> that can span a number of |
belaran@999 | 3394 files. A transaction is <emphasis>atomic</emphasis>: either |
belaran@999 | 3395 the entire transaction succeeds and its effects are all |
belaran@999 | 3396 visible to readers in one go, or the whole thing is undone. |
belaran@999 | 3397 This guarantee of atomicity means that if you're running two |
belaran@999 | 3398 copies of Mercurial, where one is reading data and one is |
belaran@999 | 3399 writing it, the reader will never see a partially written |
belaran@999 | 3400 result that might confuse it.</para> |
belaran@999 | 3401 |
belaran@999 | 3402 <para id="x_2f9">The fact that Mercurial only appends to files makes it |
belaran@999 | 3403 easier to provide this transactional guarantee. The easier it |
belaran@999 | 3404 is to do stuff like this, the more confident you should be |
belaran@999 | 3405 that it's done correctly.</para> |
belaran@999 | 3406 |
belaran@999 | 3407 </sect2> |
belaran@999 | 3408 <sect2> |
belaran@999 | 3409 <title>Fast retrieval</title> |
belaran@999 | 3410 |
belaran@999 | 3411 <para id="x_2fa">Mercurial cleverly avoids a pitfall common to |
belaran@999 | 3412 all earlier revision control systems: the problem of |
belaran@999 | 3413 <emphasis>inefficient retrieval</emphasis>. Most revision |
belaran@999 | 3414 control systems store the contents of a revision as an |
belaran@999 | 3415 incremental series of modifications against a |
belaran@999 | 3416 <quote>snapshot</quote>. (Some base the snapshot on the |
belaran@999 | 3417 oldest revision, others on the newest.) To reconstruct a |
belaran@999 | 3418 specific revision, you must first read the snapshot, and then |
belaran@999 | 3419 every one of the revisions between the snapshot and your |
belaran@999 | 3420 target revision. The more history that a file accumulates, |
belaran@999 | 3421 the more revisions you must read, hence the longer it takes to |
belaran@999 | 3422 reconstruct a particular revision.</para> |
belaran@999 | 3423 |
belaran@999 | 3424 <figure id="fig:concepts:snapshot" float="0"> |
belaran@999 | 3425 <title>Snapshot of a revlog, with incremental deltas</title> |
belaran@999 | 3426 <mediaobject> |
belaran@999 | 3427 <imageobject><imagedata fileref="figs/snapshot.png"/></imageobject> |
belaran@999 | 3428 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3429 </mediaobject> |
belaran@999 | 3430 </figure> |
belaran@999 | 3431 |
belaran@999 | 3432 <para id="x_2fc">The innovation that Mercurial applies to this problem is |
belaran@999 | 3433 simple but effective. Once the cumulative amount of delta |
belaran@999 | 3434 information stored since the last snapshot exceeds a fixed |
belaran@999 | 3435 threshold, it stores a new snapshot (compressed, of course), |
belaran@999 | 3436 instead of another delta. This makes it possible to |
belaran@999 | 3437 reconstruct <emphasis>any</emphasis> revision of a file |
belaran@999 | 3438 quickly. This approach works so well that it has since been |
belaran@999 | 3439 copied by several other revision control systems.</para> |
belaran@999 | 3440 |
belaran@999 | 3441 <para id="x_2fd"><xref linkend="fig:concepts:snapshot"/> illustrates |
belaran@999 | 3442 the idea. In an entry in a revlog's index file, Mercurial |
belaran@999 | 3443 stores the range of entries from the data file that it must |
belaran@999 | 3444 read to reconstruct a particular revision.</para> |
belaran@999 | 3445 |
belaran@999 | 3446 <sect3> |
belaran@999 | 3447 <title>Aside: the influence of video compression</title> |
belaran@999 | 3448 |
belaran@999 | 3449 <para id="x_2fe">If you're familiar with video compression or |
belaran@999 | 3450 have ever watched a TV feed through a digital cable or |
belaran@999 | 3451 satellite service, you may know that most video compression |
belaran@999 | 3452 schemes store each frame of video as a delta against its |
belaran@999 | 3453 predecessor frame.</para> |
belaran@999 | 3454 |
belaran@999 | 3455 <para id="x_2ff">Mercurial borrows this idea to make it |
belaran@999 | 3456 possible to reconstruct a revision from a snapshot and a |
belaran@999 | 3457 small number of deltas.</para> |
belaran@999 | 3458 |
belaran@999 | 3459 </sect3> |
belaran@999 | 3460 </sect2> |
belaran@999 | 3461 <sect2> |
belaran@999 | 3462 <title>Identification and strong integrity</title> |
belaran@999 | 3463 |
belaran@999 | 3464 <para id="x_300">Along with delta or snapshot information, a revlog entry |
belaran@999 | 3465 contains a cryptographic hash of the data that it represents. |
belaran@999 | 3466 This makes it difficult to forge the contents of a revision, |
belaran@999 | 3467 and easy to detect accidental corruption.</para> |
belaran@999 | 3468 |
belaran@999 | 3469 <para id="x_301">Hashes provide more than a mere check against corruption; |
belaran@999 | 3470 they are used as the identifiers for revisions. The changeset |
belaran@999 | 3471 identification hashes that you see as an end user are from |
belaran@999 | 3472 revisions of the changelog. Although filelogs and the |
belaran@999 | 3473 manifest also use hashes, Mercurial only uses these behind the |
belaran@999 | 3474 scenes.</para> |
belaran@999 | 3475 |
belaran@999 | 3476 <para id="x_302">Mercurial verifies that hashes are correct when it |
belaran@999 | 3477 retrieves file revisions and when it pulls changes from |
belaran@999 | 3478 another repository. If it encounters an integrity problem, it |
belaran@999 | 3479 will complain and stop whatever it's doing.</para> |
belaran@999 | 3480 |
belaran@999 | 3481 <para id="x_303">In addition to the effect it has on retrieval efficiency, |
belaran@999 | 3482 Mercurial's use of periodic snapshots makes it more robust |
belaran@999 | 3483 against partial data corruption. If a revlog becomes partly |
belaran@999 | 3484 corrupted due to a hardware error or system bug, it's often |
belaran@999 | 3485 possible to reconstruct some or most revisions from the |
belaran@999 | 3486 uncorrupted sections of the revlog, both before and after the |
belaran@999 | 3487 corrupted section. This would not be possible with a |
belaran@999 | 3488 delta-only storage model.</para> |
belaran@999 | 3489 </sect2> |
belaran@999 | 3490 </sect1> |
belaran@999 | 3491 |
belaran@999 | 3492 <sect1> |
belaran@999 | 3493 <title>Revision history, branching, and merging</title> |
belaran@999 | 3494 |
belaran@999 | 3495 <para id="x_304">Every entry in a Mercurial revlog knows the identity of its |
belaran@999 | 3496 immediate ancestor revision, usually referred to as its |
belaran@999 | 3497 <emphasis>parent</emphasis>. In fact, a revision contains room |
belaran@999 | 3498 for not one parent, but two. Mercurial uses a special hash, |
belaran@999 | 3499 called the <quote>null ID</quote>, to represent the idea |
belaran@999 | 3500 <quote>there is no parent here</quote>. This hash is simply a |
belaran@999 | 3501 string of zeroes.</para> |
belaran@999 | 3502 |
belaran@999 | 3503 <para id="x_305">In <xref linkend="fig:concepts:revlog"/>, you can see |
belaran@999 | 3504 an example of the conceptual structure of a revlog. Filelogs, |
belaran@999 | 3505 manifests, and changelogs all have this same structure; they |
belaran@999 | 3506 differ only in the kind of data stored in each delta or |
belaran@999 | 3507 snapshot.</para> |
belaran@999 | 3508 |
belaran@999 | 3509 <para id="x_306">The first revision in a revlog (at the bottom of the image) |
belaran@999 | 3510 has the null ID in both of its parent slots. For a |
belaran@999 | 3511 <quote>normal</quote> revision, its first parent slot contains |
belaran@999 | 3512 the ID of its parent revision, and its second contains the null |
belaran@999 | 3513 ID, indicating that the revision has only one real parent. Any |
belaran@999 | 3514 two revisions that have the same parent ID are branches. A |
belaran@999 | 3515 revision that represents a merge between branches has two normal |
belaran@999 | 3516 revision IDs in its parent slots.</para> |
belaran@999 | 3517 |
belaran@999 | 3518 <figure id="fig:concepts:revlog" float="0"> |
belaran@999 | 3519 <title>The conceptual structure of a revlog</title> |
belaran@999 | 3520 <mediaobject> |
belaran@999 | 3521 <imageobject><imagedata fileref="figs/revlog.png"/></imageobject> |
belaran@999 | 3522 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3523 </mediaobject> |
belaran@999 | 3524 </figure> |
belaran@999 | 3525 |
belaran@999 | 3526 </sect1> |
belaran@999 | 3527 <sect1> |
belaran@999 | 3528 <title>The working directory</title> |
belaran@999 | 3529 |
belaran@999 | 3530 <para id="x_307">In the working directory, Mercurial stores a snapshot of the |
belaran@999 | 3531 files from the repository as of a particular changeset.</para> |
belaran@999 | 3532 |
belaran@999 | 3533 <para id="x_308">The working directory <quote>knows</quote> which changeset |
belaran@999 | 3534 it contains. When you update the working directory to contain a |
belaran@999 | 3535 particular changeset, Mercurial looks up the appropriate |
belaran@999 | 3536 revision of the manifest to find out which files it was tracking |
belaran@999 | 3537 at the time that changeset was committed, and which revision of |
belaran@999 | 3538 each file was then current. It then recreates a copy of each of |
belaran@999 | 3539 those files, with the same contents it had when the changeset |
belaran@999 | 3540 was committed.</para> |
belaran@999 | 3541 |
belaran@999 | 3542 <para id="x_309">The <emphasis>dirstate</emphasis> is a special |
belaran@999 | 3543 structure that contains Mercurial's knowledge of the working |
belaran@999 | 3544 directory. It is maintained as a file named |
belaran@999 | 3545 <filename moreinfo="none">.hg/dirstate</filename> inside a repository. The |
belaran@999 | 3546 dirstate details which changeset the working directory is |
belaran@999 | 3547 updated to, and all of the files that Mercurial is tracking in |
belaran@999 | 3548 the working directory. It also lets Mercurial quickly notice |
belaran@999 | 3549 changed files, by recording their checkout times and |
belaran@999 | 3550 sizes.</para> |
belaran@999 | 3551 |
belaran@999 | 3552 <para id="x_30a">Just as a revision of a revlog has room for two parents, so |
belaran@999 | 3553 that it can represent either a normal revision (with one parent) |
belaran@999 | 3554 or a merge of two earlier revisions, the dirstate has slots for |
belaran@999 | 3555 two parents. When you use the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3556 update</command> command, the changeset that you update to is |
belaran@999 | 3557 stored in the <quote>first parent</quote> slot, and the null ID |
belaran@999 | 3558 in the second. When you <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3559 merge</command> with another changeset, the first parent |
belaran@999 | 3560 remains unchanged, and the second parent is filled in with the |
belaran@999 | 3561 changeset you're merging with. The <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3562 parents</command> command tells you what the parents of the |
belaran@999 | 3563 dirstate are.</para> |
belaran@999 | 3564 |
belaran@999 | 3565 <sect2> |
belaran@999 | 3566 <title>What happens when you commit</title> |
belaran@999 | 3567 |
belaran@999 | 3568 <para id="x_30b">The dirstate stores parent information for more than just |
belaran@999 | 3569 book-keeping purposes. Mercurial uses the parents of the |
belaran@999 | 3570 dirstate as <emphasis>the parents of a new |
belaran@999 | 3571 changeset</emphasis> when you perform a commit.</para> |
belaran@999 | 3572 |
belaran@999 | 3573 <figure id="fig:concepts:wdir" float="0"> |
belaran@999 | 3574 <title>The working directory can have two parents</title> |
belaran@999 | 3575 <mediaobject> |
belaran@999 | 3576 <imageobject><imagedata fileref="figs/wdir.png"/></imageobject> |
belaran@999 | 3577 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3578 </mediaobject> |
belaran@999 | 3579 </figure> |
belaran@999 | 3580 |
belaran@999 | 3581 <para id="x_30d"><xref linkend="fig:concepts:wdir"/> shows the |
belaran@999 | 3582 normal state of the working directory, where it has a single |
belaran@999 | 3583 changeset as parent. That changeset is the |
belaran@999 | 3584 <emphasis>tip</emphasis>, the newest changeset in the |
belaran@999 | 3585 repository that has no children.</para> |
belaran@999 | 3586 |
belaran@999 | 3587 <figure id="fig:concepts:wdir-after-commit" float="0"> |
belaran@999 | 3588 <title>The working directory gains new parents after a |
belaran@999 | 3589 commit</title> |
belaran@999 | 3590 <mediaobject> |
belaran@999 | 3591 <imageobject><imagedata fileref="figs/wdir-after-commit.png"/></imageobject> |
belaran@999 | 3592 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3593 </mediaobject> |
belaran@999 | 3594 </figure> |
belaran@999 | 3595 |
belaran@999 | 3596 <para id="x_30f">It's useful to think of the working directory as |
belaran@999 | 3597 <quote>the changeset I'm about to commit</quote>. Any files |
belaran@999 | 3598 that you tell Mercurial that you've added, removed, renamed, |
belaran@999 | 3599 or copied will be reflected in that changeset, as will |
belaran@999 | 3600 modifications to any files that Mercurial is already tracking; |
belaran@999 | 3601 the new changeset will have the parents of the working |
belaran@999 | 3602 directory as its parents.</para> |
belaran@999 | 3603 |
belaran@999 | 3604 <para id="x_310">After a commit, Mercurial will update the |
belaran@999 | 3605 parents of the working directory, so that the first parent is |
belaran@999 | 3606 the ID of the new changeset, and the second is the null ID. |
belaran@999 | 3607 This is shown in <xref linkend="fig:concepts:wdir-after-commit"/>. Mercurial |
belaran@999 | 3608 doesn't touch any of the files in the working directory when |
belaran@999 | 3609 you commit; it just modifies the dirstate to note its new |
belaran@999 | 3610 parents.</para> |
belaran@999 | 3611 |
belaran@999 | 3612 </sect2> |
belaran@999 | 3613 <sect2> |
belaran@999 | 3614 <title>Creating a new head</title> |
belaran@999 | 3615 |
belaran@999 | 3616 <para id="x_311">It's perfectly normal to update the working directory to a |
belaran@999 | 3617 changeset other than the current tip. For example, you might |
belaran@999 | 3618 want to know what your project looked like last Tuesday, or |
belaran@999 | 3619 you could be looking through changesets to see which one |
belaran@999 | 3620 introduced a bug. In cases like this, the natural thing to do |
belaran@999 | 3621 is update the working directory to the changeset you're |
belaran@999 | 3622 interested in, and then examine the files in the working |
belaran@999 | 3623 directory directly to see their contents as they were when you |
belaran@999 | 3624 committed that changeset. The effect of this is shown in |
belaran@999 | 3625 <xref linkend="fig:concepts:wdir-pre-branch"/>.</para> |
belaran@999 | 3626 |
belaran@999 | 3627 <figure id="fig:concepts:wdir-pre-branch" float="0"> |
belaran@999 | 3628 <title>The working directory, updated to an older |
belaran@999 | 3629 changeset</title> |
belaran@999 | 3630 <mediaobject> |
belaran@999 | 3631 <imageobject><imagedata fileref="figs/wdir-pre-branch.png"/></imageobject> |
belaran@999 | 3632 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3633 </mediaobject> |
belaran@999 | 3634 </figure> |
belaran@999 | 3635 |
belaran@999 | 3636 <para id="x_313">Having updated the working directory to an |
belaran@999 | 3637 older changeset, what happens if you make some changes, and |
belaran@999 | 3638 then commit? Mercurial behaves in the same way as I outlined |
belaran@999 | 3639 above. The parents of the working directory become the |
belaran@999 | 3640 parents of the new changeset. This new changeset has no |
belaran@999 | 3641 children, so it becomes the new tip. And the repository now |
belaran@999 | 3642 contains two changesets that have no children; we call these |
belaran@999 | 3643 <emphasis>heads</emphasis>. You can see the structure that |
belaran@999 | 3644 this creates in <xref linkend="fig:concepts:wdir-branch"/>.</para> |
belaran@999 | 3645 |
belaran@999 | 3646 <figure id="fig:concepts:wdir-branch" float="0"> |
belaran@999 | 3647 <title>After a commit made while synced to an older |
belaran@999 | 3648 changeset</title> |
belaran@999 | 3649 <mediaobject> |
belaran@999 | 3650 <imageobject><imagedata fileref="figs/wdir-branch.png"/></imageobject> |
belaran@999 | 3651 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3652 </mediaobject> |
belaran@999 | 3653 </figure> |
belaran@999 | 3654 |
belaran@999 | 3655 <note> |
belaran@999 | 3656 <para id="x_315">If you're new to Mercurial, you should keep |
belaran@999 | 3657 in mind a common <quote>error</quote>, which is to use the |
belaran@999 | 3658 <command role="hg-cmd" moreinfo="none">hg pull</command> command without any |
belaran@999 | 3659 options. By default, the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3660 pull</command> command <emphasis>does not</emphasis> |
belaran@999 | 3661 update the working directory, so you'll bring new changesets |
belaran@999 | 3662 into your repository, but the working directory will stay |
belaran@999 | 3663 synced at the same changeset as before the pull. If you |
belaran@999 | 3664 make some changes and commit afterwards, you'll thus create |
belaran@999 | 3665 a new head, because your working directory isn't synced to |
belaran@999 | 3666 whatever the current tip is. To combine the operation of a |
belaran@999 | 3667 pull, followed by an update, run <command moreinfo="none">hg pull |
belaran@999 | 3668 -u</command>.</para> |
belaran@999 | 3669 |
belaran@999 | 3670 <para id="x_316">I put the word <quote>error</quote> in quotes |
belaran@999 | 3671 because all that you need to do to rectify the situation |
belaran@999 | 3672 where you created a new head by accident is |
belaran@999 | 3673 <command role="hg-cmd" moreinfo="none">hg merge</command>, then <command role="hg-cmd" moreinfo="none">hg commit</command>. In other words, this |
belaran@999 | 3674 almost never has negative consequences; it's just something |
belaran@999 | 3675 of a surprise for newcomers. I'll discuss other ways to |
belaran@999 | 3676 avoid this behavior, and why Mercurial behaves in this |
belaran@999 | 3677 initially surprising way, later on.</para> |
belaran@999 | 3678 </note> |
belaran@999 | 3679 |
belaran@999 | 3680 </sect2> |
belaran@999 | 3681 <sect2> |
belaran@999 | 3682 <title>Merging changes</title> |
belaran@999 | 3683 |
belaran@999 | 3684 <para id="x_317">When you run the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3685 merge</command> command, Mercurial leaves the first parent |
belaran@999 | 3686 of the working directory unchanged, and sets the second parent |
belaran@999 | 3687 to the changeset you're merging with, as shown in <xref linkend="fig:concepts:wdir-merge"/>.</para> |
belaran@999 | 3688 |
belaran@999 | 3689 <figure id="fig:concepts:wdir-merge" float="0"> |
belaran@999 | 3690 <title>Merging two heads</title> |
belaran@999 | 3691 <mediaobject> |
belaran@999 | 3692 <imageobject> |
belaran@999 | 3693 <imagedata fileref="figs/wdir-merge.png"/> |
belaran@999 | 3694 </imageobject> |
belaran@999 | 3695 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 3696 </mediaobject> |
belaran@999 | 3697 </figure> |
belaran@999 | 3698 |
belaran@999 | 3699 <para id="x_319">Mercurial also has to modify the working directory, to |
belaran@999 | 3700 merge the files managed in the two changesets. Simplified a |
belaran@999 | 3701 little, the merging process goes like this, for every file in |
belaran@999 | 3702 the manifests of both changesets.</para> |
belaran@999 | 3703 <itemizedlist> |
belaran@999 | 3704 <listitem><para id="x_31a">If neither changeset has modified a file, do |
belaran@999 | 3705 nothing with that file.</para> |
belaran@999 | 3706 </listitem> |
belaran@999 | 3707 <listitem><para id="x_31b">If one changeset has modified a file, and the |
belaran@999 | 3708 other hasn't, create the modified copy of the file in the |
belaran@999 | 3709 working directory.</para> |
belaran@999 | 3710 </listitem> |
belaran@999 | 3711 <listitem><para id="x_31c">If one changeset has removed a file, and the |
belaran@999 | 3712 other hasn't (or has also deleted it), delete the file |
belaran@999 | 3713 from the working directory.</para> |
belaran@999 | 3714 </listitem> |
belaran@999 | 3715 <listitem><para id="x_31d">If one changeset has removed a file, but the |
belaran@999 | 3716 other has modified the file, ask the user what to do: keep |
belaran@999 | 3717 the modified file, or remove it?</para> |
belaran@999 | 3718 </listitem> |
belaran@999 | 3719 <listitem><para id="x_31e">If both changesets have modified a file, |
belaran@999 | 3720 invoke an external merge program to choose the new |
belaran@999 | 3721 contents for the merged file. This may require input from |
belaran@999 | 3722 the user.</para> |
belaran@999 | 3723 </listitem> |
belaran@999 | 3724 <listitem><para id="x_31f">If one changeset has modified a file, and the |
belaran@999 | 3725 other has renamed or copied the file, make sure that the |
belaran@999 | 3726 changes follow the new name of the file.</para> |
belaran@999 | 3727 </listitem></itemizedlist> |
belaran@999 | 3728 <para id="x_320">There are more details—merging has plenty of corner |
belaran@999 | 3729 cases—but these are the most common choices that are |
belaran@999 | 3730 involved in a merge. As you can see, most cases are |
belaran@999 | 3731 completely automatic, and indeed most merges finish |
belaran@999 | 3732 automatically, without requiring your input to resolve any |
belaran@999 | 3733 conflicts.</para> |
belaran@999 | 3734 |
belaran@999 | 3735 <para id="x_321">When you're thinking about what happens when you commit |
belaran@999 | 3736 after a merge, once again the working directory is <quote>the |
belaran@999 | 3737 changeset I'm about to commit</quote>. After the <command role="hg-cmd" moreinfo="none">hg merge</command> command completes, the |
belaran@999 | 3738 working directory has two parents; these will become the |
belaran@999 | 3739 parents of the new changeset.</para> |
belaran@999 | 3740 |
belaran@999 | 3741 <para id="x_322">Mercurial lets you perform multiple merges, but |
belaran@999 | 3742 you must commit the results of each individual merge as you |
belaran@999 | 3743 go. This is necessary because Mercurial only tracks two |
belaran@999 | 3744 parents for both revisions and the working directory. While |
belaran@999 | 3745 it would be technically feasible to merge multiple changesets |
belaran@999 | 3746 at once, Mercurial avoids this for simplicity. With multi-way |
belaran@999 | 3747 merges, the risks of user confusion, nasty conflict |
belaran@999 | 3748 resolution, and making a terrible mess of a merge would grow |
belaran@999 | 3749 intolerable.</para> |
belaran@999 | 3750 |
belaran@999 | 3751 </sect2> |
belaran@999 | 3752 |
belaran@999 | 3753 <sect2> |
belaran@999 | 3754 <title>Merging and renames</title> |
belaran@999 | 3755 |
belaran@999 | 3756 <para id="x_69a">A surprising number of revision control systems pay little |
belaran@999 | 3757 or no attention to a file's <emphasis>name</emphasis> over |
belaran@999 | 3758 time. For instance, it used to be common that if a file got |
belaran@999 | 3759 renamed on one side of a merge, the changes from the other |
belaran@999 | 3760 side would be silently dropped.</para> |
belaran@999 | 3761 |
belaran@999 | 3762 <para id="x_69b">Mercurial records metadata when you tell it to perform a |
belaran@999 | 3763 rename or copy. It uses this metadata during a merge to do the |
belaran@999 | 3764 right thing in the case of a merge. For instance, if I rename |
belaran@999 | 3765 a file, and you edit it without renaming it, when we merge our |
belaran@999 | 3766 work the file will be renamed and have your edits |
belaran@999 | 3767 applied.</para> |
belaran@999 | 3768 </sect2> |
belaran@999 | 3769 </sect1> |
belaran@999 | 3770 |
belaran@999 | 3771 <sect1> |
belaran@999 | 3772 <title>Other interesting design features</title> |
belaran@999 | 3773 |
belaran@999 | 3774 <para id="x_323">In the sections above, I've tried to highlight some of the |
belaran@999 | 3775 most important aspects of Mercurial's design, to illustrate that |
belaran@999 | 3776 it pays careful attention to reliability and performance. |
belaran@999 | 3777 However, the attention to detail doesn't stop there. There are |
belaran@999 | 3778 a number of other aspects of Mercurial's construction that I |
belaran@999 | 3779 personally find interesting. I'll detail a few of them here, |
belaran@999 | 3780 separate from the <quote>big ticket</quote> items above, so that |
belaran@999 | 3781 if you're interested, you can gain a better idea of the amount |
belaran@999 | 3782 of thinking that goes into a well-designed system.</para> |
belaran@999 | 3783 |
belaran@999 | 3784 <sect2> |
belaran@999 | 3785 <title>Clever compression</title> |
belaran@999 | 3786 |
belaran@999 | 3787 <para id="x_324">When appropriate, Mercurial will store both snapshots and |
belaran@999 | 3788 deltas in compressed form. It does this by always |
belaran@999 | 3789 <emphasis>trying to</emphasis> compress a snapshot or delta, |
belaran@999 | 3790 but only storing the compressed version if it's smaller than |
belaran@999 | 3791 the uncompressed version.</para> |
belaran@999 | 3792 |
belaran@999 | 3793 <para id="x_325">This means that Mercurial does <quote>the right |
belaran@999 | 3794 thing</quote> when storing a file whose native form is |
belaran@999 | 3795 compressed, such as a <literal moreinfo="none">zip</literal> archive or a JPEG |
belaran@999 | 3796 image. When these types of files are compressed a second |
belaran@999 | 3797 time, the resulting file is usually bigger than the |
belaran@999 | 3798 once-compressed form, and so Mercurial will store the plain |
belaran@999 | 3799 <literal moreinfo="none">zip</literal> or JPEG.</para> |
belaran@999 | 3800 |
belaran@999 | 3801 <para id="x_326">Deltas between revisions of a compressed file are usually |
belaran@999 | 3802 larger than snapshots of the file, and Mercurial again does |
belaran@999 | 3803 <quote>the right thing</quote> in these cases. It finds that |
belaran@999 | 3804 such a delta exceeds the threshold at which it should store a |
belaran@999 | 3805 complete snapshot of the file, so it stores the snapshot, |
belaran@999 | 3806 again saving space compared to a naive delta-only |
belaran@999 | 3807 approach.</para> |
belaran@999 | 3808 |
belaran@999 | 3809 <sect3> |
belaran@999 | 3810 <title>Network recompression</title> |
belaran@999 | 3811 |
belaran@999 | 3812 <para id="x_327">When storing revisions on disk, Mercurial uses the |
belaran@999 | 3813 <quote>deflate</quote> compression algorithm (the same one |
belaran@999 | 3814 used by the popular <literal moreinfo="none">zip</literal> archive format), |
belaran@999 | 3815 which balances good speed with a respectable compression |
belaran@999 | 3816 ratio. However, when transmitting revision data over a |
belaran@999 | 3817 network connection, Mercurial uncompresses the compressed |
belaran@999 | 3818 revision data.</para> |
belaran@999 | 3819 |
belaran@999 | 3820 <para id="x_328">If the connection is over HTTP, Mercurial recompresses |
belaran@999 | 3821 the entire stream of data using a compression algorithm that |
belaran@999 | 3822 gives a better compression ratio (the Burrows-Wheeler |
belaran@999 | 3823 algorithm from the widely used <literal moreinfo="none">bzip2</literal> |
belaran@999 | 3824 compression package). This combination of algorithm and |
belaran@999 | 3825 compression of the entire stream (instead of a revision at a |
belaran@999 | 3826 time) substantially reduces the number of bytes to be |
belaran@999 | 3827 transferred, yielding better network performance over most |
belaran@999 | 3828 kinds of network.</para> |
belaran@999 | 3829 |
belaran@999 | 3830 <para id="x_329">If the connection is over |
belaran@999 | 3831 <command moreinfo="none">ssh</command>, Mercurial |
belaran@999 | 3832 <emphasis>doesn't</emphasis> recompress the stream, because |
belaran@999 | 3833 <command moreinfo="none">ssh</command> can already do this itself. You can |
belaran@999 | 3834 tell Mercurial to always use <command moreinfo="none">ssh</command>'s |
belaran@999 | 3835 compression feature by editing the |
belaran@999 | 3836 <filename moreinfo="none">.hgrc</filename> file in your home directory as |
belaran@999 | 3837 follows.</para> |
belaran@999 | 3838 |
belaran@999 | 3839 <programlisting format="linespecific">[ui] |
belaran@999 | 3840 ssh = ssh -C</programlisting> |
belaran@999 | 3841 |
belaran@999 | 3842 </sect3> |
belaran@999 | 3843 </sect2> |
belaran@999 | 3844 <sect2> |
belaran@999 | 3845 <title>Read/write ordering and atomicity</title> |
belaran@999 | 3846 |
belaran@999 | 3847 <para id="x_32a">Appending to files isn't the whole story when |
belaran@999 | 3848 it comes to guaranteeing that a reader won't see a partial |
belaran@999 | 3849 write. If you recall <xref linkend="fig:concepts:metadata"/>, |
belaran@999 | 3850 revisions in the changelog point to revisions in the manifest, |
belaran@999 | 3851 and revisions in the manifest point to revisions in filelogs. |
belaran@999 | 3852 This hierarchy is deliberate.</para> |
belaran@999 | 3853 |
belaran@999 | 3854 <para id="x_32b">A writer starts a transaction by writing filelog and |
belaran@999 | 3855 manifest data, and doesn't write any changelog data until |
belaran@999 | 3856 those are finished. A reader starts by reading changelog |
belaran@999 | 3857 data, then manifest data, followed by filelog data.</para> |
belaran@999 | 3858 |
belaran@999 | 3859 <para id="x_32c">Since the writer has always finished writing filelog and |
belaran@999 | 3860 manifest data before it writes to the changelog, a reader will |
belaran@999 | 3861 never read a pointer to a partially written manifest revision |
belaran@999 | 3862 from the changelog, and it will never read a pointer to a |
belaran@999 | 3863 partially written filelog revision from the manifest.</para> |
belaran@999 | 3864 |
belaran@999 | 3865 </sect2> |
belaran@999 | 3866 <sect2> |
belaran@999 | 3867 <title>Concurrent access</title> |
belaran@999 | 3868 |
belaran@999 | 3869 <para id="x_32d">The read/write ordering and atomicity guarantees mean that |
belaran@999 | 3870 Mercurial never needs to <emphasis>lock</emphasis> a |
belaran@999 | 3871 repository when it's reading data, even if the repository is |
belaran@999 | 3872 being written to while the read is occurring. This has a big |
belaran@999 | 3873 effect on scalability; you can have an arbitrary number of |
belaran@999 | 3874 Mercurial processes safely reading data from a repository |
belaran@999 | 3875 all at once, no matter whether it's being written to or |
belaran@999 | 3876 not.</para> |
belaran@999 | 3877 |
belaran@999 | 3878 <para id="x_32e">The lockless nature of reading means that if you're |
belaran@999 | 3879 sharing a repository on a multi-user system, you don't need to |
belaran@999 | 3880 grant other local users permission to |
belaran@999 | 3881 <emphasis>write</emphasis> to your repository in order for |
belaran@999 | 3882 them to be able to clone it or pull changes from it; they only |
belaran@999 | 3883 need <emphasis>read</emphasis> permission. (This is |
belaran@999 | 3884 <emphasis>not</emphasis> a common feature among revision |
belaran@999 | 3885 control systems, so don't take it for granted! Most require |
belaran@999 | 3886 readers to be able to lock a repository to access it safely, |
belaran@999 | 3887 and this requires write permission on at least one directory, |
belaran@999 | 3888 which of course makes for all kinds of nasty and annoying |
belaran@999 | 3889 security and administrative problems.)</para> |
belaran@999 | 3890 |
belaran@999 | 3891 <para id="x_32f">Mercurial uses locks to ensure that only one process can |
belaran@999 | 3892 write to a repository at a time (the locking mechanism is safe |
belaran@999 | 3893 even over filesystems that are notoriously hostile to locking, |
belaran@999 | 3894 such as NFS). If a repository is locked, a writer will wait |
belaran@999 | 3895 for a while to retry if the repository becomes unlocked, but |
belaran@999 | 3896 if the repository remains locked for too long, the process |
belaran@999 | 3897 attempting to write will time out after a while. This means |
belaran@999 | 3898 that your daily automated scripts won't get stuck forever and |
belaran@999 | 3899 pile up if a system crashes unnoticed, for example. (Yes, the |
belaran@999 | 3900 timeout is configurable, from zero to infinity.)</para> |
belaran@999 | 3901 |
belaran@999 | 3902 <sect3> |
belaran@999 | 3903 <title>Safe dirstate access</title> |
belaran@999 | 3904 |
belaran@999 | 3905 <para id="x_330">As with revision data, Mercurial doesn't take a lock to |
belaran@999 | 3906 read the dirstate file; it does acquire a lock to write it. |
belaran@999 | 3907 To avoid the possibility of reading a partially written copy |
belaran@999 | 3908 of the dirstate file, Mercurial writes to a file with a |
belaran@999 | 3909 unique name in the same directory as the dirstate file, then |
belaran@999 | 3910 renames the temporary file atomically to |
belaran@999 | 3911 <filename moreinfo="none">dirstate</filename>. The file named |
belaran@999 | 3912 <filename moreinfo="none">dirstate</filename> is thus guaranteed to be |
belaran@999 | 3913 complete, not partially written.</para> |
belaran@999 | 3914 |
belaran@999 | 3915 </sect3> |
belaran@999 | 3916 </sect2> |
belaran@999 | 3917 <sect2> |
belaran@999 | 3918 <title>Avoiding seeks</title> |
belaran@999 | 3919 |
belaran@999 | 3920 <para id="x_331">Critical to Mercurial's performance is the avoidance of |
belaran@999 | 3921 seeks of the disk head, since any seek is far more expensive |
belaran@999 | 3922 than even a comparatively large read operation.</para> |
belaran@999 | 3923 |
belaran@999 | 3924 <para id="x_332">This is why, for example, the dirstate is stored in a |
belaran@999 | 3925 single file. If there were a dirstate file per directory that |
belaran@999 | 3926 Mercurial tracked, the disk would seek once per directory. |
belaran@999 | 3927 Instead, Mercurial reads the entire single dirstate file in |
belaran@999 | 3928 one step.</para> |
belaran@999 | 3929 |
belaran@999 | 3930 <para id="x_333">Mercurial also uses a <quote>copy on write</quote> scheme |
belaran@999 | 3931 when cloning a repository on local storage. Instead of |
belaran@999 | 3932 copying every revlog file from the old repository into the new |
belaran@999 | 3933 repository, it makes a <quote>hard link</quote>, which is a |
belaran@999 | 3934 shorthand way to say <quote>these two names point to the same |
belaran@999 | 3935 file</quote>. When Mercurial is about to write to one of a |
belaran@999 | 3936 revlog's files, it checks to see if the number of names |
belaran@999 | 3937 pointing at the file is greater than one. If it is, more than |
belaran@999 | 3938 one repository is using the file, so Mercurial makes a new |
belaran@999 | 3939 copy of the file that is private to this repository.</para> |
belaran@999 | 3940 |
belaran@999 | 3941 <para id="x_334">A few revision control developers have pointed out that |
belaran@999 | 3942 this idea of making a complete private copy of a file is not |
belaran@999 | 3943 very efficient in its use of storage. While this is true, |
belaran@999 | 3944 storage is cheap, and this method gives the highest |
belaran@999 | 3945 performance while deferring most book-keeping to the operating |
belaran@999 | 3946 system. An alternative scheme would most likely reduce |
belaran@999 | 3947 performance and increase the complexity of the software, but |
belaran@999 | 3948 speed and simplicity are key to the <quote>feel</quote> of |
belaran@999 | 3949 day-to-day use.</para> |
belaran@999 | 3950 |
belaran@999 | 3951 </sect2> |
belaran@999 | 3952 <sect2> |
belaran@999 | 3953 <title>Other contents of the dirstate</title> |
belaran@999 | 3954 |
belaran@999 | 3955 <para id="x_335">Because Mercurial doesn't force you to tell it when you're |
belaran@999 | 3956 modifying a file, it uses the dirstate to store some extra |
belaran@999 | 3957 information so it can determine efficiently whether you have |
belaran@999 | 3958 modified a file. For each file in the working directory, it |
belaran@999 | 3959 stores the time that it last modified the file itself, and the |
belaran@999 | 3960 size of the file at that time.</para> |
belaran@999 | 3961 |
belaran@999 | 3962 <para id="x_336">When you explicitly <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 3963 add</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>, |
belaran@999 | 3964 <command role="hg-cmd" moreinfo="none">hg rename</command> or <command role="hg-cmd" moreinfo="none">hg copy</command> files, Mercurial updates the |
belaran@999 | 3965 dirstate so that it knows what to do with those files when you |
belaran@999 | 3966 commit.</para> |
belaran@999 | 3967 |
belaran@999 | 3968 <para id="x_337">The dirstate helps Mercurial to efficiently |
belaran@999 | 3969 check the status of files in a repository.</para> |
belaran@999 | 3970 |
belaran@999 | 3971 <itemizedlist> |
belaran@999 | 3972 <listitem> |
belaran@999 | 3973 <para id="x_726">When Mercurial checks the state of a file in the |
belaran@999 | 3974 working directory, it first checks a file's modification |
belaran@999 | 3975 time against the time in the dirstate that records when |
belaran@999 | 3976 Mercurial last wrote the file. If the last modified time |
belaran@999 | 3977 is the same as the time when Mercurial wrote the file, the |
belaran@999 | 3978 file must not have been modified, so Mercurial does not |
belaran@999 | 3979 need to check any further.</para> |
belaran@999 | 3980 </listitem> |
belaran@999 | 3981 <listitem> |
belaran@999 | 3982 <para id="x_727">If the file's size has changed, the file must have |
belaran@999 | 3983 been modified. If the modification time has changed, but |
belaran@999 | 3984 the size has not, only then does Mercurial need to |
belaran@999 | 3985 actually read the contents of the file to see if it has |
belaran@999 | 3986 changed.</para> |
belaran@999 | 3987 </listitem> |
belaran@999 | 3988 </itemizedlist> |
belaran@999 | 3989 |
belaran@999 | 3990 <para id="x_728">Storing the modification time and size dramatically |
belaran@999 | 3991 reduces the number of read operations that Mercurial needs to |
belaran@999 | 3992 perform when we run commands like <command moreinfo="none">hg status</command>. |
belaran@999 | 3993 This results in large performance improvements.</para> |
belaran@999 | 3994 </sect2> |
belaran@999 | 3995 </sect1> |
belaran@999 | 3996 </chapter> |
belaran@999 | 3997 |
belaran@999 | 3998 <!-- |
belaran@999 | 3999 local variables: |
belaran@999 | 4000 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 4001 end: |
belaran@999 | 4002 --> |
belaran@999 | 4003 |
belaran@999 | 4004 <!-- BEGIN ch05 --> |
belaran@999 | 4005 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 4006 |
belaran@999 | 4007 <chapter id="chap:daily"> |
belaran@999 | 4008 <?dbhtml filename="mercurial-in-daily-use.html"?> |
belaran@999 | 4009 <title>Mercurial pour une utilisation de tous les jours</title> |
belaran@999 | 4010 |
belaran@999 | 4011 <sect1> |
belaran@999 | 4012 <title>Informer Mercurial des fichier à suivre</title> |
belaran@999 | 4013 |
belaran@999 | 4014 <para id="x_1a3">Mercurial ne suit pas les fichiers de votre dépôt tant |
belaran@999 | 4015 que vous ne lui avez pas dit de les gérer. La commande <command role="hg-cmd" moreinfo="none">hg status</command> vous dira quels fichiers sont |
belaran@999 | 4016 inconnus de Mercurial. Il utilise un |
belaran@999 | 4017 <quote><literal moreinfo="none">?</literal></quote> pour montrer ces fichiers.</para> |
belaran@999 | 4018 |
belaran@999 | 4019 <para id="x_1a4">Pour informer Mercurial de suivre un fichier, utilisez |
belaran@999 | 4020 la commande <command role="hg-cmd" moreinfo="none">hg add</command>. Une fois que vous |
belaran@999 | 4021 avez ajouté un fichier, la ligne correspondante à ce fichier dans la |
belaran@999 | 4022 sortie de <command role="hg-cmd" moreinfo="none">hg status</command> change de |
belaran@999 | 4023 <quote><literal moreinfo="none">?</literal></quote> à |
belaran@999 | 4024 <quote><literal moreinfo="none">A</literal></quote>.</para> |
belaran@999 | 4025 |
belaran@999 | 4026 <!-- BEGIN daily.files.add --> |
belaran@999 | 4027 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init add-example</userinput> |
belaran@999 | 4028 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd add-example</userinput> |
belaran@999 | 4029 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > myfile.txt</userinput> |
belaran@999 | 4030 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4031 ? myfile.txt |
belaran@999 | 4032 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile.txt</userinput> |
belaran@999 | 4033 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4034 A myfile.txt |
belaran@999 | 4035 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added one file'</userinput> |
belaran@999 | 4036 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4037 </screen> |
belaran@999 | 4038 <!-- END daily.files.add --> |
belaran@999 | 4039 |
belaran@999 | 4040 |
belaran@999 | 4041 <para id="x_1a5">Après avoir exécuté un <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4042 commit</command>, les fichiers que vous avez ajoutés avant le commit |
belaran@999 | 4043 ne seront plus listés dans la sortie de <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4044 status</command>. La raison de ceci est que, par défaut, <command role="hg-cmd" moreinfo="none">hg status</command> ne vous montre que les fichiers |
belaran@999 | 4045 <quote>intéressants</quote> —ceux que vous avez (par exemple) |
belaran@999 | 4046 modifiés, supprimés ou renommés. Si vous aviez un dépôt qui contient un |
belaran@999 | 4047 millier de fichiers, vous ne voudriez certainement que rarement entendre |
belaran@999 | 4048 parler des fichiers que Mercurial suit, mais qui n'ont pas changés. |
belaran@999 | 4049 (Vous pouvez quand même avoir cette information, nous y reviendrons |
belaran@999 | 4050 plus tard.)</para> |
belaran@999 | 4051 |
belaran@999 | 4052 <para id="x_1a6">Une fois que vous ajoutez un fichier, Mercurial ne fait |
belaran@999 | 4053 rien du tout avec celui-ci immédiatement. Au lieu de ça, il va prendre |
belaran@999 | 4054 un "snapshot" de l'état du fichier la prochaine fois que vous |
belaran@999 | 4055 exécuterez un commit. Il continuera ensuite à suivre les changements |
belaran@999 | 4056 que vous avez fait au fichier chaque fois que vous committerez, et ce, |
belaran@999 | 4057 jusqu'à ce que vous supprimiez le fichier.</para> |
belaran@999 | 4058 |
belaran@999 | 4059 <sect2> |
belaran@999 | 4060 <title>Nommage des fichiers explicite versus implicite</title> |
belaran@999 | 4061 |
belaran@999 | 4062 <para id="x_1a7">Un comportement utile que Mercurial possède est que si |
belaran@999 | 4063 vous passez le nom d'un répertoire à une commande, toute commande |
belaran@999 | 4064 Mercurial la traitera comme : <quote>Je veux opérer sur chaque fichier |
belaran@999 | 4065 dans ce répertoire et ses sous-répertoires</quote>.</para> |
belaran@999 | 4066 |
belaran@999 | 4067 <!-- BEGIN daily.files.add-dir --> |
belaran@999 | 4068 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput> |
belaran@999 | 4069 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b/somefile.txt</userinput> |
belaran@999 | 4070 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c > b/source.cpp</userinput> |
belaran@999 | 4071 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b/d</userinput> |
belaran@999 | 4072 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo d > b/d/test.h</userinput> |
belaran@999 | 4073 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput> |
belaran@999 | 4074 adding b/d/test.h |
belaran@999 | 4075 adding b/somefile.txt |
belaran@999 | 4076 adding b/source.cpp |
belaran@999 | 4077 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added all files in subdirectory'</userinput> |
belaran@999 | 4078 </screen> |
belaran@999 | 4079 <!-- END daily.files.add-dir --> |
belaran@999 | 4080 |
belaran@999 | 4081 |
belaran@999 | 4082 <para id="x_1a8">Remarquez que dans cet exemple, Mercurial affiche le |
belaran@999 | 4083 nom des fichiers qu'il a ajouté, alors qu'il ne l'a pas fait lorsque |
belaran@999 | 4084 nous avons ajouté le fichier nommé <filename moreinfo="none">myfile.txt</filename> |
belaran@999 | 4085 dans l'exemple précédent.</para> |
belaran@999 | 4086 |
belaran@999 | 4087 <para id="x_1a9">Ce qu'il se passe est que dans le premier cas, nous |
belaran@999 | 4088 avons nommé explicitement le fichier à ajouter sur la ligne de |
belaran@999 | 4089 commande. Ce que Mercurial suppose dans ce cas est que nous savons ce |
belaran@999 | 4090 que nous faisons, il n'affiche donc rien en sortie.</para> |
belaran@999 | 4091 |
belaran@999 | 4092 <para id="x_1aa">Cependant, lorsque nous avons |
belaran@999 | 4093 <emphasis>implicitement</emphasis> donné les fichiers à l'aide du nom |
belaran@999 | 4094 d'un répertoire, Mercurial prend l'initiative d'afficher le nom de |
belaran@999 | 4095 chaque fichier avec lequel il fait quelque chose. Ceci clarifie ce |
belaran@999 | 4096 qu'il se passe et réduit la probabilité d'une mauvaise surprise |
belaran@999 | 4097 restée silencieuse. Ce comportement est commun à la plupart des |
belaran@999 | 4098 commandes Mercurial.</para> |
belaran@999 | 4099 </sect2> |
belaran@999 | 4100 <sect2> |
belaran@999 | 4101 <title>Mercurial suit les fichiers, pas les répertoires</title> |
belaran@999 | 4102 |
belaran@999 | 4103 <para id="x_1ab">Mercurial ne suit pas les informations sur les |
belaran@999 | 4104 répertoires. En contrepartie, il suit le chemin vers un fichier. Avant |
belaran@999 | 4105 de créer un fichier, il crée au préalable les répertoires manquants |
belaran@999 | 4106 dans le chemin. Après avoir supprimé un fichier, il supprime chaque |
belaran@999 | 4107 répertoire vide qui apparaît dans le chemin du fichier. Ceci apparaît |
belaran@999 | 4108 comme une distinction triviale, cependant, cela a une conséquence |
belaran@999 | 4109 pratique mineure : il n'est pas possible de représenter un répertoire |
belaran@999 | 4110 totalement vide dans Mercurial.</para> |
belaran@999 | 4111 |
belaran@999 | 4112 <para id="x_1ac">Les répertoires vides sont rarement utiles. Il existe |
belaran@999 | 4113 cependant des solutions alternatives et non intrusives que vous |
belaran@999 | 4114 pouvez utiliser pour obtenir l'effet approprié. Les développeurs de |
belaran@999 | 4115 Mercurial ont ainsi pensé que la complexité requise pour gérer les |
belaran@999 | 4116 répertoires n'était pas aussi importante que le bénéfice que cette |
belaran@999 | 4117 fonctionnalité apporterait.</para> |
belaran@999 | 4118 |
belaran@999 | 4119 <para id="x_1ad">Si vous avez besoin d'un répertoire vide dans votre |
belaran@999 | 4120 dépôt, il existe quelques façons d'y arriver. L'une d'elles est de |
belaran@999 | 4121 créer un répertoire et ensuite, de faire un <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4122 add</command> sur un fichier <quote>caché</quote> dans ce |
belaran@999 | 4123 répertoire. Sur les systèmes de type Unix, tout fichier dont le nom |
belaran@999 | 4124 commence avec un point (<quote><literal moreinfo="none">.</literal></quote>) est |
belaran@999 | 4125 considéré comme caché par la plupart des commandes et outils |
belaran@999 | 4126 graphiques. Cette approche est illustrée ci-après.</para> |
belaran@999 | 4127 |
belaran@999 | 4128 <!-- BEGIN daily.files.hidden --> |
belaran@999 | 4129 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hidden-example</userinput> |
belaran@999 | 4130 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hidden-example</userinput> |
belaran@999 | 4131 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir empty</userinput> |
belaran@999 | 4132 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">touch empty/.hidden</userinput> |
belaran@999 | 4133 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add empty/.hidden</userinput> |
belaran@999 | 4134 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Manage an empty-looking directory'</userinput> |
belaran@999 | 4135 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls empty</userinput> |
belaran@999 | 4136 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 4137 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone hidden-example tmp</userinput> |
belaran@999 | 4138 updating working directory |
belaran@999 | 4139 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4140 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp</userinput> |
belaran@999 | 4141 empty |
belaran@999 | 4142 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls tmp/empty</userinput> |
belaran@999 | 4143 </screen> |
belaran@999 | 4144 <!-- END daily.files.hidden --> |
belaran@999 | 4145 |
belaran@999 | 4146 |
belaran@999 | 4147 <para id="x_1ae">Une autre façon de s'attaquer au besoin d'un |
belaran@999 | 4148 répertoire vide est de simplement d'en créer un dans vos scripts |
belaran@999 | 4149 de construction avant qu'ils n'en aient le besoin.</para> |
belaran@999 | 4150 </sect2> |
belaran@999 | 4151 </sect1> |
belaran@999 | 4152 |
belaran@999 | 4153 <sect1> |
belaran@999 | 4154 <title>Comment arrêter de suivre un fichier</title> |
belaran@999 | 4155 |
belaran@999 | 4156 <para id="x_1af">Une fois que vous décidez qu'un fichier n'appartient |
belaran@999 | 4157 plus à votre dépôt, utilisez la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4158 remove</command>. Ceci supprime le fichier et informe Mercurial |
belaran@999 | 4159 d'arrêter de le suivre (ce qui prendra effet lors du prochain commit). |
belaran@999 | 4160 Un fichier supprimé est représenté dans la sortie de la commande |
belaran@999 | 4161 <command role="hg-cmd" moreinfo="none">hg status</command> par un |
belaran@999 | 4162 <quote><literal moreinfo="none">R</literal></quote>.</para> |
belaran@999 | 4163 |
belaran@999 | 4164 <!-- BEGIN daily.files.remove --> |
belaran@999 | 4165 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init remove-example</userinput> |
belaran@999 | 4166 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd remove-example</userinput> |
belaran@999 | 4167 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 4168 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput> |
belaran@999 | 4169 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b/b</userinput> |
belaran@999 | 4170 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a b</userinput> |
belaran@999 | 4171 adding b/b |
belaran@999 | 4172 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Small example for file removal'</userinput> |
belaran@999 | 4173 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove a</userinput> |
belaran@999 | 4174 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4175 R a |
belaran@999 | 4176 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove b</userinput> |
belaran@999 | 4177 removing b/b |
belaran@999 | 4178 </screen> |
belaran@999 | 4179 <!-- END daily.files.remove --> |
belaran@999 | 4180 |
belaran@999 | 4181 |
belaran@999 | 4182 <para id="x_1b0">Après avoir fait un <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4183 remove</command> sur un fichier, Mercurial ne suivra plus aucun |
belaran@999 | 4184 changement sur ce fichier, même si vous recréez un fichier avec le même |
belaran@999 | 4185 nom dans votre répertoire de travail. Si vous recréez un fichier avec le |
belaran@999 | 4186 même nom et que vous désirez que Mercurial suive ce dernier, faite |
belaran@999 | 4187 simplement un <command role="hg-cmd" moreinfo="none">hg add</command> sur celui-ci. |
belaran@999 | 4188 Mercurial saura alors que le nouveau fichier ne fait pas référence à |
belaran@999 | 4189 l'ancien fichier qui portait le même nom.</para> |
belaran@999 | 4190 |
belaran@999 | 4191 <sect2> |
belaran@999 | 4192 <title>Supprimer un fichier n'affecte pas son historique</title> |
belaran@999 | 4193 |
belaran@999 | 4194 <para id="x_1b1">Il est important de comprendre que supprimer un fichier |
belaran@999 | 4195 n'a que deux effets.</para> |
belaran@999 | 4196 |
belaran@999 | 4197 <itemizedlist> |
belaran@999 | 4198 <listitem><para id="x_1b2">Il supprime la version actuelle de ce |
belaran@999 | 4199 fichier du répertoire de travail.</para> |
belaran@999 | 4200 </listitem> |
belaran@999 | 4201 <listitem><para id="x_1b3">Il arrête, à partir du prochain commit, le |
belaran@999 | 4202 suivi de Mercurial sur les changements qui ont lieu sur ce |
belaran@999 | 4203 fichier.</para> |
belaran@999 | 4204 </listitem></itemizedlist> |
belaran@999 | 4205 |
belaran@999 | 4206 <para id="x_1b4">Supprimer un fichier <emphasis>n'</emphasis>affecte en |
belaran@999 | 4207 <emphasis>aucun</emphasis> cas l'<emphasis>historique</emphasis> du |
belaran@999 | 4208 fichier.</para> |
belaran@999 | 4209 |
belaran@999 | 4210 <para id="x_1b5">Si vous mettez à jour le répertoire de travail à un |
belaran@999 | 4211 changeset qui a été committé alors que le fichier que vous venez de |
belaran@999 | 4212 supprimer était encore suivi, ce fichier réapparaîtra dans le |
belaran@999 | 4213 répertoire de travail, avec le contenu qu'il avait lorsque vous aviez |
belaran@999 | 4214 committé ce changeset. Si vous mettez à jour (update) le répertoire de |
belaran@999 | 4215 travail à un changeset ultérieur dans lequel le fichier a été |
belaran@999 | 4216 supprimé, Mercurial supprimera une nouvelle fois le fichier du |
belaran@999 | 4217 répertoire de travail.</para> |
belaran@999 | 4218 </sect2> |
belaran@999 | 4219 |
belaran@999 | 4220 <sect2> |
belaran@999 | 4221 <title>Fichiers manquants</title> |
belaran@999 | 4222 |
belaran@999 | 4223 <para id="x_1b6">Mercurial considère qu'un fichier que vous avez |
belaran@999 | 4224 supprimé sans utiliser<command role="hg-cmd" moreinfo="none">hg remove</command> |
belaran@999 | 4225 comme étant <emphasis>manquant</emphasis>. Un fichier manquant est |
belaran@999 | 4226 représenté avec un <quote><literal moreinfo="none">!</literal></quote> en sortie de |
belaran@999 | 4227 <command role="hg-cmd" moreinfo="none">hg status</command>. |
belaran@999 | 4228 Les commandes Mercurial ne feront rien avec les fichiers |
belaran@999 | 4229 manquants.</para> |
belaran@999 | 4230 |
belaran@999 | 4231 <!-- BEGIN daily.files.missing --> |
belaran@999 | 4232 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init missing-example</userinput> |
belaran@999 | 4233 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd missing-example</userinput> |
belaran@999 | 4234 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 4235 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> |
belaran@999 | 4236 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'File about to be missing'</userinput> |
belaran@999 | 4237 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm a</userinput> |
belaran@999 | 4238 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4239 ! a |
belaran@999 | 4240 </screen> |
belaran@999 | 4241 <!-- END daily.files.missing --> |
belaran@999 | 4242 |
belaran@999 | 4243 |
belaran@999 | 4244 <para id="x_1b7">Si votre dépôt contient un fichier que <command role="hg-cmd" moreinfo="none">hg status</command> reporte comme manquant, et que |
belaran@999 | 4245 vous voulez que ce fichier reste supprimé, vous pouvez exécuter |
belaran@999 | 4246 <command role="hg-cmd" moreinfo="none">hg remove <option role="hg-opt-remove">--after</option></command> à tout moment |
belaran@999 | 4247 pour dire à Mercurial que vous aviez bien voulu supprimer ce |
belaran@999 | 4248 fichier.</para> |
belaran@999 | 4249 |
belaran@999 | 4250 <!-- BEGIN daily.files.remove-after --> |
belaran@999 | 4251 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove --after a</userinput> |
belaran@999 | 4252 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4253 R a |
belaran@999 | 4254 </screen> |
belaran@999 | 4255 <!-- END daily.files.remove-after --> |
belaran@999 | 4256 |
belaran@999 | 4257 |
belaran@999 | 4258 <para id="x_1b8">D'un autre coté, si vous avez supprimé le fichier |
belaran@999 | 4259 manquant par accident, donnez à la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4260 revert</command> le nom du fichier à retrouver. Il réapparaitra dans |
belaran@999 | 4261 sa forme non modifiée.</para> |
belaran@999 | 4262 |
belaran@999 | 4263 <!-- BEGIN daily.files.recover-missing --> |
belaran@999 | 4264 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert a</userinput> |
belaran@999 | 4265 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat a</userinput> |
belaran@999 | 4266 a |
belaran@999 | 4267 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4268 </screen> |
belaran@999 | 4269 <!-- END daily.files.recover-missing --> |
belaran@999 | 4270 |
belaran@999 | 4271 |
belaran@999 | 4272 </sect2> |
belaran@999 | 4273 |
belaran@999 | 4274 <sect2> |
belaran@999 | 4275 <title>Entre nous : Pourquoi dire explicitement à Mercurial de supprimer un |
belaran@999 | 4276 fichier ?</title> |
belaran@999 | 4277 |
belaran@999 | 4278 <para id="x_1b9">Vous pourriez vous demander pourquoi il est nécessaire |
belaran@999 | 4279 de dire explicitement à Mercurial que vous souhaitez supprimer un |
belaran@999 | 4280 fichier. Au début du développement de Mercurial, celui ci vous |
belaran@999 | 4281 laissait pourtant supprimer un fichier sans soucis ; Mercurial vous |
belaran@999 | 4282 aurait automatiquement informé de l'absence du fichier lorsque vous |
belaran@999 | 4283 auriez lancé un <command role="hg-cmd" moreinfo="none">hg commit</command> et arrêté |
belaran@999 | 4284 de le suivre. En pratique, ceci a montré qu'il était trop facile de |
belaran@999 | 4285 supprimer accidentellement un fichier sans le remarquer.</para> |
belaran@999 | 4286 </sect2> |
belaran@999 | 4287 |
belaran@999 | 4288 <sect2> |
belaran@999 | 4289 <title>Raccourci utile—ajouter et supprimer des fichiers en une |
belaran@999 | 4290 seule étape.</title> |
belaran@999 | 4291 |
belaran@999 | 4292 <para id="x_1ba">Mercurial offre une commande combinée, <command role="hg-cmd" moreinfo="none">hg addremove</command>, qui ajoute les fichiers non |
belaran@999 | 4293 suivis et marque les fichiers manquants comme supprimés.</para> |
belaran@999 | 4294 |
belaran@999 | 4295 <!-- BEGIN daily.files.addremove --> |
belaran@999 | 4296 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init addremove-example</userinput> |
belaran@999 | 4297 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd addremove-example</userinput> |
belaran@999 | 4298 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 4299 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b</userinput> |
belaran@999 | 4300 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg addremove</userinput> |
belaran@999 | 4301 adding a |
belaran@999 | 4302 adding b |
belaran@999 | 4303 </screen> |
belaran@999 | 4304 <!-- END daily.files.addremove --> |
belaran@999 | 4305 |
belaran@999 | 4306 |
belaran@999 | 4307 <para id="x_1bb">La commande <command role="hg-cmd" moreinfo="none">hg commit</command> |
belaran@999 | 4308 fournit aussi une option <option role="hg-opt-commit">-A</option> qui |
belaran@999 | 4309 exécute le même ajouter-et-supprimer, immédiatement suivi d'un |
belaran@999 | 4310 commit.</para> |
belaran@999 | 4311 |
belaran@999 | 4312 <!-- BEGIN daily.files.commit-addremove --> |
belaran@999 | 4313 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo c > c</userinput> |
belaran@999 | 4314 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Commit with addremove'</userinput> |
belaran@999 | 4315 adding c |
belaran@999 | 4316 </screen> |
belaran@999 | 4317 <!-- END daily.files.commit-addremove --> |
belaran@999 | 4318 |
belaran@999 | 4319 |
belaran@999 | 4320 </sect2> |
belaran@999 | 4321 </sect1> |
belaran@999 | 4322 |
belaran@999 | 4323 <sect1 id="chap:daily.copy"> |
belaran@999 | 4324 <title>Copier des fichiers</title> |
belaran@999 | 4325 |
belaran@999 | 4326 <para id="x_1bc">Mercurial fournit une commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4327 copy</command> qui vous permet de faire une nouvelle copie d'un |
belaran@999 | 4328 fichier. Lorsque vous copiez un fichier en utilisant cette commande, |
belaran@999 | 4329 Mercurial crée un enregistrement du fait que ce nouveau fichier est une |
belaran@999 | 4330 copie du fichier originel. Il traite ces fichiers copiés spécialement |
belaran@999 | 4331 lorsque vous fusionnez (merge) votre travail avec quelqu'un |
belaran@999 | 4332 d'autre.</para> |
belaran@999 | 4333 |
belaran@999 | 4334 <sect2> |
belaran@999 | 4335 <title>Les résultats d'une copie durant une fusion (merge)</title> |
belaran@999 | 4336 |
belaran@999 | 4337 <para id="x_1bd">Ce qu'il se passe durant une fusion (merge) est que |
belaran@999 | 4338 les changements <quote>suivent</quote> une copie. Pour illustrer ce |
belaran@999 | 4339 que cela veut dire de la meilleure façon, créons un exemple. Nous |
belaran@999 | 4340 allons commencer avec le mini dépôt usuel qui contient un simple |
belaran@999 | 4341 fichier.</para> |
belaran@999 | 4342 |
belaran@999 | 4343 <!-- BEGIN daily.copy.init --> |
belaran@999 | 4344 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init my-copy</userinput> |
belaran@999 | 4345 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput> |
belaran@999 | 4346 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo line > file</userinput> |
belaran@999 | 4347 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file</userinput> |
belaran@999 | 4348 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Added a file'</userinput> |
belaran@999 | 4349 </screen> |
belaran@999 | 4350 <!-- END daily.copy.init --> |
belaran@999 | 4351 |
belaran@999 | 4352 |
belaran@999 | 4353 <para id="x_1be">Nous devons faire du travail en parallèle, ainsi, |
belaran@999 | 4354 nous aurons quelque chose à fusionner (merge). Donc clonons notre |
belaran@999 | 4355 dépôt.</para> |
belaran@999 | 4356 |
belaran@999 | 4357 <!-- BEGIN daily.copy.clone --> |
belaran@999 | 4358 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 4359 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone my-copy your-copy</userinput> |
belaran@999 | 4360 updating working directory |
belaran@999 | 4361 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4362 </screen> |
belaran@999 | 4363 <!-- END daily.copy.clone --> |
belaran@999 | 4364 |
belaran@999 | 4365 |
belaran@999 | 4366 <para id="x_1bf">De retour dans notre dépôt initial, utilisons la |
belaran@999 | 4367 commande <command role="hg-cmd" moreinfo="none">hg copy</command> pour faire une |
belaran@999 | 4368 copie du premier fichier que nous avons créé.</para> |
belaran@999 | 4369 |
belaran@999 | 4370 <!-- BEGIN daily.copy.copy --> |
belaran@999 | 4371 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-copy</userinput> |
belaran@999 | 4372 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput> |
belaran@999 | 4373 </screen> |
belaran@999 | 4374 <!-- END daily.copy.copy --> |
belaran@999 | 4375 |
belaran@999 | 4376 |
belaran@999 | 4377 <para id="x_1c0">Si nous regardons ensuite à la sortie de la commande |
belaran@999 | 4378 <command role="hg-cmd" moreinfo="none">hg status</command>, les fichiers copiés |
belaran@999 | 4379 ont l'air de fichiers normalement ajoutés.</para> |
belaran@999 | 4380 |
belaran@999 | 4381 <!-- BEGIN daily.copy.status --> |
belaran@999 | 4382 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4383 A new-file |
belaran@999 | 4384 </screen> |
belaran@999 | 4385 <!-- END daily.copy.status --> |
belaran@999 | 4386 |
belaran@999 | 4387 |
belaran@999 | 4388 <para id="x_1c1">Mais si nous passons l'option <option role="hg-opt-status">-C</option> à <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4389 status</command>, il affiche une autre ligne de sortie : il s'agit |
belaran@999 | 4390 du fichier <emphasis>source</emphasis> pour notre copie.</para> |
belaran@999 | 4391 |
belaran@999 | 4392 <!-- BEGIN daily.copy.status-copy --> |
belaran@999 | 4393 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput> |
belaran@999 | 4394 A new-file |
belaran@999 | 4395 file |
belaran@999 | 4396 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Copied file'</userinput> |
belaran@999 | 4397 </screen> |
belaran@999 | 4398 <!-- END daily.copy.status-copy --> |
belaran@999 | 4399 |
belaran@999 | 4400 |
belaran@999 | 4401 <para id="x_1c2">Maintenant, de retour dans le dépôt que nous avons |
belaran@999 | 4402 cloné, créons un changement en parallèle. Nous allons ajouter une |
belaran@999 | 4403 ligne de contenu au fichier original qui a été créé.</para> |
belaran@999 | 4404 |
belaran@999 | 4405 <!-- BEGIN daily.copy.other --> |
belaran@999 | 4406 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../your-copy</userinput> |
belaran@999 | 4407 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'new contents' >> file</userinput> |
belaran@999 | 4408 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Changed file'</userinput> |
belaran@999 | 4409 </screen> |
belaran@999 | 4410 <!-- END daily.copy.other --> |
belaran@999 | 4411 |
belaran@999 | 4412 |
belaran@999 | 4413 <para id="x_1c3">Nous avons alors un fichier <filename moreinfo="none">file</filename> |
belaran@999 | 4414 modifié dans ce dépôt. Lorsque nous récupérons (pull) les changements |
belaran@999 | 4415 depuis le premier répertoire et fusionnons (merge) les deux "heads", |
belaran@999 | 4416 Mercurial propagera les changements que nous avons faits localement |
belaran@999 | 4417 au fichier <filename moreinfo="none">file</filename> dans sa copie |
belaran@999 | 4418 <filename moreinfo="none">new-file</filename>.</para> |
belaran@999 | 4419 |
belaran@999 | 4420 <!-- BEGIN daily.copy.merge --> |
belaran@999 | 4421 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../my-copy</userinput> |
belaran@999 | 4422 pulling from ../my-copy |
belaran@999 | 4423 searching for changes |
belaran@999 | 4424 adding changesets |
belaran@999 | 4425 adding manifests |
belaran@999 | 4426 adding file changes |
belaran@999 | 4427 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 4428 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 4429 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 4430 merging file and new-file to new-file |
belaran@999 | 4431 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4432 (branch merge, don't forget to commit) |
belaran@999 | 4433 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat new-file</userinput> |
belaran@999 | 4434 line |
belaran@999 | 4435 new contents |
belaran@999 | 4436 </screen> |
belaran@999 | 4437 <!-- END daily.copy.merge --> |
belaran@999 | 4438 |
belaran@999 | 4439 |
belaran@999 | 4440 </sect2> |
belaran@999 | 4441 <sect2 id="sec:daily:why-copy"> |
belaran@999 | 4442 <title>Pourquoi est-ce que les changements devraient suivre les copies |
belaran@999 | 4443 ?</title> |
belaran@999 | 4444 |
belaran@999 | 4445 <para id="x_1c4">Ce comportement—des changements d'un fichiers |
belaran@999 | 4446 qui se propagent aux copies de ce fichier—peut sembler |
belaran@999 | 4447 ésotérique, mais, dans la plupart des cas, c'est hautement |
belaran@999 | 4448 désirable.</para> |
belaran@999 | 4449 |
belaran@999 | 4450 <para id="x_1c5">Pour commencer, souvenez vous que cette propagation |
belaran@999 | 4451 a lieue <emphasis>seulement</emphasis> lors des fusions (merge). |
belaran@999 | 4452 Donc, si vous faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur |
belaran@999 | 4453 un fichier, et par la suite modifiez le fichier original durant le |
belaran@999 | 4454 cours normal de votre travail, rien n'a lieu.</para> |
belaran@999 | 4455 |
belaran@999 | 4456 <para id="x_1c6">La deuxième chose à savoir c'est que les modifications |
belaran@999 | 4457 ne se propageront à travers une copie que si le changeset à partir |
belaran@999 | 4458 duquel vous faites une fusion (merge) <emphasis>n'a pas encore |
belaran@999 | 4459 vu</emphasis> la copie.</para> |
belaran@999 | 4460 |
belaran@999 | 4461 <para id="x_1c7">La raison pour laquelle Mercurial fait ainsi est une |
belaran@999 | 4462 règle. Imaginons que je corrige un important bug dans un fichier source |
belaran@999 | 4463 et que je commit mes changements. Pendant ce temps, vous avez décidé de |
belaran@999 | 4464 faire un <command role="hg-cmd" moreinfo="none">hg copy</command> du fichier dans |
belaran@999 | 4465 votre dépôt, sans rien savoir au sujet du bug ou à propos de la |
belaran@999 | 4466 correction. Vous avez alors commencé à "hacker" sur votre copie du |
belaran@999 | 4467 fichier.</para> |
belaran@999 | 4468 |
belaran@999 | 4469 <para id="x_1c8">Si vous aviez récupéré (pull) et fusionné (merge) mes |
belaran@999 | 4470 changements, et que Mercurial <emphasis>n'avait pas</emphasis> |
belaran@999 | 4471 propagé les changements à travers les copies, votre nouveau fichier |
belaran@999 | 4472 source contiendrait maintenant le bug, et à moins que vous ne sachiez |
belaran@999 | 4473 qu'il faille propager la correction du bug à la main, le bug aurait |
belaran@999 | 4474 <emphasis>subsisté</emphasis> dans votre copie du fichier.</para> |
belaran@999 | 4475 |
belaran@999 | 4476 <para id="x_1c9">En propageant automatiquement les changements qui |
belaran@999 | 4477 fixent les bugs à partir du fichier original vers les copies, |
belaran@999 | 4478 Mercurial prévient ce type de problèmes. A ma connaissance, Mercurial |
belaran@999 | 4479 est le <emphasis>seul</emphasis> système de gestion de révisions qui |
belaran@999 | 4480 propage les changements à travers les copies comme ceci.</para> |
belaran@999 | 4481 |
belaran@999 | 4482 <para id="x_1ca">Une fois que votre historique des changements a un |
belaran@999 | 4483 enregistrement concernant une copie et qu'une fusion postérieure a |
belaran@999 | 4484 eu lieue, il n'y a d'habitude pas d'autre besoin de propager les |
belaran@999 | 4485 changements du fichier originel vers le fichier copié. C'est pourquoi |
belaran@999 | 4486 Mercurial ne propage les changements à travers les copies qu'à la |
belaran@999 | 4487 première fusion, et pas d'avantage.</para> |
belaran@999 | 4488 </sect2> |
belaran@999 | 4489 |
belaran@999 | 4490 <sect2> |
belaran@999 | 4491 <title>Comment faire des changements qui <emphasis>ne</emphasis> |
belaran@999 | 4492 suivent <emphasis>pas</emphasis> une copie</title> |
belaran@999 | 4493 |
belaran@999 | 4494 <para id="x_1cb">Si pour une raison ou une autre, vous décidez que |
belaran@999 | 4495 cette fonctionnalité de propager automatiquement les changements à |
belaran@999 | 4496 travers les copies n'est pas pour vous, utilisez simplement la |
belaran@999 | 4497 commande normale de copie de votre système (sur les systèmes de type |
belaran@999 | 4498 Unix, il s'agit de <command moreinfo="none">cp</command>) pour faire une copie d'un |
belaran@999 | 4499 fichier. Utilisez ensuite <command role="hg-cmd" moreinfo="none">hg add</command> |
belaran@999 | 4500 pour ajouter les nouveaux fichiers à la main. Cependant, avant d'en |
belaran@999 | 4501 faire ainsi, relisez <xref linkend="sec:daily:why-copy"/>, et faites |
belaran@999 | 4502 un choix en connaissance de cause comme quoi cette fonctionnalité |
belaran@999 | 4503 n'est pas appropriée à votre cas spécifique.</para> |
belaran@999 | 4504 |
belaran@999 | 4505 </sect2> |
belaran@999 | 4506 <sect2> |
belaran@999 | 4507 <title>Comportement de la commande <command role="hg-cmd" moreinfo="none">hg copy</command></title> |
belaran@999 | 4508 |
belaran@999 | 4509 <para id="x_1cc">Lorsque vous utilisez la commande <command role="hg-cmd" moreinfo="none">hg copy</command>, Mercurial crée une copie de chaque |
belaran@999 | 4510 fichier source tel qu'il est actuellement dans le répertoire de |
belaran@999 | 4511 travail. Cela signifie que si vous effectuez des modifications sur un |
belaran@999 | 4512 fichier, puis faites un <command role="hg-cmd" moreinfo="none">hg copy</command> sur |
belaran@999 | 4513 celui-ci sans avoir au préalable committé ces changements, la nouvelle |
belaran@999 | 4514 copie contiendra aussi les modifications que vous avez fait jusqu'à |
belaran@999 | 4515 ce point. (Je trouve ce comportement quelque peu contre intuitif, |
belaran@999 | 4516 c'est pourquoi j'en fais mention ici.)</para> |
belaran@999 | 4517 <!-- Vérifier que je n'ai pas fait de contre sens en relisant la |
belaran@999 | 4518 version anglaise, ce que je comprend ici me paraît un peu bizarre --> |
belaran@999 | 4519 |
belaran@999 | 4520 <para id="x_1cd">La commande <command role="hg-cmd" moreinfo="none">hg copy</command> |
belaran@999 | 4521 agit comme la commande Unix <command moreinfo="none">cp</command> (vous pouvez |
belaran@999 | 4522 utilisez l'alias <command role="hg-cmd" moreinfo="none">hg cp</command> si vous |
belaran@999 | 4523 préférez). Nous devons lui donner deux ou plus arguments où le |
belaran@999 | 4524 dernier est considéré comme la <emphasis>destination</emphasis>, et |
belaran@999 | 4525 les autres comme les <emphasis>sources</emphasis>.</para> |
belaran@999 | 4526 |
belaran@999 | 4527 <para id="x_685">Si vous passez à <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4528 copy</command> un seul fichier source, et que la destination |
belaran@999 | 4529 n'existe pas, ceci créera un nouveau fichier avec ce nom.</para> |
belaran@999 | 4530 |
belaran@999 | 4531 <!-- BEGIN daily.copy.simple --> |
belaran@999 | 4532 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir k</userinput> |
belaran@999 | 4533 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a k</userinput> |
belaran@999 | 4534 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls k</userinput> |
belaran@999 | 4535 a |
belaran@999 | 4536 </screen> |
belaran@999 | 4537 <!-- END daily.copy.simple --> |
belaran@999 | 4538 |
belaran@999 | 4539 |
belaran@999 | 4540 <para id="x_1ce">Si la destination est un répertoire, Mercurial copie |
belaran@999 | 4541 les sources dans ce répertoire.</para> |
belaran@999 | 4542 |
belaran@999 | 4543 <!-- BEGIN daily.copy.dir-dest --> |
belaran@999 | 4544 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir d</userinput> |
belaran@999 | 4545 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy a b d</userinput> |
belaran@999 | 4546 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls d</userinput> |
belaran@999 | 4547 a b |
belaran@999 | 4548 </screen> |
belaran@999 | 4549 <!-- END daily.copy.dir-dest --> |
belaran@999 | 4550 |
belaran@999 | 4551 |
belaran@999 | 4552 <para id="x_1cf">La copie de répertoire est récursive et préserve la |
belaran@999 | 4553 structure du répertoire source.</para> |
belaran@999 | 4554 |
belaran@999 | 4555 <!-- BEGIN daily.copy.dir-src --> |
belaran@999 | 4556 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z e</userinput> |
belaran@999 | 4557 copying z/a/c to e/a/c |
belaran@999 | 4558 </screen> |
belaran@999 | 4559 <!-- END daily.copy.dir-src --> |
belaran@999 | 4560 |
belaran@999 | 4561 |
belaran@999 | 4562 <para id="x_1d0">Si la source et la destination sont tous deux des |
belaran@999 | 4563 répertoires, l'arborescence de la source est recréée dans le |
belaran@999 | 4564 répertoire destination.</para> |
belaran@999 | 4565 |
belaran@999 | 4566 <!-- BEGIN daily.copy.dir-src-dest --> |
belaran@999 | 4567 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy z d</userinput> |
belaran@999 | 4568 copying z/a/c to d/z/a/c |
belaran@999 | 4569 </screen> |
belaran@999 | 4570 <!-- END daily.copy.dir-src-dest --> |
belaran@999 | 4571 |
belaran@999 | 4572 |
belaran@999 | 4573 <para id="x_1d1">Comme avec la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4574 remove</command>, si vous copiez un fichier manuellement et voulez |
belaran@999 | 4575 que Mercurial sache qu'il s'agit d'une copie, utilisez simplement |
belaran@999 | 4576 l'option <option role="hg-opt-copy">--after</option> avec <command role="hg-cmd" moreinfo="none">hg copy</command>.</para> |
belaran@999 | 4577 |
belaran@999 | 4578 <!-- BEGIN daily.copy.after --> |
belaran@999 | 4579 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cp a n</userinput> |
belaran@999 | 4580 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy --after a n</userinput> |
belaran@999 | 4581 </screen> |
belaran@999 | 4582 <!-- END daily.copy.after --> |
belaran@999 | 4583 |
belaran@999 | 4584 </sect2> |
belaran@999 | 4585 </sect1> |
belaran@999 | 4586 |
belaran@999 | 4587 <sect1> |
belaran@999 | 4588 <title>Renommer les fichiers</title> |
belaran@999 | 4589 |
belaran@999 | 4590 <para id="x_1d2">Il est plus commun d'avoir besoin de renommer un |
belaran@999 | 4591 fichier que d'en faire une copie. La raison pour laquelle j'ai discuté |
belaran@999 | 4592 de la commande <command role="hg-cmd" moreinfo="none">hg copy</command> avant de parler |
belaran@999 | 4593 de renommage des fichiers est que Mercurial traite les renommages |
belaran@999 | 4594 essentiellement comme une copie. Ainsi, savoir comment Mercurial traite |
belaran@999 | 4595 les copies de fichiers vous informe sur ce que vous êtes en droit |
belaran@999 | 4596 d'attendre lorsque vous renommez un fichier.</para> |
belaran@999 | 4597 |
belaran@999 | 4598 <para id="x_1d3">Lorsque vous utilisez la commande <command role="hg-cmd" moreinfo="none">hg rename</command>, Mercurial crée une copie de tous |
belaran@999 | 4599 les fichiers sources, les supprime et marque ces fichiers comme étant |
belaran@999 | 4600 supprimés.</para> |
belaran@999 | 4601 |
belaran@999 | 4602 <!-- BEGIN daily.rename.rename --> |
belaran@999 | 4603 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput> |
belaran@999 | 4604 </screen> |
belaran@999 | 4605 <!-- END daily.rename.rename --> |
belaran@999 | 4606 |
belaran@999 | 4607 |
belaran@999 | 4608 <para id="x_1d4">La commande <command role="hg-cmd" moreinfo="none">hg status</command> |
belaran@999 | 4609 montre les nouveaux fichiers comme ajoutés et les fichiers originaux |
belaran@999 | 4610 comme supprimés.</para> |
belaran@999 | 4611 |
belaran@999 | 4612 <!-- BEGIN daily.rename.status --> |
belaran@999 | 4613 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 4614 A b |
belaran@999 | 4615 R a |
belaran@999 | 4616 </screen> |
belaran@999 | 4617 <!-- END daily.rename.status --> |
belaran@999 | 4618 |
belaran@999 | 4619 |
belaran@999 | 4620 <para id="x_1d5">A cause du <command role="hg-cmd" moreinfo="none">hg copy</command>, |
belaran@999 | 4621 nous devons utiliser l'option <option role="hg-opt-status">-C</option> |
belaran@999 | 4622 pour la commande <command role="hg-cmd" moreinfo="none">hg status</command> afin |
belaran@999 | 4623 d'observer que le fichier ajouté est bien suivi par Mercurial comme |
belaran@999 | 4624 étant une copie de l'original maintenant supprimé.</para> |
belaran@999 | 4625 |
belaran@999 | 4626 <!-- BEGIN daily.rename.status-copy --> |
belaran@999 | 4627 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -C</userinput> |
belaran@999 | 4628 A b |
belaran@999 | 4629 a |
belaran@999 | 4630 R a |
belaran@999 | 4631 </screen> |
belaran@999 | 4632 <!-- END daily.rename.status-copy --> |
belaran@999 | 4633 |
belaran@999 | 4634 |
belaran@999 | 4635 <para id="x_1d6">Comme avec <command role="hg-cmd" moreinfo="none">hg remove</command> et |
belaran@999 | 4636 <command role="hg-cmd" moreinfo="none">hg copy</command>, vous pouvez informer |
belaran@999 | 4637 Mercurial au sujet d'un renommage après coup en utilisant l'option |
belaran@999 | 4638 <option role="hg-opt-rename">--after</option>. Dans le plus grand |
belaran@999 | 4639 respect, le comportement de la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4640 rename</command>, et les options qu'il accepte sont similaires à la |
belaran@999 | 4641 commande <command role="hg-cmd" moreinfo="none">hg copy</command>.</para> |
belaran@999 | 4642 |
belaran@999 | 4643 <para id="x_686">Si vous êtes familier avec la ligne de commande Unix, |
belaran@999 | 4644 vous serez heureux d'apprendre que la commande <command role="hg-cmd" moreinfo="none">hg rename</command> peut être invoquée par <command role="hg-cmd" moreinfo="none">hg mv</command>.</para> |
belaran@999 | 4645 |
belaran@999 | 4646 <sect2> |
belaran@999 | 4647 <title>Renommer les fichiers et fusionner (merge) les changements</title> |
belaran@999 | 4648 |
belaran@999 | 4649 <para id="x_1d7">Puise que le "rename" de Mercurial est implanté comme un |
belaran@999 | 4650 "copy-and-remove", la même propagation des changements a lieue après |
belaran@999 | 4651 un "rename" qu'après un "copy" lorsque vous fusionnez (merge).</para> |
belaran@999 | 4652 |
belaran@999 | 4653 <para id="x_1d8">Si je modifie un fichier et que vous le renommez, si |
belaran@999 | 4654 ensuite nous fusionnons nos changements respectifs, mes modifications |
belaran@999 | 4655 sur le fichier sous son nom originel seront propagés vers le même |
belaran@999 | 4656 fichier sous son nouveau nom. (C'est quelque chose que vous pourriez |
belaran@999 | 4657 espérer voir <quote>fonctionner simplement</quote>, mais tous les |
belaran@999 | 4658 systèmes de gestion de version ne le font pas.)</para> |
belaran@999 | 4659 |
belaran@999 | 4660 <para id="x_1d9">Tandis qu'avoir des changements qui suivent une copie |
belaran@999 | 4661 est une fonctionnalité où vous hocheriez sûrement la tête en disant |
belaran@999 | 4662 <quote>oui, cela pourrait être utile</quote>, il est clair que les |
belaran@999 | 4663 voir suivre un renommage est définitivement important. Sans cette |
belaran@999 | 4664 aptitude, il serait vraiment trop facile d'avoir des changements |
belaran@999 | 4665 qui deviennent orphelins lorsque des fichiers sont renommés.</para> |
belaran@999 | 4666 </sect2> |
belaran@999 | 4667 |
belaran@999 | 4668 <sect2> |
belaran@999 | 4669 <title>Renommages divergeants et fusion (merge)</title> |
belaran@999 | 4670 |
belaran@999 | 4671 <para id="x_1da">Le cas de noms divergeants a lieu lorsque deux |
belaran@999 | 4672 développeurs commencent avec un fichier—appelons le |
belaran@999 | 4673 <filename moreinfo="none">foo</filename>—dans leurs dépôts respectifs.</para> |
belaran@999 | 4674 |
belaran@999 | 4675 <!-- BEGIN rename.divergent.clone --> |
belaran@999 | 4676 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig anne</userinput> |
belaran@999 | 4677 updating working directory |
belaran@999 | 4678 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4679 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone orig bob</userinput> |
belaran@999 | 4680 updating working directory |
belaran@999 | 4681 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4682 </screen> |
belaran@999 | 4683 <!-- END rename.divergent.clone --> |
belaran@999 | 4684 |
belaran@999 | 4685 |
belaran@999 | 4686 <para id="x_1db">Anne renomme le fichier en |
belaran@999 | 4687 <filename moreinfo="none">bar</filename>.</para> |
belaran@999 | 4688 |
belaran@999 | 4689 <!-- BEGIN rename.divergent.rename.anne --> |
belaran@999 | 4690 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd anne</userinput> |
belaran@999 | 4691 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename foo bar</userinput> |
belaran@999 | 4692 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to bar'</userinput> |
belaran@999 | 4693 </screen> |
belaran@999 | 4694 <!-- END rename.divergent.rename.anne --> |
belaran@999 | 4695 |
belaran@999 | 4696 |
belaran@999 | 4697 <para id="x_1dc">Pendant ce temps, Bob le renomme en |
belaran@999 | 4698 <filename moreinfo="none">quux</filename>. (Souvenez vous que <command role="hg-cmd" moreinfo="none">hg mv</command> est un alias pour <command role="hg-cmd" moreinfo="none">hg rename</command>.)</para> |
belaran@999 | 4699 |
belaran@999 | 4700 <!-- BEGIN rename.divergent.rename.bob --> |
belaran@999 | 4701 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../bob</userinput> |
belaran@999 | 4702 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg mv foo quux</userinput> |
belaran@999 | 4703 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m 'Rename foo to quux'</userinput> |
belaran@999 | 4704 </screen> |
belaran@999 | 4705 <!-- END rename.divergent.rename.bob --> |
belaran@999 | 4706 |
belaran@999 | 4707 |
belaran@999 | 4708 <para id="x_1dd">J'aime à penser qu'il s'agit d'un conflit puisque |
belaran@999 | 4709 chaque développeur a exprimé différentes intentions au sujet de ce |
belaran@999 | 4710 que le nom de ce fichier aurait du être.</para> |
belaran@999 | 4711 |
belaran@999 | 4712 <para id="x_1de">Que pensez vous qu'il devrait se produire lorsqu'ils |
belaran@999 | 4713 fusionnent (merge) leurs travaux ? Le comportement actuel de |
belaran@999 | 4714 Mercurial est qu'il préserve toujours les <emphasis>deux</emphasis> |
belaran@999 | 4715 noms lorsqu'il fusionne (merge) des changesets qui contiennent des |
belaran@999 | 4716 renommages divergeants.</para> |
belaran@999 | 4717 |
belaran@999 | 4718 <!-- BEGIN rename.divergent.merge --> |
belaran@999 | 4719 <screen format="linespecific"># See http://www.selenic.com/mercurial/bts/issue455 |
belaran@999 | 4720 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../orig</userinput> |
belaran@999 | 4721 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../anne</userinput> |
belaran@999 | 4722 pulling from ../anne |
belaran@999 | 4723 searching for changes |
belaran@999 | 4724 adding changesets |
belaran@999 | 4725 adding manifests |
belaran@999 | 4726 adding file changes |
belaran@999 | 4727 added 1 changesets with 1 changes to 1 files |
belaran@999 | 4728 1 files updated, 0 files merged, 1 files removed, 0 files unresolved |
belaran@999 | 4729 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../bob</userinput> |
belaran@999 | 4730 pulling from ../bob |
belaran@999 | 4731 searching for changes |
belaran@999 | 4732 adding changesets |
belaran@999 | 4733 adding manifests |
belaran@999 | 4734 adding file changes |
belaran@999 | 4735 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 4736 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 4737 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 4738 warning: detected divergent renames of foo to: |
belaran@999 | 4739 bar |
belaran@999 | 4740 quux |
belaran@999 | 4741 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4742 (branch merge, don't forget to commit) |
belaran@999 | 4743 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls</userinput> |
belaran@999 | 4744 bar quux |
belaran@999 | 4745 </screen> |
belaran@999 | 4746 <!-- END rename.divergent.merge --> |
belaran@999 | 4747 |
belaran@999 | 4748 |
belaran@999 | 4749 <para id="x_1df">Remarquez que bien que Mercurial vous avertisse au |
belaran@999 | 4750 sujet de la divergeance des renommages, il vous laisse faire quelque |
belaran@999 | 4751 chose au sujet de la divergeance après la fusion (merge).</para> |
belaran@999 | 4752 </sect2> |
belaran@999 | 4753 |
belaran@999 | 4754 <sect2> |
belaran@999 | 4755 <title>Renommages et fusion convergeants</title> |
belaran@999 | 4756 |
belaran@999 | 4757 <para id="x_1e0">Un autre type de conflit de renommage intervient |
belaran@999 | 4758 lorsque deux personne choisissent de renommer différents fichiers |
belaran@999 | 4759 <emphasis>source</emphasis> vers la même |
belaran@999 | 4760 <emphasis>destination</emphasis>. Dans ce cas, Mercurial exécute la |
belaran@999 | 4761 machinerie normale de fusion (merge) et vous guide vers une |
belaran@999 | 4762 solution convenable.</para> |
belaran@999 | 4763 </sect2> |
belaran@999 | 4764 |
belaran@999 | 4765 <sect2> |
belaran@999 | 4766 <title>Autres cas anguleux relatifs aux noms</title> |
belaran@999 | 4767 |
belaran@999 | 4768 <para id="x_1e1">Mercurial possède un bug de longue date dans lequel il |
belaran@999 | 4769 échoue à traiter une fusion (merge) où un coté a un fichier avec un |
belaran@999 | 4770 nom donné, alors que l'autre coté possède un répertoire avec le même nom. |
belaran@999 | 4771 Ceci est documenté dans l'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue29">issue |
belaran@999 | 4772 29</ulink>.</para> |
belaran@999 | 4773 |
belaran@999 | 4774 <!-- BEGIN issue29.go --> |
belaran@999 | 4775 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init issue29</userinput> |
belaran@999 | 4776 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd issue29</userinput> |
belaran@999 | 4777 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 4778 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Ama</userinput> |
belaran@999 | 4779 adding a |
belaran@999 | 4780 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b</userinput> |
belaran@999 | 4781 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amb</userinput> |
belaran@999 | 4782 adding b |
belaran@999 | 4783 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg up 0</userinput> |
belaran@999 | 4784 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
belaran@999 | 4785 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mkdir b</userinput> |
belaran@999 | 4786 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b/b</userinput> |
belaran@999 | 4787 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -Amc</userinput> |
belaran@999 | 4788 adding b/b |
belaran@999 | 4789 created new head |
belaran@999 | 4790 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 4791 abort: Is a directory: /tmp/issue29vhrzWD/issue29/b |
belaran@999 | 4792 </screen> |
belaran@999 | 4793 <!-- END issue29.go --> |
belaran@999 | 4794 |
belaran@999 | 4795 |
belaran@999 | 4796 </sect2> |
belaran@999 | 4797 </sect1> |
belaran@999 | 4798 |
belaran@999 | 4799 <sect1> |
belaran@999 | 4800 <title>Récupération d'erreurs</title> |
belaran@999 | 4801 |
belaran@999 | 4802 <para id="x_1e2">Mercurial possède certaines commandes utiles qui vont |
belaran@999 | 4803 vous aider à récupérer de certaines erreurs communes.</para> |
belaran@999 | 4804 |
belaran@999 | 4805 <para id="x_1e3">La commande <command role="hg-cmd" moreinfo="none">hg revert</command> |
belaran@999 | 4806 vous permet d'annuler les changements que vous avez faits dans votre |
belaran@999 | 4807 répertoire de travail. Par exemple, si vous faites un <command role="hg-cmd" moreinfo="none">hg add</command> sur un fichier par accident, exécutez |
belaran@999 | 4808 juste <command role="hg-cmd" moreinfo="none">hg revert</command> avec le nom du fichier |
belaran@999 | 4809 que vous avez ajouté et tandis que le fichier ne sera touché d'une |
belaran@999 | 4810 quelconque manière, il ne sera plus suivi comme ajouté par Mercurial. |
belaran@999 | 4811 Vous pouvez aussi utiliser la commande <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4812 revert</command> pour vous débarrasser de modifications erronés |
belaran@999 | 4813 apportées à un fichier.</para> |
belaran@999 | 4814 |
belaran@999 | 4815 <para id="x_1e4">Il est utile de se souvenir que la commande <command role="hg-cmd" moreinfo="none">hg revert</command> est utile pour les modifications |
belaran@999 | 4816 qui n'ont pas encore été committées. Une fois que vous avez committé un |
belaran@999 | 4817 changement, si vous décidez qu'il s'agissait d'une erreur, vous pouvez |
belaran@999 | 4818 toujours faire quelque chose à ce sujet, bien que vos options soient |
belaran@999 | 4819 un peu plus limitées.</para> |
belaran@999 | 4820 |
belaran@999 | 4821 <para id="x_1e5">Pour plus d'informations au sujet de la commande |
belaran@999 | 4822 <command role="hg-cmd" moreinfo="none">hg revert</command>, et des détails sur comment |
belaran@999 | 4823 traiter les modifications que vous avez déjà committées, référez vous à |
belaran@999 | 4824 <xref linkend="chap:undo"/>.</para> |
belaran@999 | 4825 </sect1> |
belaran@999 | 4826 |
belaran@999 | 4827 <sect1> |
belaran@999 | 4828 <title>Traiter avec les fusions (merge) malicieuses</title> |
belaran@999 | 4829 |
belaran@999 | 4830 <para id="x_687">Dans des projets compliqués ou conséquents, il n'est pas |
belaran@999 | 4831 rare qu'une fusion (merge) de deux changesets finisse par une migraine. |
belaran@999 | 4832 Supposez qu'il y ait un gros fichier source qui ait été largement édité de |
belaran@999 | 4833 chaque coté de la fusion (merge) : ceci va inévitablement résulter en |
belaran@999 | 4834 conflits, dont certains peuvent prendre plusieurs essais pour s'en |
belaran@999 | 4835 sortir.</para> |
belaran@999 | 4836 |
belaran@999 | 4837 <para id="x_688">Développons en un cas simple pour voir comment le gérer. |
belaran@999 | 4838 Nous allons commencer avec un dépôt contenant un fichier, et le |
belaran@999 | 4839 cloner deux fois.</para> |
belaran@999 | 4840 |
belaran@999 | 4841 <!-- BEGIN ch04/resolve.init --> |
belaran@999 | 4842 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init conflict</userinput> |
belaran@999 | 4843 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd conflict</userinput> |
belaran@999 | 4844 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first > myfile.txt</userinput> |
belaran@999 | 4845 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -A -m first</userinput> |
belaran@999 | 4846 adding myfile.txt |
belaran@999 | 4847 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 4848 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict left</userinput> |
belaran@999 | 4849 updating working directory |
belaran@999 | 4850 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4851 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone conflict right</userinput> |
belaran@999 | 4852 updating working directory |
belaran@999 | 4853 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4854 </screen> |
belaran@999 | 4855 <!-- END ch04/resolve.init --> |
belaran@999 | 4856 |
belaran@999 | 4857 |
belaran@999 | 4858 <para id="x_689">Dans un des clones, nous allons modifier le fichier |
belaran@999 | 4859 d'une façon.</para> |
belaran@999 | 4860 |
belaran@999 | 4861 <!-- BEGIN ch04/resolve.left --> |
belaran@999 | 4862 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd left</userinput> |
belaran@999 | 4863 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo left >> myfile.txt</userinput> |
belaran@999 | 4864 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m left</userinput> |
belaran@999 | 4865 </screen> |
belaran@999 | 4866 <!-- END ch04/resolve.left --> |
belaran@999 | 4867 |
belaran@999 | 4868 |
belaran@999 | 4869 <para id="x_68a">Dans un autre, nous allons modifier le fichier |
belaran@999 | 4870 différemment.</para> |
belaran@999 | 4871 |
belaran@999 | 4872 <!-- BEGIN ch04/resolve.right --> |
belaran@999 | 4873 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../right</userinput> |
belaran@999 | 4874 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo right >> myfile.txt</userinput> |
belaran@999 | 4875 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg ci -m right</userinput> |
belaran@999 | 4876 </screen> |
belaran@999 | 4877 <!-- END ch04/resolve.right --> |
belaran@999 | 4878 |
belaran@999 | 4879 |
belaran@999 | 4880 <para id="x_68b">Ensuite, nous allons récupérer (pull) chaque ensemble de |
belaran@999 | 4881 changement dans notre dépôt original.</para> |
belaran@999 | 4882 |
belaran@999 | 4883 <!-- BEGIN ch04/resolve.pull --> |
belaran@999 | 4884 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../conflict</userinput> |
belaran@999 | 4885 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../left</userinput> |
belaran@999 | 4886 pulling from ../left |
belaran@999 | 4887 searching for changes |
belaran@999 | 4888 adding changesets |
belaran@999 | 4889 adding manifests |
belaran@999 | 4890 adding file changes |
belaran@999 | 4891 added 1 changesets with 1 changes to 1 files |
belaran@999 | 4892 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 4893 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull -u ../right</userinput> |
belaran@999 | 4894 pulling from ../right |
belaran@999 | 4895 searching for changes |
belaran@999 | 4896 adding changesets |
belaran@999 | 4897 adding manifests |
belaran@999 | 4898 adding file changes |
belaran@999 | 4899 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 4900 not updating, since new heads added |
belaran@999 | 4901 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 4902 </screen> |
belaran@999 | 4903 <!-- END ch04/resolve.pull --> |
belaran@999 | 4904 |
belaran@999 | 4905 |
belaran@999 | 4906 <para id="x_68c">Nous nous attendons à ce que notre dépôt contienne deux |
belaran@999 | 4907 "heads".</para> |
belaran@999 | 4908 |
belaran@999 | 4909 <!-- BEGIN ch04/resolve.heads --> |
belaran@999 | 4910 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> |
belaran@999 | 4911 changeset: 2:85f1afc84c33 |
belaran@999 | 4912 tag: tip |
belaran@999 | 4913 parent: 0:14a820f81f48 |
belaran@999 | 4914 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 4915 date: Sun Aug 16 14:04:51 2009 +0000 |
belaran@999 | 4916 summary: right |
belaran@999 | 4917 |
belaran@999 | 4918 changeset: 1:085ebbf44348 |
belaran@999 | 4919 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 4920 date: Sun Aug 16 14:04:51 2009 +0000 |
belaran@999 | 4921 summary: left |
belaran@999 | 4922 |
belaran@999 | 4923 </screen> |
belaran@999 | 4924 <!-- END ch04/resolve.heads --> |
belaran@999 | 4925 |
belaran@999 | 4926 |
belaran@999 | 4927 <para id="x_68d">Normalement, si nous lançons <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4928 merge</command> à ce point, il nous renverra vers une interface |
belaran@999 | 4929 utilisateur qui nous permettra de résoudre manuellement les éditions |
belaran@999 | 4930 conflictuelles sur le fichier <filename moreinfo="none">myfile.txt</filename>. |
belaran@999 | 4931 Cependant, pour simplifier ici les choses dans la présentation, nous |
belaran@999 | 4932 aimerions plutôt que la fusion (merge) échoue immédiatement. Voici une |
belaran@999 | 4933 façon de le faire.</para> |
belaran@999 | 4934 |
belaran@999 | 4935 <!-- BEGIN ch04/resolve.export --> |
belaran@999 | 4936 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">export HGMERGE=false</userinput> |
belaran@999 | 4937 </screen> |
belaran@999 | 4938 <!-- END ch04/resolve.export --> |
belaran@999 | 4939 |
belaran@999 | 4940 |
belaran@999 | 4941 <para id="x_68e">Nous avons dit au processus de fusion de Mercurial |
belaran@999 | 4942 d'exécuter la commande <command moreinfo="none">false</command> (qui échoue |
belaran@999 | 4943 immédiatement, à la demande) s'il détecte une fusion (merge) qu'il ne |
belaran@999 | 4944 peut pas arranger automatiquement.</para> |
belaran@999 | 4945 |
belaran@999 | 4946 <para id="x_68f">Si nous appelons maintenant <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 4947 merge</command>, il devrait échouer et reporter une erreur.</para> |
belaran@999 | 4948 |
belaran@999 | 4949 <!-- BEGIN ch04/resolve.merge --> |
belaran@999 | 4950 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 4951 merging myfile.txt |
belaran@999 | 4952 merging myfile.txt failed! |
belaran@999 | 4953 0 files updated, 0 files merged, 0 files removed, 1 files unresolved |
belaran@999 | 4954 use 'hg resolve' to retry unresolved file merges or 'hg up --clean' to abandon |
belaran@999 | 4955 </screen> |
belaran@999 | 4956 <!-- END ch04/resolve.merge --> |
belaran@999 | 4957 |
belaran@999 | 4958 |
belaran@999 | 4959 <para id="x_690">Même si nous ne remarquons pas qu'une fusion (merge) a |
belaran@999 | 4960 échoué, Mercurial nous empêchera de committer le résultat d'une fusion |
belaran@999 | 4961 ratée.</para> |
belaran@999 | 4962 |
belaran@999 | 4963 <!-- BEGIN ch04/resolve.cifail --> |
belaran@999 | 4964 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Attempt to commit a failed merge'</userinput> |
belaran@999 | 4965 abort: unresolved merge conflicts (see hg resolve) |
belaran@999 | 4966 </screen> |
belaran@999 | 4967 <!-- END ch04/resolve.cifail --> |
belaran@999 | 4968 |
belaran@999 | 4969 |
belaran@999 | 4970 <para id="x_691">Lorsque <command role="hg-cmd" moreinfo="none">hg commit</command> |
belaran@999 | 4971 échoue dans ce cas, il suggère que nous utilisons la commande peu |
belaran@999 | 4972 connue <command role="hg-cmd" moreinfo="none">hg resolve</command>. Comme d'habitude, |
belaran@999 | 4973 <command role="hg-cmd" moreinfo="none">hg help resolve</command> affichera une aide |
belaran@999 | 4974 sommaire.</para> |
belaran@999 | 4975 |
belaran@999 | 4976 <sect2> |
belaran@999 | 4977 <title>États de résolution des fichiers</title> |
belaran@999 | 4978 <!-- TODO Vérifier traduction : File resolution states --> |
belaran@999 | 4979 |
belaran@999 | 4980 <para id="x_692">Lorsqu'une fusion intervient, la plupart des fichiers |
belaran@999 | 4981 vont, la plupart du temps, rester sans modification. Pour chaque |
belaran@999 | 4982 fichier sur lequel Mercurial doit faire quelque chose, il suit l'état |
belaran@999 | 4983 de celui-ci.</para> |
belaran@999 | 4984 |
belaran@999 | 4985 <itemizedlist> |
belaran@999 | 4986 <listitem><para id="x_693">Un fichier |
belaran@999 | 4987 <quote><emphasis>resolved</emphasis></quote> a été fusionné |
belaran@999 | 4988 (merge) avec succès, que ce soit automatiquement par Mercurial ou |
belaran@999 | 4989 manuellement par une intervention humaine.</para></listitem> |
belaran@999 | 4990 <listitem><para id="x_694">Un fichier |
belaran@999 | 4991 <quote><emphasis>unresolved</emphasis></quote> n'a pas été |
belaran@999 | 4992 fusionné (merge) correctement et a besoin de plus |
belaran@999 | 4993 d'attention.</para> |
belaran@999 | 4994 </listitem> |
belaran@999 | 4995 </itemizedlist> |
belaran@999 | 4996 |
belaran@999 | 4997 <para id="x_695">Si Mercurial voit un fichier |
belaran@999 | 4998 <emphasis>quelconque</emphasis> dans un état |
belaran@999 | 4999 <quote>unresolved</quote> après une fusion (merge), il considère que |
belaran@999 | 5000 la fusion (merge) a échoué. Heureusement, nous n'avons pas à |
belaran@999 | 5001 recommencer la procédure à partir du début.</para> |
belaran@999 | 5002 |
belaran@999 | 5003 <para id="x_696">L'option <option role="hg-opt-resolve">--list</option> |
belaran@999 | 5004 ou <option role="hg-opt-resolve">-l</option> passée à <command role="hg-cmd" moreinfo="none">hg resolve</command> liste l'état de chaque fichier |
belaran@999 | 5005 fusionné (merge).</para> |
belaran@999 | 5006 |
belaran@999 | 5007 <!-- BEGIN ch04/resolve.list --> |
belaran@999 | 5008 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg resolve -l</userinput> |
belaran@999 | 5009 U myfile.txt |
belaran@999 | 5010 </screen> |
belaran@999 | 5011 <!-- END ch04/resolve.list --> |
belaran@999 | 5012 |
belaran@999 | 5013 |
belaran@999 | 5014 <para id="x_697">En sortie de <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 5015 resolve</command>, un fichier "resolved" est marqué avec un |
belaran@999 | 5016 <literal moreinfo="none">R</literal>, alors qu'un fichier "unresolved" est marqué |
belaran@999 | 5017 d'un <literal moreinfo="none">U</literal>. S'il existe un fichier listé avec un |
belaran@999 | 5018 <literal moreinfo="none">U</literal>, nous savons qu'essayer de committer le résultat |
belaran@999 | 5019 de la fusion (merge) échouera.</para> |
belaran@999 | 5020 </sect2> |
belaran@999 | 5021 |
belaran@999 | 5022 <sect2> |
belaran@999 | 5023 <title>Résoudre une fusion de fichier</title> |
belaran@999 | 5024 |
belaran@999 | 5025 <para id="x_698">Nous avons plusieurs options pour changer l'état d'un |
belaran@999 | 5026 fichier de "unresolved" à "resolved". Le plus commun est de relancer |
belaran@999 | 5027 <command role="hg-cmd" moreinfo="none">hg resolve</command>. Si nous passons les noms |
belaran@999 | 5028 des fichiers individuels ou des répertoires, ceci retentera la fusion |
belaran@999 | 5029 de tous les fichiers présents à cet endroit. Nous pouvons aussi |
belaran@999 | 5030 passer l'option <option role="hg-opt-resolve">--all</option> ou |
belaran@999 | 5031 <option role="hg-opt-resolve">-a</option> qui tentera de fusionner |
belaran@999 | 5032 <emphasis>tous</emphasis> les fichiers "unresolved".</para> |
belaran@999 | 5033 |
belaran@999 | 5034 <para id="x_699">Mercurial nous laisse aussi modifier la résolution |
belaran@999 | 5035 d'un fichier directement. Nous pouvons marquer un fichier "resolved" |
belaran@999 | 5036 en utilisant l'option <option role="hg-opt-resolve">--mark</option>, |
belaran@999 | 5037 ou "unresolved" en utilisant l'option <option role="hg-opt-resolve">--unmark</option>. Ceci nous autorise à |
belaran@999 | 5038 nettoyer une fusion particulièrement compliquée à la main, et de |
belaran@999 | 5039 garder un suivi de nos progrès avec chaque fichier pendant que nous |
belaran@999 | 5040 procédons.</para> |
belaran@999 | 5041 </sect2> |
belaran@999 | 5042 </sect1> |
belaran@999 | 5043 |
belaran@999 | 5044 <sect1> |
belaran@999 | 5045 <title>Des "diffs" plus utiles</title> |
belaran@999 | 5046 |
belaran@999 | 5047 <para id="x_6c7">La sortie par défaut de la commande <command role="hg-cmd" moreinfo="none">hg diff</command> est compatible rétrospectivement avec |
belaran@999 | 5048 la commande régulière <command moreinfo="none">diff</command>, mais ceci a quelques |
belaran@999 | 5049 inconvénients.</para> |
belaran@999 | 5050 |
belaran@999 | 5051 <para id="x_6c8">Considérez le cas où nous utilisons <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 5052 rename</command> pour renommer un fichier.</para> |
belaran@999 | 5053 |
belaran@999 | 5054 <!-- BEGIN ch04/diff.rename.basic --> |
belaran@999 | 5055 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rename a b</userinput> |
belaran@999 | 5056 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> |
belaran@999 | 5057 diff -r f5deb7868663 a |
belaran@999 | 5058 --- a/a Sun Aug 16 14:04:49 2009 +0000 |
belaran@999 | 5059 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 |
belaran@999 | 5060 @@ -1,1 +0,0 @@ |
belaran@999 | 5061 -a |
belaran@999 | 5062 diff -r f5deb7868663 b |
belaran@999 | 5063 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
belaran@999 | 5064 +++ b/b Sun Aug 16 14:04:49 2009 +0000 |
belaran@999 | 5065 @@ -0,0 +1,1 @@ |
belaran@999 | 5066 +a |
belaran@999 | 5067 </screen> |
belaran@999 | 5068 <!-- END ch04/diff.rename.basic --> |
belaran@999 | 5069 |
belaran@999 | 5070 |
belaran@999 | 5071 <para id="x_6c9">La sortie de <command role="hg-cmd" moreinfo="none">hg diff</command> |
belaran@999 | 5072 ci-dessus cache le fait que nous avons simplement renommé un fichier. |
belaran@999 | 5073 La commande <command role="hg-cmd" moreinfo="none">hg diff</command> accepte l'option |
belaran@999 | 5074 <option>--git</option> ou <option>-g</option> pour utiliser un nouveau |
belaran@999 | 5075 format de diff qui montre ces informations sous une forme plus |
belaran@999 | 5076 expressive.</para> |
belaran@999 | 5077 |
belaran@999 | 5078 <!-- BEGIN ch04/diff.rename.git --> |
belaran@999 | 5079 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput> |
belaran@999 | 5080 diff --git a/a b/b |
belaran@999 | 5081 rename from a |
belaran@999 | 5082 rename to b |
belaran@999 | 5083 </screen> |
belaran@999 | 5084 <!-- END ch04/diff.rename.git --> |
belaran@999 | 5085 |
belaran@999 | 5086 |
belaran@999 | 5087 <para id="x_6ca">Cette option peut aussi aider avec le cas autrement |
belaran@999 | 5088 confus : un fichier qui apparaît comme étant modifié en accord avec |
belaran@999 | 5089 <command role="hg-cmd" moreinfo="none">hg status</command>, mais où <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien. Cette situation peut |
belaran@999 | 5090 survenir si nous changeons les permissions d'exécution du |
belaran@999 | 5091 fichier.</para> |
belaran@999 | 5092 |
belaran@999 | 5093 <!-- BEGIN ch04/diff.chmod --> |
belaran@999 | 5094 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x a</userinput> |
belaran@999 | 5095 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg st</userinput> |
belaran@999 | 5096 M a |
belaran@999 | 5097 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> |
belaran@999 | 5098 </screen> |
belaran@999 | 5099 <!-- END ch04/diff.chmod --> |
belaran@999 | 5100 |
belaran@999 | 5101 |
belaran@999 | 5102 <para id="x_6cb">La commande normale <command moreinfo="none">diff</command> ne fait pas |
belaran@999 | 5103 attention aux permissions des fichiers, ce qui explique pourquoi |
belaran@999 | 5104 <command role="hg-cmd" moreinfo="none">hg diff</command> n'affiche rien du tout par |
belaran@999 | 5105 défaut. Si nous lui passons l'option <option>-g</option>, ceci nous |
belaran@999 | 5106 informe de ce qu'il s'est vraiment passé.</para> |
belaran@999 | 5107 |
belaran@999 | 5108 <!-- BEGIN ch04/diff.chmod.git --> |
belaran@999 | 5109 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff -g</userinput> |
belaran@999 | 5110 diff --git a/a b/a |
belaran@999 | 5111 old mode 100644 |
belaran@999 | 5112 new mode 100755 |
belaran@999 | 5113 </screen> |
belaran@999 | 5114 <!-- END ch04/diff.chmod.git --> |
belaran@999 | 5115 |
belaran@999 | 5116 </sect1> |
belaran@999 | 5117 |
belaran@999 | 5118 <sect1> |
belaran@999 | 5119 <title>Quels fichiers suivre et lesquels éviter</title> |
belaran@999 | 5120 |
belaran@999 | 5121 <para id="x_6cc">Les systèmes de gestion de révisions sont en général |
belaran@999 | 5122 meilleurs pour gérer les fichiers textes qui sont écrits par les |
belaran@999 | 5123 humains, comme le code source, où les fichiers ne changent pas |
belaran@999 | 5124 énormément d'une révision à l'autre. Certains systèmes de gestion de |
belaran@999 | 5125 révisions centralisés peuvent aussi traiter très convenablement les |
belaran@999 | 5126 fichiers binaires, tels que les images bitmap.</para> |
belaran@999 | 5127 |
belaran@999 | 5128 <para id="x_6cd">Par exemple, une équipe de développement de jeux va |
belaran@999 | 5129 probablement gérer les deux types : ses codes source et tous ses binaires |
belaran@999 | 5130 (ex. données géométriques, textures, schémas de cartes) dans un système |
belaran@999 | 5131 de contrôle de révisions.</para> |
belaran@999 | 5132 <!-- Vérifier la traduction de map layouts que j'ai traduit par schémas |
belaran@999 | 5133 de cartes --> |
belaran@999 | 5134 |
belaran@999 | 5135 <para id="x_6ce">Puisqu'il est d'habitude impossible de fusionner (merge) |
belaran@999 | 5136 deux modifications conflictuelles sur un fichier binaire, les systèmes |
belaran@999 | 5137 de version centralisés offrent souvent un mécanisme de verrou (lock) qui |
belaran@999 | 5138 permet à un utilisateur de dire <quote>Je suis la seule personne qui |
belaran@999 | 5139 peut éditer ce fichier</quote>.</para> |
belaran@999 | 5140 |
belaran@999 | 5141 <para id="x_6cf">En comparaison avec un système centralisé, un système |
belaran@999 | 5142 décentralisé de gestion de révision change certains facteurs qui |
belaran@999 | 5143 guident les décisions sur quels fichiers gérer et comment.</para> |
belaran@999 | 5144 |
belaran@999 | 5145 <para id="x_6d0">Par exemple, un système distribué de gestion de révisions |
belaran@999 | 5146 ne peut pas, par sa nature, offrir un système de véroux (lock) sur les |
belaran@999 | 5147 fichiers. Il n'y a donc pas de mécanisme inclus pour empêcher deux |
belaran@999 | 5148 personnes de faire des modifications conflictuelles sur un fichier |
belaran@999 | 5149 binaire. Si vous avez une équipe où plusieurs personnes peuvent souvent |
belaran@999 | 5150 éditer un fichier binaire, cela ne serait pas une très bonne idée |
belaran@999 | 5151 d'utiliser Mercurial —ou tout autre système distribué de gestion |
belaran@999 | 5152 de révisions—pour gérer ces fichiers.</para> |
belaran@999 | 5153 |
belaran@999 | 5154 <para id="x_6d1">Lorsque vous sauvegardez les modifications sur un |
belaran@999 | 5155 fichier, Mercurial ne sauvegarde d'habitude que les différences entre |
belaran@999 | 5156 la version précédente et la version actuelle d'un fichier. Pour la |
belaran@999 | 5157 plupart des fichiers texte, ceci est très efficace. Cependant, certains |
belaran@999 | 5158 fichiers (en particulier les fichiers binaires) sont construits d'une |
belaran@999 | 5159 façon que même un petit changement sur un contenu logique résulte sur |
belaran@999 | 5160 un changement de la plupart des octets du fichier. Par exemple, les |
belaran@999 | 5161 fichiers compressés sont particulièrement sujets à ce comportement. Si |
belaran@999 | 5162 les différences entre deux versions successives d'un fichier sont |
belaran@999 | 5163 toujours très grandes, Mercurial ne sera pas capable de sauvegarder |
belaran@999 | 5164 l'historique des révisions sur le fichier très efficacement. Ceci peut |
belaran@999 | 5165 affecter aussi bien les besoins pour la sauvegarde locale que le temps |
belaran@999 | 5166 nécessaire à cloner le dépôt.</para> |
belaran@999 | 5167 |
belaran@999 | 5168 <para id="x_6d2">Pour avoir une idée de comment ceci pourrait vous |
belaran@999 | 5169 affecter en pratique, supposez que nous voulions que Mercurial gère des |
belaran@999 | 5170 documents OpenOffice. OpenOffice sauvegarde les documents sur le disque |
belaran@999 | 5171 comme des fichiers compressés zip. Même le fait d'éditer ces fichiers |
belaran@999 | 5172 d'une seule lettre, changera les bits de la quasi totalité du fichier |
belaran@999 | 5173 lorsque vous le sauvegarderez. Maintenant, supposez que ce fichier |
belaran@999 | 5174 fasse une taille de 2Mo. Puisque la plupart du fichier change à chaque |
belaran@999 | 5175 fois que vous sauvegardez, Mercurial aura à sauvegarder tous les 2Mo du |
belaran@999 | 5176 fichier à chaque commit, alors que de votre point de vue, il n'y a |
belaran@999 | 5177 que peu de mots qui changent à chaque fois. Un seul fichier |
belaran@999 | 5178 souvent édité qui n'est pas bien traité par les hypothèses que Mercurial |
belaran@999 | 5179 fait sur les sauvegardes peut facilement avoir un effet colossal sur la |
belaran@999 | 5180 taille du dépôt.</para> |
belaran@999 | 5181 |
belaran@999 | 5182 <para id="x_6d3">Même pire, si vous et quelqu'un d'autre éditez le même |
belaran@999 | 5183 document OpenOffice sur lequel vous travaillez, il n'y a pas de façon |
belaran@999 | 5184 utile pour fusionner votre travail. En fait, il n'y a pas de moyen |
belaran@999 | 5185 utile de montrer que les différences sont faites à partir de votre |
belaran@999 | 5186 vision des modifications.</para> |
belaran@999 | 5187 |
belaran@999 | 5188 <para id="x_6d4">Il y a ainsi quelques recommandations claires sur les |
belaran@999 | 5189 types de fichiers spécifiques avec lesquels faire très |
belaran@999 | 5190 attention.</para> |
belaran@999 | 5191 |
belaran@999 | 5192 <itemizedlist> |
belaran@999 | 5193 <listitem><para id="x_6d5">Les fichier qui sont très gros et |
belaran@999 | 5194 incompressibles, comme les images ISO de CD-ROM, sont, par |
belaran@999 | 5195 construction très gros et les cloner à travers un réseau sera très |
belaran@999 | 5196 long.</para></listitem> |
belaran@999 | 5197 <!-- TODO : Trouver une meilleure traduction pour : ISO CD-ROM images, will by |
belaran@999 | 5198 virtue of sheer size make clones over a network very slow. --> |
belaran@999 | 5199 <listitem><para id="x_6d6">Les fichiers qui changent beaucoup d'une |
belaran@999 | 5200 révision à l'autre peuvent être très chers à sauvegarder si vous |
belaran@999 | 5201 les éditez fréquemment, de même que les conflits entre deux éditions |
belaran@999 | 5202 concurrentes peuvent être difficiles à résoudre.</para> |
belaran@999 | 5203 </listitem> |
belaran@999 | 5204 </itemizedlist> |
belaran@999 | 5205 </sect1> |
belaran@999 | 5206 |
belaran@999 | 5207 <sect1> |
belaran@999 | 5208 <title>Sauvegardes et miroirs</title> |
belaran@999 | 5209 |
belaran@999 | 5210 <para id="x_6d7">Puisque Mercurial maintient une copie complète de |
belaran@999 | 5211 l'historique de chaque clone, toute personne qui utilise Mercurial pour |
belaran@999 | 5212 collaborer à un projet peut potentiellement agir comme une source de |
belaran@999 | 5213 sauvegarde si une catastrophe survenait. Si un dépôt central devient |
belaran@999 | 5214 indisponible, vous pouvez construire un remplaçant en clonant une copie |
belaran@999 | 5215 du dépôt à partir d'un des contributeurs en récupérant (pull) tous les |
belaran@999 | 5216 changements qui n'auraient pas été vus par les autres.</para> |
belaran@999 | 5217 |
belaran@999 | 5218 <para id="x_6d8">Il est simple d'utiliser Mercurial pour construire des |
belaran@999 | 5219 serveurs hors site de sauvegarde et des miroirs distants. Initiez une |
belaran@999 | 5220 tâche périodique (ex. via la commande <command moreinfo="none">cron</command>) sur un |
belaran@999 | 5221 serveur distant pour récupérer (pull) les changements de votre dépôt |
belaran@999 | 5222 distant chaque heure. Ceci sera difficile seulement dans le cas |
belaran@999 | 5223 improbable où le nombre des dépôts maîtres que vous maintenez change |
belaran@999 | 5224 souvent, auquel cas vous aurez besoin de faire un peu de scripting pour |
belaran@999 | 5225 rafraichir la liste des dépôt à sauvegarder.</para> |
belaran@999 | 5226 |
belaran@999 | 5227 <para id="x_6d9">Si vous exécutez des sauvegardes traditionnelles de |
belaran@999 | 5228 votre dépôt maître sur bande ou disque, et que vous voulez sauvegarder |
belaran@999 | 5229 un dépôt nommé <filename moreinfo="none">myrepo</filename>, utilisez la commande |
belaran@999 | 5230 <command moreinfo="none">hg clone -U myrepo myrepo.bak</command> pour créer un clone de |
belaran@999 | 5231 <filename moreinfo="none">myrepo</filename> avant de commencer vos backups. |
belaran@999 | 5232 L'option <option>-U</option> ne crée pas de répertoire de travail après |
belaran@999 | 5233 que le clone soit accompli, puisque ceci serait superflu et ferait que |
belaran@999 | 5234 la sauvegarde prenne plus de temps.</para> |
belaran@999 | 5235 |
belaran@999 | 5236 <para id="x_6da">Si vous voulez ensuite sauvegarder |
belaran@999 | 5237 <filename moreinfo="none">myrepo.bak</filename> au lieu de <filename moreinfo="none">myrepo</filename>, |
belaran@999 | 5238 vous aurez la garantie d'avoir une image (snapshot) consistante de |
belaran@999 | 5239 votre dépôt sur lequel un développeur insomniaque n'enverra (push) pas de |
belaran@999 | 5240 changements en milieu de sauvegarde.</para> |
belaran@999 | 5241 </sect1> |
belaran@999 | 5242 </chapter> |
belaran@999 | 5243 |
belaran@999 | 5244 <!-- |
belaran@999 | 5245 local variables: |
belaran@999 | 5246 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 5247 end: |
belaran@999 | 5248 --> |
belaran@999 | 5249 |
belaran@999 | 5250 <!-- BEGIN ch06 --> |
belaran@999 | 5251 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 5252 |
belaran@999 | 5253 <chapter id="cha:collab"> |
belaran@999 | 5254 <?dbhtml filename="collaborating-with-other-people.html"?> |
belaran@999 | 5255 <title>Collaborating with other people</title> |
belaran@999 | 5256 |
belaran@999 | 5257 <para id="x_44a">As a completely decentralised tool, Mercurial doesn't impose |
belaran@999 | 5258 any policy on how people ought to work with each other. However, |
belaran@999 | 5259 if you're new to distributed revision control, it helps to have |
belaran@999 | 5260 some tools and examples in mind when you're thinking about |
belaran@999 | 5261 possible workflow models.</para> |
belaran@999 | 5262 |
belaran@999 | 5263 <sect1> |
belaran@999 | 5264 <title>Mercurial's web interface</title> |
belaran@999 | 5265 |
belaran@999 | 5266 <para id="x_44b">Mercurial has a powerful web interface that provides several |
belaran@999 | 5267 useful capabilities.</para> |
belaran@999 | 5268 |
belaran@999 | 5269 <para id="x_44c">For interactive use, the web interface lets you browse a |
belaran@999 | 5270 single repository or a collection of repositories. You can view |
belaran@999 | 5271 the history of a repository, examine each change (comments and |
belaran@999 | 5272 diffs), and view the contents of each directory and file. You |
belaran@999 | 5273 can even get a view of history that gives a graphical view of |
belaran@999 | 5274 the relationships between individual changes and merges.</para> |
belaran@999 | 5275 |
belaran@999 | 5276 <para id="x_44d">Also for human consumption, the web interface provides |
belaran@999 | 5277 Atom and RSS feeds of the changes in a repository. This lets you |
belaran@999 | 5278 <quote>subscribe</quote> to a repository using your favorite |
belaran@999 | 5279 feed reader, and be automatically notified of activity in that |
belaran@999 | 5280 repository as soon as it happens. I find this capability much |
belaran@999 | 5281 more convenient than the model of subscribing to a mailing list |
belaran@999 | 5282 to which notifications are sent, as it requires no additional |
belaran@999 | 5283 configuration on the part of whoever is serving the |
belaran@999 | 5284 repository.</para> |
belaran@999 | 5285 |
belaran@999 | 5286 <para id="x_44e">The web interface also lets remote users clone a repository, |
belaran@999 | 5287 pull changes from it, and (when the server is configured to |
belaran@999 | 5288 permit it) push changes back to it. Mercurial's HTTP tunneling |
belaran@999 | 5289 protocol aggressively compresses data, so that it works |
belaran@999 | 5290 efficiently even over low-bandwidth network connections.</para> |
belaran@999 | 5291 |
belaran@999 | 5292 <para id="x_44f">The easiest way to get started with the web interface is to |
belaran@999 | 5293 use your web browser to visit an existing repository, such as |
belaran@999 | 5294 the master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg">http://www.selenic.com/repo/hg</ulink>.</para> |
belaran@999 | 5295 |
belaran@999 | 5296 <para id="x_450">If you're interested in providing a web interface |
belaran@999 | 5297 to your own repositories, there are several good ways to do |
belaran@999 | 5298 this.</para> |
belaran@999 | 5299 |
belaran@999 | 5300 <para id="x_69d">The easiest and fastest way to get started in an informal |
belaran@999 | 5301 environment is to use the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 5302 serve</command> command, which is best suited to short-term |
belaran@999 | 5303 <quote>lightweight</quote> serving. See <xref linkend="sec:collab:serve"/> below for details of how to use |
belaran@999 | 5304 this command.</para> |
belaran@999 | 5305 |
belaran@999 | 5306 <para id="x_69e">For longer-lived repositories that you'd like to |
belaran@999 | 5307 have permanently available, there are several public hosting |
belaran@999 | 5308 services available. Some are free to open source projects, |
belaran@999 | 5309 while others offer paid commercial hosting. An up-to-date list |
belaran@999 | 5310 is available at <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting">http://www.selenic.com/mercurial/wiki/index.cgi/MercurialHosting</ulink>.</para> |
belaran@999 | 5311 |
belaran@999 | 5312 <para id="x_6a0">If you would prefer to host your own repositories, Mercurial |
belaran@999 | 5313 has built-in support for several popular hosting technologies, |
belaran@999 | 5314 most notably CGI (Common Gateway Interface), and WSGI (Web |
belaran@999 | 5315 Services Gateway Interface). See <xref linkend="sec:collab:cgi"/> for details of CGI and WSGI |
belaran@999 | 5316 configuration.</para> |
belaran@999 | 5317 </sect1> |
belaran@999 | 5318 |
belaran@999 | 5319 <sect1> |
belaran@999 | 5320 <title>Collaboration models</title> |
belaran@999 | 5321 |
belaran@999 | 5322 <para id="x_451">With a suitably flexible tool, making decisions about |
belaran@999 | 5323 workflow is much more of a social engineering challenge than a |
belaran@999 | 5324 technical one. Mercurial imposes few limitations on how you can |
belaran@999 | 5325 structure the flow of work in a project, so it's up to you and |
belaran@999 | 5326 your group to set up and live with a model that matches your own |
belaran@999 | 5327 particular needs.</para> |
belaran@999 | 5328 |
belaran@999 | 5329 <sect2> |
belaran@999 | 5330 <title>Factors to keep in mind</title> |
belaran@999 | 5331 |
belaran@999 | 5332 <para id="x_452">The most important aspect of any model that you must keep |
belaran@999 | 5333 in mind is how well it matches the needs and capabilities of |
belaran@999 | 5334 the people who will be using it. This might seem |
belaran@999 | 5335 self-evident; even so, you still can't afford to forget it for |
belaran@999 | 5336 a moment.</para> |
belaran@999 | 5337 |
belaran@999 | 5338 <para id="x_453">I once put together a workflow model that seemed to make |
belaran@999 | 5339 perfect sense to me, but that caused a considerable amount of |
belaran@999 | 5340 consternation and strife within my development team. In spite |
belaran@999 | 5341 of my attempts to explain why we needed a complex set of |
belaran@999 | 5342 branches, and how changes ought to flow between them, a few |
belaran@999 | 5343 team members revolted. Even though they were smart people, |
belaran@999 | 5344 they didn't want to pay attention to the constraints we were |
belaran@999 | 5345 operating under, or face the consequences of those constraints |
belaran@999 | 5346 in the details of the model that I was advocating.</para> |
belaran@999 | 5347 |
belaran@999 | 5348 <para id="x_454">Don't sweep foreseeable social or technical problems under |
belaran@999 | 5349 the rug. Whatever scheme you put into effect, you should plan |
belaran@999 | 5350 for mistakes and problem scenarios. Consider adding automated |
belaran@999 | 5351 machinery to prevent, or quickly recover from, trouble that |
belaran@999 | 5352 you can anticipate. As an example, if you intend to have a |
belaran@999 | 5353 branch with not-for-release changes in it, you'd do well to |
belaran@999 | 5354 think early about the possibility that someone might |
belaran@999 | 5355 accidentally merge those changes into a release branch. You |
belaran@999 | 5356 could avoid this particular problem by writing a hook that |
belaran@999 | 5357 prevents changes from being merged from an inappropriate |
belaran@999 | 5358 branch.</para> |
belaran@999 | 5359 </sect2> |
belaran@999 | 5360 |
belaran@999 | 5361 <sect2> |
belaran@999 | 5362 <title>Informal anarchy</title> |
belaran@999 | 5363 |
belaran@999 | 5364 <para id="x_455">I wouldn't suggest an <quote>anything goes</quote> |
belaran@999 | 5365 approach as something sustainable, but it's a model that's |
belaran@999 | 5366 easy to grasp, and it works perfectly well in a few unusual |
belaran@999 | 5367 situations.</para> |
belaran@999 | 5368 |
belaran@999 | 5369 <para id="x_456">As one example, many projects have a loose-knit group of |
belaran@999 | 5370 collaborators who rarely physically meet each other. Some |
belaran@999 | 5371 groups like to overcome the isolation of working at a distance |
belaran@999 | 5372 by organizing occasional <quote>sprints</quote>. In a sprint, |
belaran@999 | 5373 a number of people get together in a single location (a |
belaran@999 | 5374 company's conference room, a hotel meeting room, that kind of |
belaran@999 | 5375 place) and spend several days more or less locked in there, |
belaran@999 | 5376 hacking intensely on a handful of projects.</para> |
belaran@999 | 5377 |
belaran@999 | 5378 <para id="x_457">A sprint or a hacking session in a coffee shop are the perfect places to use the |
belaran@999 | 5379 <command role="hg-cmd" moreinfo="none">hg serve</command> command, since |
belaran@999 | 5380 <command role="hg-cmd" moreinfo="none">hg serve</command> does not require any |
belaran@999 | 5381 fancy server infrastructure. You can get started with |
belaran@999 | 5382 <command role="hg-cmd" moreinfo="none">hg serve</command> in moments, by |
belaran@999 | 5383 reading <xref linkend="sec:collab:serve"/> below. Then simply |
belaran@999 | 5384 tell the person next to you that you're running a server, send |
belaran@999 | 5385 the URL to them in an instant message, and you immediately |
belaran@999 | 5386 have a quick-turnaround way to work together. They can type |
belaran@999 | 5387 your URL into their web browser and quickly review your |
belaran@999 | 5388 changes; or they can pull a bugfix from you and verify it; or |
belaran@999 | 5389 they can clone a branch containing a new feature and try it |
belaran@999 | 5390 out.</para> |
belaran@999 | 5391 |
belaran@999 | 5392 <para id="x_458">The charm, and the problem, with doing things |
belaran@999 | 5393 in an ad hoc fashion like this is that only people who know |
belaran@999 | 5394 about your changes, and where they are, can see them. Such an |
belaran@999 | 5395 informal approach simply doesn't scale beyond a handful |
belaran@999 | 5396 people, because each individual needs to know about |
belaran@999 | 5397 <emphasis>n</emphasis> different repositories to pull |
belaran@999 | 5398 from.</para> |
belaran@999 | 5399 </sect2> |
belaran@999 | 5400 |
belaran@999 | 5401 <sect2> |
belaran@999 | 5402 <title>A single central repository</title> |
belaran@999 | 5403 |
belaran@999 | 5404 <para id="x_459">For smaller projects migrating from a centralised revision |
belaran@999 | 5405 control tool, perhaps the easiest way to get started is to |
belaran@999 | 5406 have changes flow through a single shared central repository. |
belaran@999 | 5407 This is also the most common <quote>building block</quote> for |
belaran@999 | 5408 more ambitious workflow schemes.</para> |
belaran@999 | 5409 |
belaran@999 | 5410 <para id="x_45a">Contributors start by cloning a copy of this repository. |
belaran@999 | 5411 They can pull changes from it whenever they need to, and some |
belaran@999 | 5412 (perhaps all) developers have permission to push a change back |
belaran@999 | 5413 when they're ready for other people to see it.</para> |
belaran@999 | 5414 |
belaran@999 | 5415 <para id="x_45b">Under this model, it can still often make sense for people |
belaran@999 | 5416 to pull changes directly from each other, without going |
belaran@999 | 5417 through the central repository. Consider a case in which I |
belaran@999 | 5418 have a tentative bug fix, but I am worried that if I were to |
belaran@999 | 5419 publish it to the central repository, it might subsequently |
belaran@999 | 5420 break everyone else's trees as they pull it. To reduce the |
belaran@999 | 5421 potential for damage, I can ask you to clone my repository |
belaran@999 | 5422 into a temporary repository of your own and test it. This |
belaran@999 | 5423 lets us put off publishing the potentially unsafe change until |
belaran@999 | 5424 it has had a little testing.</para> |
belaran@999 | 5425 |
belaran@999 | 5426 <para id="x_45c">If a team is hosting its own repository in this |
belaran@999 | 5427 kind of scenario, people will usually use the |
belaran@999 | 5428 <command moreinfo="none">ssh</command> protocol to securely push changes to |
belaran@999 | 5429 the central repository, as documented in <xref linkend="sec:collab:ssh"/>. It's also usual to publish a |
belaran@999 | 5430 read-only copy of the repository over HTTP, as in |
belaran@999 | 5431 <xref linkend="sec:collab:cgi"/>. Publishing over HTTP |
belaran@999 | 5432 satisfies the needs of people who don't have push access, and |
belaran@999 | 5433 those who want to use web browsers to browse the repository's |
belaran@999 | 5434 history.</para> |
belaran@999 | 5435 </sect2> |
belaran@999 | 5436 |
belaran@999 | 5437 <sect2> |
belaran@999 | 5438 <title>A hosted central repository</title> |
belaran@999 | 5439 |
belaran@999 | 5440 <para id="x_6a1">A wonderful thing about public hosting services like |
belaran@999 | 5441 <ulink url="http://bitbucket.org/">Bitbucket</ulink> is that |
belaran@999 | 5442 not only do they handle the fiddly server configuration |
belaran@999 | 5443 details, such as user accounts, authentication, and secure |
belaran@999 | 5444 wire protocols, they provide additional infrastructure to make |
belaran@999 | 5445 this model work well.</para> |
belaran@999 | 5446 |
belaran@999 | 5447 <para id="x_6a2">For instance, a well-engineered hosting service will let |
belaran@999 | 5448 people clone their own copies of a repository with a single |
belaran@999 | 5449 click. This lets people work in separate spaces and share |
belaran@999 | 5450 their changes when they're ready.</para> |
belaran@999 | 5451 |
belaran@999 | 5452 <para id="x_6a3">In addition, a good hosting service will let people |
belaran@999 | 5453 communicate with each other, for instance to say <quote>there |
belaran@999 | 5454 are changes ready for you to review in this |
belaran@999 | 5455 tree</quote>.</para> |
belaran@999 | 5456 </sect2> |
belaran@999 | 5457 |
belaran@999 | 5458 <sect2> |
belaran@999 | 5459 <title>Working with multiple branches</title> |
belaran@999 | 5460 |
belaran@999 | 5461 <para id="x_45d">Projects of any significant size naturally tend to make |
belaran@999 | 5462 progress on several fronts simultaneously. In the case of |
belaran@999 | 5463 software, it's common for a project to go through periodic |
belaran@999 | 5464 official releases. A release might then go into |
belaran@999 | 5465 <quote>maintenance mode</quote> for a while after its first |
belaran@999 | 5466 publication; maintenance releases tend to contain only bug |
belaran@999 | 5467 fixes, not new features. In parallel with these maintenance |
belaran@999 | 5468 releases, one or more future releases may be under |
belaran@999 | 5469 development. People normally use the word |
belaran@999 | 5470 <quote>branch</quote> to refer to one of these many slightly |
belaran@999 | 5471 different directions in which development is |
belaran@999 | 5472 proceeding.</para> |
belaran@999 | 5473 |
belaran@999 | 5474 <para id="x_45e">Mercurial is particularly well suited to managing a number |
belaran@999 | 5475 of simultaneous, but not identical, branches. Each |
belaran@999 | 5476 <quote>development direction</quote> can live in its own |
belaran@999 | 5477 central repository, and you can merge changes from one to |
belaran@999 | 5478 another as the need arises. Because repositories are |
belaran@999 | 5479 independent of each other, unstable changes in a development |
belaran@999 | 5480 branch will never affect a stable branch unless someone |
belaran@999 | 5481 explicitly merges those changes into the stable branch.</para> |
belaran@999 | 5482 |
belaran@999 | 5483 <para id="x_45f">Here's an example of how this can work in practice. Let's |
belaran@999 | 5484 say you have one <quote>main branch</quote> on a central |
belaran@999 | 5485 server.</para> |
belaran@999 | 5486 |
belaran@999 | 5487 <!-- BEGIN branching.init --> |
belaran@999 | 5488 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init main</userinput> |
belaran@999 | 5489 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main</userinput> |
belaran@999 | 5490 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a boring feature.' > myfile</userinput> |
belaran@999 | 5491 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'We have reached an important milestone!'</userinput> |
belaran@999 | 5492 adding myfile |
belaran@999 | 5493 </screen> |
belaran@999 | 5494 <!-- END branching.init --> |
belaran@999 | 5495 |
belaran@999 | 5496 |
belaran@999 | 5497 <para id="x_460">People clone it, make changes locally, test them, and push |
belaran@999 | 5498 them back.</para> |
belaran@999 | 5499 |
belaran@999 | 5500 <para id="x_461">Once the main branch reaches a release milestone, you can |
belaran@999 | 5501 use the <command role="hg-cmd" moreinfo="none">hg tag</command> command to |
belaran@999 | 5502 give a permanent name to the milestone revision.</para> |
belaran@999 | 5503 |
belaran@999 | 5504 <!-- BEGIN branching.tag --> |
belaran@999 | 5505 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput> |
belaran@999 | 5506 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 5507 changeset: 1:5e447fdaf941 |
belaran@999 | 5508 tag: tip |
belaran@999 | 5509 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 5510 date: Sun Aug 16 14:04:47 2009 +0000 |
belaran@999 | 5511 summary: Added tag v1.0 for changeset 6412b791fd06 |
belaran@999 | 5512 |
belaran@999 | 5513 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> |
belaran@999 | 5514 tip 1:5e447fdaf941 |
belaran@999 | 5515 v1.0 0:6412b791fd06 |
belaran@999 | 5516 </screen> |
belaran@999 | 5517 <!-- END branching.tag --> |
belaran@999 | 5518 |
belaran@999 | 5519 |
belaran@999 | 5520 <para id="x_462">Let's say some ongoing |
belaran@999 | 5521 development occurs on the main branch.</para> |
belaran@999 | 5522 |
belaran@999 | 5523 <!-- BEGIN branching.main --> |
belaran@999 | 5524 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput> |
belaran@999 | 5525 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is exciting and new!' >> myfile</userinput> |
belaran@999 | 5526 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add a new feature'</userinput> |
belaran@999 | 5527 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 5528 This is a boring feature. |
belaran@999 | 5529 This is exciting and new! |
belaran@999 | 5530 </screen> |
belaran@999 | 5531 <!-- END branching.main --> |
belaran@999 | 5532 |
belaran@999 | 5533 |
belaran@999 | 5534 <para id="x_463">Using the tag that was recorded at the milestone, people |
belaran@999 | 5535 who clone that repository at any time in the future can use |
belaran@999 | 5536 <command role="hg-cmd" moreinfo="none">hg update</command> to get a copy of |
belaran@999 | 5537 the working directory exactly as it was when that tagged |
belaran@999 | 5538 revision was committed.</para> |
belaran@999 | 5539 |
belaran@999 | 5540 <!-- BEGIN branching.update --> |
belaran@999 | 5541 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 5542 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -U main main-old</userinput> |
belaran@999 | 5543 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd main-old</userinput> |
belaran@999 | 5544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update v1.0</userinput> |
belaran@999 | 5545 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 5546 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 5547 This is a boring feature. |
belaran@999 | 5548 </screen> |
belaran@999 | 5549 <!-- END branching.update --> |
belaran@999 | 5550 |
belaran@999 | 5551 |
belaran@999 | 5552 <para id="x_464">In addition, immediately after the main branch is tagged, |
belaran@999 | 5553 we can then clone the main branch on the server to a new |
belaran@999 | 5554 <quote>stable</quote> branch, also on the server.</para> |
belaran@999 | 5555 |
belaran@999 | 5556 <!-- BEGIN branching.clone --> |
belaran@999 | 5557 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 5558 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -rv1.0 main stable</userinput> |
belaran@999 | 5559 requesting all changes |
belaran@999 | 5560 adding changesets |
belaran@999 | 5561 adding manifests |
belaran@999 | 5562 adding file changes |
belaran@999 | 5563 added 1 changesets with 1 changes to 1 files |
belaran@999 | 5564 updating working directory |
belaran@999 | 5565 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 5566 </screen> |
belaran@999 | 5567 <!-- END branching.clone --> |
belaran@999 | 5568 |
belaran@999 | 5569 |
belaran@999 | 5570 <para id="x_465">If we need to make a change to the stable |
belaran@999 | 5571 branch, we can then clone <emphasis>that</emphasis> |
belaran@999 | 5572 repository, make our changes, commit, and push our changes |
belaran@999 | 5573 back there.</para> |
belaran@999 | 5574 |
belaran@999 | 5575 <!-- BEGIN branching.stable --> |
belaran@999 | 5576 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone stable stable-fix</userinput> |
belaran@999 | 5577 updating working directory |
belaran@999 | 5578 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 5579 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd stable-fix</userinput> |
belaran@999 | 5580 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This is a fix to a boring feature.' > myfile</userinput> |
belaran@999 | 5581 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Fix a bug'</userinput> |
belaran@999 | 5582 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> |
belaran@999 | 5583 pushing to /tmp/branchingPsTziR/stable |
belaran@999 | 5584 searching for changes |
belaran@999 | 5585 adding changesets |
belaran@999 | 5586 adding manifests |
belaran@999 | 5587 adding file changes |
belaran@999 | 5588 added 1 changesets with 1 changes to 1 files |
belaran@999 | 5589 </screen> |
belaran@999 | 5590 <!-- END branching.stable --> |
belaran@999 | 5591 |
belaran@999 | 5592 |
belaran@999 | 5593 <para id="x_466">Because Mercurial repositories are independent, and |
belaran@999 | 5594 Mercurial doesn't move changes around automatically, the |
belaran@999 | 5595 stable and main branches are <emphasis>isolated</emphasis> |
belaran@999 | 5596 from each other. The changes that we made on the main branch |
belaran@999 | 5597 don't <quote>leak</quote> to the stable branch, and vice |
belaran@999 | 5598 versa.</para> |
belaran@999 | 5599 |
belaran@999 | 5600 <para id="x_467">We'll often want all of our bugfixes on the stable |
belaran@999 | 5601 branch to show up on the main branch, too. Rather than |
belaran@999 | 5602 rewrite a bugfix on the main branch, we can simply pull and |
belaran@999 | 5603 merge changes from the stable to the main branch, and |
belaran@999 | 5604 Mercurial will bring those bugfixes in for us.</para> |
belaran@999 | 5605 |
belaran@999 | 5606 <!-- BEGIN branching.merge --> |
belaran@999 | 5607 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../main</userinput> |
belaran@999 | 5608 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../stable</userinput> |
belaran@999 | 5609 pulling from ../stable |
belaran@999 | 5610 searching for changes |
belaran@999 | 5611 adding changesets |
belaran@999 | 5612 adding manifests |
belaran@999 | 5613 adding file changes |
belaran@999 | 5614 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 5615 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 5616 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 5617 merging myfile |
belaran@999 | 5618 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 5619 (branch merge, don't forget to commit) |
belaran@999 | 5620 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Bring in bugfix from stable branch'</userinput> |
belaran@999 | 5621 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 5622 This is a fix to a boring feature. |
belaran@999 | 5623 This is exciting and new! |
belaran@999 | 5624 </screen> |
belaran@999 | 5625 <!-- END branching.merge --> |
belaran@999 | 5626 |
belaran@999 | 5627 |
belaran@999 | 5628 <para id="x_468">The main branch will still contain changes that |
belaran@999 | 5629 are not on the stable branch, but it will also contain all of |
belaran@999 | 5630 the bugfixes from the stable branch. The stable branch |
belaran@999 | 5631 remains unaffected by these changes, since changes are only |
belaran@999 | 5632 flowing from the stable to the main branch, and not the other |
belaran@999 | 5633 way.</para> |
belaran@999 | 5634 </sect2> |
belaran@999 | 5635 |
belaran@999 | 5636 <sect2> |
belaran@999 | 5637 <title>Feature branches</title> |
belaran@999 | 5638 |
belaran@999 | 5639 <para id="x_469">For larger projects, an effective way to manage change is |
belaran@999 | 5640 to break up a team into smaller groups. Each group has a |
belaran@999 | 5641 shared branch of its own, cloned from a single |
belaran@999 | 5642 <quote>master</quote> branch used by the entire project. |
belaran@999 | 5643 People working on an individual branch are typically quite |
belaran@999 | 5644 isolated from developments on other branches.</para> |
belaran@999 | 5645 |
belaran@999 | 5646 <figure id="fig:collab:feature-branches" float="0"> |
belaran@999 | 5647 <title>Feature branches</title> |
belaran@999 | 5648 <mediaobject> |
belaran@999 | 5649 <imageobject><imagedata width="100%" fileref="figs/feature-branches.png"/></imageobject> |
belaran@999 | 5650 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 5651 </mediaobject> |
belaran@999 | 5652 </figure> |
belaran@999 | 5653 |
belaran@999 | 5654 <para id="x_46b">When a particular feature is deemed to be in suitable |
belaran@999 | 5655 shape, someone on that feature team pulls and merges from the |
belaran@999 | 5656 master branch into the feature branch, then pushes back up to |
belaran@999 | 5657 the master branch.</para> |
belaran@999 | 5658 </sect2> |
belaran@999 | 5659 |
belaran@999 | 5660 <sect2> |
belaran@999 | 5661 <title>The release train</title> |
belaran@999 | 5662 |
belaran@999 | 5663 <para id="x_46c">Some projects are organized on a <quote>train</quote> |
belaran@999 | 5664 basis: a release is scheduled to happen every few months, and |
belaran@999 | 5665 whatever features are ready when the <quote>train</quote> is |
belaran@999 | 5666 ready to leave are allowed in.</para> |
belaran@999 | 5667 |
belaran@999 | 5668 <para id="x_46d">This model resembles working with feature branches. The |
belaran@999 | 5669 difference is that when a feature branch misses a train, |
belaran@999 | 5670 someone on the feature team pulls and merges the changes that |
belaran@999 | 5671 went out on that train release into the feature branch, and |
belaran@999 | 5672 the team continues its work on top of that release so that |
belaran@999 | 5673 their feature can make the next release.</para> |
belaran@999 | 5674 </sect2> |
belaran@999 | 5675 |
belaran@999 | 5676 <sect2> |
belaran@999 | 5677 <title>The Linux kernel model</title> |
belaran@999 | 5678 |
belaran@999 | 5679 <para id="x_46e">The development of the Linux kernel has a shallow |
belaran@999 | 5680 hierarchical structure, surrounded by a cloud of apparent |
belaran@999 | 5681 chaos. Because most Linux developers use |
belaran@999 | 5682 <command moreinfo="none">git</command>, a distributed revision control tool |
belaran@999 | 5683 with capabilities similar to Mercurial, it's useful to |
belaran@999 | 5684 describe the way work flows in that environment; if you like |
belaran@999 | 5685 the ideas, the approach translates well across tools.</para> |
belaran@999 | 5686 |
belaran@999 | 5687 <para id="x_46f">At the center of the community sits Linus Torvalds, the |
belaran@999 | 5688 creator of Linux. He publishes a single source repository |
belaran@999 | 5689 that is considered the <quote>authoritative</quote> current |
belaran@999 | 5690 tree by the entire developer community. Anyone can clone |
belaran@999 | 5691 Linus's tree, but he is very choosy about whose trees he pulls |
belaran@999 | 5692 from.</para> |
belaran@999 | 5693 |
belaran@999 | 5694 <para id="x_470">Linus has a number of <quote>trusted lieutenants</quote>. |
belaran@999 | 5695 As a general rule, he pulls whatever changes they publish, in |
belaran@999 | 5696 most cases without even reviewing those changes. Some of |
belaran@999 | 5697 those lieutenants are generally agreed to be |
belaran@999 | 5698 <quote>maintainers</quote>, responsible for specific |
belaran@999 | 5699 subsystems within the kernel. If a random kernel hacker wants |
belaran@999 | 5700 to make a change to a subsystem that they want to end up in |
belaran@999 | 5701 Linus's tree, they must find out who the subsystem's |
belaran@999 | 5702 maintainer is, and ask that maintainer to take their change. |
belaran@999 | 5703 If the maintainer reviews their changes and agrees to take |
belaran@999 | 5704 them, they'll pass them along to Linus in due course.</para> |
belaran@999 | 5705 |
belaran@999 | 5706 <para id="x_471">Individual lieutenants have their own approaches to |
belaran@999 | 5707 reviewing, accepting, and publishing changes; and for deciding |
belaran@999 | 5708 when to feed them to Linus. In addition, there are several |
belaran@999 | 5709 well known branches that people use for different purposes. |
belaran@999 | 5710 For example, a few people maintain <quote>stable</quote> |
belaran@999 | 5711 repositories of older versions of the kernel, to which they |
belaran@999 | 5712 apply critical fixes as needed. Some maintainers publish |
belaran@999 | 5713 multiple trees: one for experimental changes; one for changes |
belaran@999 | 5714 that they are about to feed upstream; and so on. Others just |
belaran@999 | 5715 publish a single tree.</para> |
belaran@999 | 5716 |
belaran@999 | 5717 <para id="x_472">This model has two notable features. The first is that |
belaran@999 | 5718 it's <quote>pull only</quote>. You have to ask, convince, or |
belaran@999 | 5719 beg another developer to take a change from you, because there |
belaran@999 | 5720 are almost no trees to which more than one person can push, |
belaran@999 | 5721 and there's no way to push changes into a tree that someone |
belaran@999 | 5722 else controls.</para> |
belaran@999 | 5723 |
belaran@999 | 5724 <para id="x_473">The second is that it's based on reputation and acclaim. |
belaran@999 | 5725 If you're an unknown, Linus will probably ignore changes from |
belaran@999 | 5726 you without even responding. But a subsystem maintainer will |
belaran@999 | 5727 probably review them, and will likely take them if they pass |
belaran@999 | 5728 their criteria for suitability. The more <quote>good</quote> |
belaran@999 | 5729 changes you contribute to a maintainer, the more likely they |
belaran@999 | 5730 are to trust your judgment and accept your changes. If you're |
belaran@999 | 5731 well-known and maintain a long-lived branch for something |
belaran@999 | 5732 Linus hasn't yet accepted, people with similar interests may |
belaran@999 | 5733 pull your changes regularly to keep up with your work.</para> |
belaran@999 | 5734 |
belaran@999 | 5735 <para id="x_474">Reputation and acclaim don't necessarily cross subsystem |
belaran@999 | 5736 or <quote>people</quote> boundaries. If you're a respected |
belaran@999 | 5737 but specialised storage hacker, and you try to fix a |
belaran@999 | 5738 networking bug, that change will receive a level of scrutiny |
belaran@999 | 5739 from a network maintainer comparable to a change from a |
belaran@999 | 5740 complete stranger.</para> |
belaran@999 | 5741 |
belaran@999 | 5742 <para id="x_475">To people who come from more orderly project backgrounds, |
belaran@999 | 5743 the comparatively chaotic Linux kernel development process |
belaran@999 | 5744 often seems completely insane. It's subject to the whims of |
belaran@999 | 5745 individuals; people make sweeping changes whenever they deem |
belaran@999 | 5746 it appropriate; and the pace of development is astounding. |
belaran@999 | 5747 And yet Linux is a highly successful, well-regarded piece of |
belaran@999 | 5748 software.</para> |
belaran@999 | 5749 </sect2> |
belaran@999 | 5750 |
belaran@999 | 5751 <sect2> |
belaran@999 | 5752 <title>Pull-only versus shared-push collaboration</title> |
belaran@999 | 5753 |
belaran@999 | 5754 <para id="x_476">A perpetual source of heat in the open source community is |
belaran@999 | 5755 whether a development model in which people only ever pull |
belaran@999 | 5756 changes from others is <quote>better than</quote> one in which |
belaran@999 | 5757 multiple people can push changes to a shared |
belaran@999 | 5758 repository.</para> |
belaran@999 | 5759 |
belaran@999 | 5760 <para id="x_477">Typically, the backers of the shared-push model use tools |
belaran@999 | 5761 that actively enforce this approach. If you're using a |
belaran@999 | 5762 centralised revision control tool such as Subversion, there's |
belaran@999 | 5763 no way to make a choice over which model you'll use: the tool |
belaran@999 | 5764 gives you shared-push, and if you want to do anything else, |
belaran@999 | 5765 you'll have to roll your own approach on top (such as applying |
belaran@999 | 5766 a patch by hand).</para> |
belaran@999 | 5767 |
belaran@999 | 5768 <para id="x_478">A good distributed revision control tool will |
belaran@999 | 5769 support both models. You and your collaborators can then |
belaran@999 | 5770 structure how you work together based on your own needs and |
belaran@999 | 5771 preferences, not on what contortions your tools force you |
belaran@999 | 5772 into.</para> |
belaran@999 | 5773 </sect2> |
belaran@999 | 5774 <sect2> |
belaran@999 | 5775 <title>Where collaboration meets branch management</title> |
belaran@999 | 5776 |
belaran@999 | 5777 <para id="x_479">Once you and your team set up some shared |
belaran@999 | 5778 repositories and start propagating changes back and forth |
belaran@999 | 5779 between local and shared repos, you begin to face a related, |
belaran@999 | 5780 but slightly different challenge: that of managing the |
belaran@999 | 5781 multiple directions in which your team may be moving at once. |
belaran@999 | 5782 Even though this subject is intimately related to how your |
belaran@999 | 5783 team collaborates, it's dense enough to merit treatment of its |
belaran@999 | 5784 own, in <xref linkend="chap:branch"/>.</para> |
belaran@999 | 5785 </sect2> |
belaran@999 | 5786 </sect1> |
belaran@999 | 5787 |
belaran@999 | 5788 <sect1> |
belaran@999 | 5789 <title>The technical side of sharing</title> |
belaran@999 | 5790 |
belaran@999 | 5791 <para id="x_47a">The remainder of this chapter is devoted to the question of |
belaran@999 | 5792 sharing changes with your collaborators.</para> |
belaran@999 | 5793 </sect1> |
belaran@999 | 5794 |
belaran@999 | 5795 <sect1 id="sec:collab:serve"> |
belaran@999 | 5796 <title>Informal sharing with <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 5797 serve</command></title> |
belaran@999 | 5798 |
belaran@999 | 5799 <para id="x_47b">Mercurial's <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 5800 command is wonderfully suited to small, tight-knit, and |
belaran@999 | 5801 fast-paced group environments. It also provides a great way to |
belaran@999 | 5802 get a feel for using Mercurial commands over a network.</para> |
belaran@999 | 5803 |
belaran@999 | 5804 <para id="x_47c">Run <command role="hg-cmd" moreinfo="none">hg serve</command> inside a |
belaran@999 | 5805 repository, and in under a second it will bring up a specialised |
belaran@999 | 5806 HTTP server; this will accept connections from any client, and |
belaran@999 | 5807 serve up data for that repository until you terminate it. |
belaran@999 | 5808 Anyone who knows the URL of the server you just started, and can |
belaran@999 | 5809 talk to your computer over the network, can then use a web |
belaran@999 | 5810 browser or Mercurial to read data from that repository. A URL |
belaran@999 | 5811 for a <command role="hg-cmd" moreinfo="none">hg serve</command> instance running |
belaran@999 | 5812 on a laptop is likely to look something like |
belaran@999 | 5813 <literal moreinfo="none">http://my-laptop.local:8000/</literal>.</para> |
belaran@999 | 5814 |
belaran@999 | 5815 <para id="x_47d">The <command role="hg-cmd" moreinfo="none">hg serve</command> command is |
belaran@999 | 5816 <emphasis>not</emphasis> a general-purpose web server. It can do |
belaran@999 | 5817 only two things:</para> |
belaran@999 | 5818 <itemizedlist> |
belaran@999 | 5819 <listitem><para id="x_47e">Allow people to browse the history of the |
belaran@999 | 5820 repository it's serving, from their normal web |
belaran@999 | 5821 browsers.</para> |
belaran@999 | 5822 </listitem> |
belaran@999 | 5823 <listitem><para id="x_47f">Speak Mercurial's wire protocol, so that people |
belaran@999 | 5824 can <command role="hg-cmd" moreinfo="none">hg clone</command> or <command role="hg-cmd" moreinfo="none">hg pull</command> changes from that |
belaran@999 | 5825 repository.</para> |
belaran@999 | 5826 </listitem></itemizedlist> |
belaran@999 | 5827 <para id="x_480">In particular, <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 5828 won't allow remote users to <emphasis>modify</emphasis> your |
belaran@999 | 5829 repository. It's intended for read-only use.</para> |
belaran@999 | 5830 |
belaran@999 | 5831 <para id="x_481">If you're getting started with Mercurial, there's nothing to |
belaran@999 | 5832 prevent you from using <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 5833 to serve up a repository on your own computer, then use commands |
belaran@999 | 5834 like <command role="hg-cmd" moreinfo="none">hg clone</command>, <command role="hg-cmd" moreinfo="none">hg incoming</command>, and so on to talk to that |
belaran@999 | 5835 server as if the repository was hosted remotely. This can help |
belaran@999 | 5836 you to quickly get acquainted with using commands on |
belaran@999 | 5837 network-hosted repositories.</para> |
belaran@999 | 5838 |
belaran@999 | 5839 <sect2> |
belaran@999 | 5840 <title>A few things to keep in mind</title> |
belaran@999 | 5841 |
belaran@999 | 5842 <para id="x_482">Because it provides unauthenticated read access to all |
belaran@999 | 5843 clients, you should only use <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 5844 serve</command> in an environment where you either don't |
belaran@999 | 5845 care, or have complete control over, who can access your |
belaran@999 | 5846 network and pull data from your repository.</para> |
belaran@999 | 5847 |
belaran@999 | 5848 <para id="x_483">The <command role="hg-cmd" moreinfo="none">hg serve</command> command |
belaran@999 | 5849 knows nothing about any firewall software you might have |
belaran@999 | 5850 installed on your system or network. It cannot detect or |
belaran@999 | 5851 control your firewall software. If other people are unable to |
belaran@999 | 5852 talk to a running <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 5853 instance, the second thing you should do |
belaran@999 | 5854 (<emphasis>after</emphasis> you make sure that they're using |
belaran@999 | 5855 the correct URL) is check your firewall configuration.</para> |
belaran@999 | 5856 |
belaran@999 | 5857 <para id="x_484">By default, <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 5858 listens for incoming connections on port 8000. If another |
belaran@999 | 5859 process is already listening on the port you want to use, you |
belaran@999 | 5860 can specify a different port to listen on using the <option role="hg-opt-serve">-p</option> option.</para> |
belaran@999 | 5861 |
belaran@999 | 5862 <para id="x_485">Normally, when <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 5863 starts, it prints no output, which can be a bit unnerving. If |
belaran@999 | 5864 you'd like to confirm that it is indeed running correctly, and |
belaran@999 | 5865 find out what URL you should send to your collaborators, start |
belaran@999 | 5866 it with the <option role="hg-opt-global">-v</option> |
belaran@999 | 5867 option.</para> |
belaran@999 | 5868 </sect2> |
belaran@999 | 5869 </sect1> |
belaran@999 | 5870 |
belaran@999 | 5871 <sect1 id="sec:collab:ssh"> |
belaran@999 | 5872 <title>Using the Secure Shell (ssh) protocol</title> |
belaran@999 | 5873 |
belaran@999 | 5874 <para id="x_486">You can pull and push changes securely over a network |
belaran@999 | 5875 connection using the Secure Shell (<literal moreinfo="none">ssh</literal>) |
belaran@999 | 5876 protocol. To use this successfully, you may have to do a little |
belaran@999 | 5877 bit of configuration on the client or server sides.</para> |
belaran@999 | 5878 |
belaran@999 | 5879 <para id="x_487">If you're not familiar with ssh, it's the name of |
belaran@999 | 5880 both a command and a network protocol that let you securely |
belaran@999 | 5881 communicate with another computer. To use it with Mercurial, |
belaran@999 | 5882 you'll be setting up one or more user accounts on a server so |
belaran@999 | 5883 that remote users can log in and execute commands.</para> |
belaran@999 | 5884 |
belaran@999 | 5885 <para id="x_488">(If you <emphasis>are</emphasis> familiar with ssh, you'll |
belaran@999 | 5886 probably find some of the material that follows to be elementary |
belaran@999 | 5887 in nature.)</para> |
belaran@999 | 5888 |
belaran@999 | 5889 <sect2> |
belaran@999 | 5890 <title>How to read and write ssh URLs</title> |
belaran@999 | 5891 |
belaran@999 | 5892 <para id="x_489">An ssh URL tends to look like this:</para> |
belaran@999 | 5893 <programlisting format="linespecific">ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting> |
belaran@999 | 5894 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 5895 <listitem><para id="x_48a">The <quote><literal moreinfo="none">ssh://</literal></quote> |
belaran@999 | 5896 part tells Mercurial to use the ssh protocol.</para> |
belaran@999 | 5897 </listitem> |
belaran@999 | 5898 <listitem><para id="x_48b">The <quote><literal moreinfo="none">bos@</literal></quote> |
belaran@999 | 5899 component indicates what username to log into the server |
belaran@999 | 5900 as. You can leave this out if the remote username is the |
belaran@999 | 5901 same as your local username.</para> |
belaran@999 | 5902 </listitem> |
belaran@999 | 5903 <listitem><para id="x_48c">The |
belaran@999 | 5904 <quote><literal moreinfo="none">hg.serpentine.com</literal></quote> gives |
belaran@999 | 5905 the hostname of the server to log into.</para> |
belaran@999 | 5906 </listitem> |
belaran@999 | 5907 <listitem><para id="x_48d">The <quote>:22</quote> identifies the port |
belaran@999 | 5908 number to connect to the server on. The default port is |
belaran@999 | 5909 22, so you only need to specify a colon and port number if |
belaran@999 | 5910 you're <emphasis>not</emphasis> using port 22.</para> |
belaran@999 | 5911 </listitem> |
belaran@999 | 5912 <listitem><para id="x_48e">The remainder of the URL is the local path to |
belaran@999 | 5913 the repository on the server.</para> |
belaran@999 | 5914 </listitem></orderedlist> |
belaran@999 | 5915 |
belaran@999 | 5916 <para id="x_48f">There's plenty of scope for confusion with the path |
belaran@999 | 5917 component of ssh URLs, as there is no standard way for tools |
belaran@999 | 5918 to interpret it. Some programs behave differently than others |
belaran@999 | 5919 when dealing with these paths. This isn't an ideal situation, |
belaran@999 | 5920 but it's unlikely to change. Please read the following |
belaran@999 | 5921 paragraphs carefully.</para> |
belaran@999 | 5922 |
belaran@999 | 5923 <para id="x_490">Mercurial treats the path to a repository on the server as |
belaran@999 | 5924 relative to the remote user's home directory. For example, if |
belaran@999 | 5925 user <literal moreinfo="none">foo</literal> on the server has a home directory |
belaran@999 | 5926 of <filename class="directory" moreinfo="none">/home/foo</filename>, then an |
belaran@999 | 5927 ssh URL that contains a path component of <filename class="directory" moreinfo="none">bar</filename> <emphasis>really</emphasis> |
belaran@999 | 5928 refers to the directory <filename class="directory" moreinfo="none">/home/foo/bar</filename>.</para> |
belaran@999 | 5929 |
belaran@999 | 5930 <para id="x_491">If you want to specify a path relative to another user's |
belaran@999 | 5931 home directory, you can use a path that starts with a tilde |
belaran@999 | 5932 character followed by the user's name (let's call them |
belaran@999 | 5933 <literal moreinfo="none">otheruser</literal>), like this.</para> |
belaran@999 | 5934 <programlisting format="linespecific">ssh://server/~otheruser/hg/repo</programlisting> |
belaran@999 | 5935 |
belaran@999 | 5936 <para id="x_492">And if you really want to specify an |
belaran@999 | 5937 <emphasis>absolute</emphasis> path on the server, begin the |
belaran@999 | 5938 path component with two slashes, as in this example.</para> |
belaran@999 | 5939 <programlisting format="linespecific">ssh://server//absolute/path</programlisting> |
belaran@999 | 5940 </sect2> |
belaran@999 | 5941 |
belaran@999 | 5942 <sect2> |
belaran@999 | 5943 <title>Finding an ssh client for your system</title> |
belaran@999 | 5944 |
belaran@999 | 5945 <para id="x_493">Almost every Unix-like system comes with OpenSSH |
belaran@999 | 5946 preinstalled. If you're using such a system, run |
belaran@999 | 5947 <literal moreinfo="none">which ssh</literal> to find out if the |
belaran@999 | 5948 <command moreinfo="none">ssh</command> command is installed (it's usually in |
belaran@999 | 5949 <filename class="directory" moreinfo="none">/usr/bin</filename>). In the |
belaran@999 | 5950 unlikely event that it isn't present, take a look at your |
belaran@999 | 5951 system documentation to figure out how to install it.</para> |
belaran@999 | 5952 |
belaran@999 | 5953 <para id="x_494">On Windows, the TortoiseHg package is bundled |
belaran@999 | 5954 with a version of Simon Tatham's excellent |
belaran@999 | 5955 <command moreinfo="none">plink</command> command, and you should not need to |
belaran@999 | 5956 do any further configuration.</para> |
belaran@999 | 5957 </sect2> |
belaran@999 | 5958 |
belaran@999 | 5959 <sect2> |
belaran@999 | 5960 <title>Generating a key pair</title> |
belaran@999 | 5961 |
belaran@999 | 5962 <para id="x_499">To avoid the need to repetitively type a |
belaran@999 | 5963 password every time you need to use your ssh client, I |
belaran@999 | 5964 recommend generating a key pair.</para> |
belaran@999 | 5965 |
belaran@999 | 5966 <tip> |
belaran@999 | 5967 <title>Key pairs are not mandatory</title> |
belaran@999 | 5968 |
belaran@999 | 5969 <para id="x_6a4">Mercurial knows nothing about ssh authentication or key |
belaran@999 | 5970 pairs. You can, if you like, safely ignore this section and |
belaran@999 | 5971 the one that follows until you grow tired of repeatedly |
belaran@999 | 5972 typing ssh passwords.</para> |
belaran@999 | 5973 </tip> |
belaran@999 | 5974 |
belaran@999 | 5975 <itemizedlist> |
belaran@999 | 5976 <listitem> |
belaran@999 | 5977 <para id="x_6a5">On a Unix-like system, the |
belaran@999 | 5978 <command moreinfo="none">ssh-keygen</command> command will do the |
belaran@999 | 5979 trick.</para> |
belaran@999 | 5980 <para id="x_6a6">On Windows, if you're using TortoiseHg, you may need |
belaran@999 | 5981 to download a command named <command moreinfo="none">puttygen</command> |
belaran@999 | 5982 from <ulink url="http://www.chiark.greenend.org.uk/~sgtatham/putty">the |
belaran@999 | 5983 PuTTY web site</ulink> to generate a key pair. See |
belaran@999 | 5984 <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter8.html#pubkey-puttygen">the |
belaran@999 | 5985 <command moreinfo="none">puttygen</command> documentation</ulink> for |
belaran@999 | 5986 details of how use the command.</para> |
belaran@999 | 5987 </listitem> |
belaran@999 | 5988 </itemizedlist> |
belaran@999 | 5989 |
belaran@999 | 5990 <para id="x_49a">When you generate a key pair, it's usually |
belaran@999 | 5991 <emphasis>highly</emphasis> advisable to protect it with a |
belaran@999 | 5992 passphrase. (The only time that you might not want to do this |
belaran@999 | 5993 is when you're using the ssh protocol for automated tasks on a |
belaran@999 | 5994 secure network.)</para> |
belaran@999 | 5995 |
belaran@999 | 5996 <para id="x_49b">Simply generating a key pair isn't enough, however. |
belaran@999 | 5997 You'll need to add the public key to the set of authorised |
belaran@999 | 5998 keys for whatever user you're logging in remotely as. For |
belaran@999 | 5999 servers using OpenSSH (the vast majority), this will mean |
belaran@999 | 6000 adding the public key to a list in a file called <filename role="special" moreinfo="none">authorized_keys</filename> in their <filename role="special" class="directory" moreinfo="none">.ssh</filename> |
belaran@999 | 6001 directory.</para> |
belaran@999 | 6002 |
belaran@999 | 6003 <para id="x_49c">On a Unix-like system, your public key will have a |
belaran@999 | 6004 <filename moreinfo="none">.pub</filename> extension. If you're using |
belaran@999 | 6005 <command moreinfo="none">puttygen</command> on Windows, you can save the |
belaran@999 | 6006 public key to a file of your choosing, or paste it from the |
belaran@999 | 6007 window it's displayed in straight into the <filename role="special" moreinfo="none">authorized_keys</filename> file.</para> |
belaran@999 | 6008 </sect2> |
belaran@999 | 6009 <sect2> |
belaran@999 | 6010 <title>Using an authentication agent</title> |
belaran@999 | 6011 |
belaran@999 | 6012 <para id="x_49d">An authentication agent is a daemon that stores |
belaran@999 | 6013 passphrases in memory (so it will forget passphrases if you |
belaran@999 | 6014 log out and log back in again). An ssh client will notice if |
belaran@999 | 6015 it's running, and query it for a passphrase. If there's no |
belaran@999 | 6016 authentication agent running, or the agent doesn't store the |
belaran@999 | 6017 necessary passphrase, you'll have to type your passphrase |
belaran@999 | 6018 every time Mercurial tries to communicate with a server on |
belaran@999 | 6019 your behalf (e.g. whenever you pull or push changes).</para> |
belaran@999 | 6020 |
belaran@999 | 6021 <para id="x_49e">The downside of storing passphrases in an agent is that |
belaran@999 | 6022 it's possible for a well-prepared attacker to recover the |
belaran@999 | 6023 plain text of your passphrases, in some cases even if your |
belaran@999 | 6024 system has been power-cycled. You should make your own |
belaran@999 | 6025 judgment as to whether this is an acceptable risk. It |
belaran@999 | 6026 certainly saves a lot of repeated typing.</para> |
belaran@999 | 6027 |
belaran@999 | 6028 <itemizedlist> |
belaran@999 | 6029 <listitem> |
belaran@999 | 6030 <para id="x_49f">On Unix-like systems, the agent is called |
belaran@999 | 6031 <command moreinfo="none">ssh-agent</command>, and it's often run |
belaran@999 | 6032 automatically for you when you log in. You'll need to use |
belaran@999 | 6033 the <command moreinfo="none">ssh-add</command> command to add passphrases |
belaran@999 | 6034 to the agent's store.</para> |
belaran@999 | 6035 </listitem> |
belaran@999 | 6036 <listitem> |
belaran@999 | 6037 <para id="x_6a7">On Windows, if you're using TortoiseHg, the |
belaran@999 | 6038 <command moreinfo="none">pageant</command> command acts as the agent. As |
belaran@999 | 6039 with <command moreinfo="none">puttygen</command>, you'll need to <ulink url="http://www.chiark.greenend.org.uk/%7Esgtatham/putty/download.html">download |
belaran@999 | 6040 <command moreinfo="none">pageant</command></ulink> from the PuTTY web |
belaran@999 | 6041 site and read <ulink url="http://the.earth.li/~sgtatham/putty/0.60/htmldoc/Chapter9.html#pageant">its |
belaran@999 | 6042 documentation</ulink>. The <command moreinfo="none">pageant</command> |
belaran@999 | 6043 command adds an icon to your system tray that will let you |
belaran@999 | 6044 manage stored passphrases.</para> |
belaran@999 | 6045 </listitem> |
belaran@999 | 6046 </itemizedlist> |
belaran@999 | 6047 </sect2> |
belaran@999 | 6048 |
belaran@999 | 6049 <sect2> |
belaran@999 | 6050 <title>Configuring the server side properly</title> |
belaran@999 | 6051 |
belaran@999 | 6052 <para id="x_4a0">Because ssh can be fiddly to set up if you're new to it, |
belaran@999 | 6053 a variety of things can go wrong. Add Mercurial |
belaran@999 | 6054 on top, and there's plenty more scope for head-scratching. |
belaran@999 | 6055 Most of these potential problems occur on the server side, not |
belaran@999 | 6056 the client side. The good news is that once you've gotten a |
belaran@999 | 6057 configuration working, it will usually continue to work |
belaran@999 | 6058 indefinitely.</para> |
belaran@999 | 6059 |
belaran@999 | 6060 <para id="x_4a1">Before you try using Mercurial to talk to an ssh server, |
belaran@999 | 6061 it's best to make sure that you can use the normal |
belaran@999 | 6062 <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command> command to |
belaran@999 | 6063 talk to the server first. If you run into problems with using |
belaran@999 | 6064 these commands directly, Mercurial surely won't work. Worse, |
belaran@999 | 6065 it will obscure the underlying problem. Any time you want to |
belaran@999 | 6066 debug ssh-related Mercurial problems, you should drop back to |
belaran@999 | 6067 making sure that plain ssh client commands work first, |
belaran@999 | 6068 <emphasis>before</emphasis> you worry about whether there's a |
belaran@999 | 6069 problem with Mercurial.</para> |
belaran@999 | 6070 |
belaran@999 | 6071 <para id="x_4a2">The first thing to be sure of on the server side is that |
belaran@999 | 6072 you can actually log in from another machine at all. If you |
belaran@999 | 6073 can't use <command moreinfo="none">ssh</command> or <command moreinfo="none">putty</command> |
belaran@999 | 6074 to log in, the error message you get may give you a few hints |
belaran@999 | 6075 as to what's wrong. The most common problems are as |
belaran@999 | 6076 follows.</para> |
belaran@999 | 6077 <itemizedlist> |
belaran@999 | 6078 <listitem><para id="x_4a3">If you get a <quote>connection refused</quote> |
belaran@999 | 6079 error, either there isn't an SSH daemon running on the |
belaran@999 | 6080 server at all, or it's inaccessible due to firewall |
belaran@999 | 6081 configuration.</para> |
belaran@999 | 6082 </listitem> |
belaran@999 | 6083 <listitem><para id="x_4a4">If you get a <quote>no route to host</quote> |
belaran@999 | 6084 error, you either have an incorrect address for the server |
belaran@999 | 6085 or a seriously locked down firewall that won't admit its |
belaran@999 | 6086 existence at all.</para> |
belaran@999 | 6087 </listitem> |
belaran@999 | 6088 <listitem><para id="x_4a5">If you get a <quote>permission denied</quote> |
belaran@999 | 6089 error, you may have mistyped the username on the server, |
belaran@999 | 6090 or you could have mistyped your key's passphrase or the |
belaran@999 | 6091 remote user's password.</para> |
belaran@999 | 6092 </listitem></itemizedlist> |
belaran@999 | 6093 <para id="x_4a6">In summary, if you're having trouble talking to the |
belaran@999 | 6094 server's ssh daemon, first make sure that one is running at |
belaran@999 | 6095 all. On many systems it will be installed, but disabled, by |
belaran@999 | 6096 default. Once you're done with this step, you should then |
belaran@999 | 6097 check that the server's firewall is configured to allow |
belaran@999 | 6098 incoming connections on the port the ssh daemon is listening |
belaran@999 | 6099 on (usually 22). Don't worry about more exotic possibilities |
belaran@999 | 6100 for misconfiguration until you've checked these two |
belaran@999 | 6101 first.</para> |
belaran@999 | 6102 |
belaran@999 | 6103 <para id="x_4a7">If you're using an authentication agent on the client side |
belaran@999 | 6104 to store passphrases for your keys, you ought to be able to |
belaran@999 | 6105 log into the server without being prompted for a passphrase or |
belaran@999 | 6106 a password. If you're prompted for a passphrase, there are a |
belaran@999 | 6107 few possible culprits.</para> |
belaran@999 | 6108 <itemizedlist> |
belaran@999 | 6109 <listitem><para id="x_4a8">You might have forgotten to use |
belaran@999 | 6110 <command moreinfo="none">ssh-add</command> or <command moreinfo="none">pageant</command> |
belaran@999 | 6111 to store the passphrase.</para> |
belaran@999 | 6112 </listitem> |
belaran@999 | 6113 <listitem><para id="x_4a9">You might have stored the passphrase for the |
belaran@999 | 6114 wrong key.</para> |
belaran@999 | 6115 </listitem></itemizedlist> |
belaran@999 | 6116 <para id="x_4aa">If you're being prompted for the remote user's password, |
belaran@999 | 6117 there are another few possible problems to check.</para> |
belaran@999 | 6118 <itemizedlist> |
belaran@999 | 6119 <listitem><para id="x_4ab">Either the user's home directory or their |
belaran@999 | 6120 <filename role="special" class="directory" moreinfo="none">.ssh</filename> |
belaran@999 | 6121 directory might have excessively liberal permissions. As |
belaran@999 | 6122 a result, the ssh daemon will not trust or read their |
belaran@999 | 6123 <filename role="special" moreinfo="none">authorized_keys</filename> file. |
belaran@999 | 6124 For example, a group-writable home or <filename role="special" class="directory" moreinfo="none">.ssh</filename> |
belaran@999 | 6125 directory will often cause this symptom.</para> |
belaran@999 | 6126 </listitem> |
belaran@999 | 6127 <listitem><para id="x_4ac">The user's <filename role="special" moreinfo="none">authorized_keys</filename> file may have |
belaran@999 | 6128 a problem. If anyone other than the user owns or can write |
belaran@999 | 6129 to that file, the ssh daemon will not trust or read |
belaran@999 | 6130 it.</para> |
belaran@999 | 6131 </listitem></itemizedlist> |
belaran@999 | 6132 |
belaran@999 | 6133 <para id="x_4ad">In the ideal world, you should be able to run the |
belaran@999 | 6134 following command successfully, and it should print exactly |
belaran@999 | 6135 one line of output, the current date and time.</para> |
belaran@999 | 6136 <programlisting format="linespecific">ssh myserver date</programlisting> |
belaran@999 | 6137 |
belaran@999 | 6138 <para id="x_4ae">If, on your server, you have login scripts that print |
belaran@999 | 6139 banners or other junk even when running non-interactive |
belaran@999 | 6140 commands like this, you should fix them before you continue, |
belaran@999 | 6141 so that they only print output if they're run interactively. |
belaran@999 | 6142 Otherwise these banners will at least clutter up Mercurial's |
belaran@999 | 6143 output. Worse, they could potentially cause problems with |
belaran@999 | 6144 running Mercurial commands remotely. Mercurial tries to |
belaran@999 | 6145 detect and ignore banners in non-interactive |
belaran@999 | 6146 <command moreinfo="none">ssh</command> sessions, but it is not foolproof. (If |
belaran@999 | 6147 you're editing your login scripts on your server, the usual |
belaran@999 | 6148 way to see if a login script is running in an interactive |
belaran@999 | 6149 shell is to check the return code from the command |
belaran@999 | 6150 <literal moreinfo="none">tty -s</literal>.)</para> |
belaran@999 | 6151 |
belaran@999 | 6152 <para id="x_4af">Once you've verified that plain old ssh is working with |
belaran@999 | 6153 your server, the next step is to ensure that Mercurial runs on |
belaran@999 | 6154 the server. The following command should run |
belaran@999 | 6155 successfully:</para> |
belaran@999 | 6156 |
belaran@999 | 6157 <programlisting format="linespecific">ssh myserver hg version</programlisting> |
belaran@999 | 6158 |
belaran@999 | 6159 <para id="x_4b0">If you see an error message instead of normal <command role="hg-cmd" moreinfo="none">hg version</command> output, this is usually |
belaran@999 | 6160 because you haven't installed Mercurial to <filename class="directory" moreinfo="none">/usr/bin</filename>. Don't worry if this |
belaran@999 | 6161 is the case; you don't need to do that. But you should check |
belaran@999 | 6162 for a few possible problems.</para> |
belaran@999 | 6163 <itemizedlist> |
belaran@999 | 6164 <listitem><para id="x_4b1">Is Mercurial really installed on the server at |
belaran@999 | 6165 all? I know this sounds trivial, but it's worth |
belaran@999 | 6166 checking!</para> |
belaran@999 | 6167 </listitem> |
belaran@999 | 6168 <listitem><para id="x_4b2">Maybe your shell's search path (usually set |
belaran@999 | 6169 via the <envar>PATH</envar> environment variable) is |
belaran@999 | 6170 simply misconfigured.</para> |
belaran@999 | 6171 </listitem> |
belaran@999 | 6172 <listitem><para id="x_4b3">Perhaps your <envar>PATH</envar> environment |
belaran@999 | 6173 variable is only being set to point to the location of the |
belaran@999 | 6174 <command moreinfo="none">hg</command> executable if the login session is |
belaran@999 | 6175 interactive. This can happen if you're setting the path |
belaran@999 | 6176 in the wrong shell login script. See your shell's |
belaran@999 | 6177 documentation for details.</para> |
belaran@999 | 6178 </listitem> |
belaran@999 | 6179 <listitem><para id="x_4b4">The <envar>PYTHONPATH</envar> environment |
belaran@999 | 6180 variable may need to contain the path to the Mercurial |
belaran@999 | 6181 Python modules. It might not be set at all; it could be |
belaran@999 | 6182 incorrect; or it may be set only if the login is |
belaran@999 | 6183 interactive.</para> |
belaran@999 | 6184 </listitem></itemizedlist> |
belaran@999 | 6185 |
belaran@999 | 6186 <para id="x_4b5">If you can run <command role="hg-cmd" moreinfo="none">hg version</command> |
belaran@999 | 6187 over an ssh connection, well done! You've got the server and |
belaran@999 | 6188 client sorted out. You should now be able to use Mercurial to |
belaran@999 | 6189 access repositories hosted by that username on that server. |
belaran@999 | 6190 If you run into problems with Mercurial and ssh at this point, |
belaran@999 | 6191 try using the <option role="hg-opt-global">--debug</option> |
belaran@999 | 6192 option to get a clearer picture of what's going on.</para> |
belaran@999 | 6193 </sect2> |
belaran@999 | 6194 <sect2> |
belaran@999 | 6195 <title>Using compression with ssh</title> |
belaran@999 | 6196 |
belaran@999 | 6197 <para id="x_4b6">Mercurial does not compress data when it uses the ssh |
belaran@999 | 6198 protocol, because the ssh protocol can transparently compress |
belaran@999 | 6199 data. However, the default behavior of ssh clients is |
belaran@999 | 6200 <emphasis>not</emphasis> to request compression.</para> |
belaran@999 | 6201 |
belaran@999 | 6202 <para id="x_4b7">Over any network other than a fast LAN (even a wireless |
belaran@999 | 6203 network), using compression is likely to significantly speed |
belaran@999 | 6204 up Mercurial's network operations. For example, over a WAN, |
belaran@999 | 6205 someone measured compression as reducing the amount of time |
belaran@999 | 6206 required to clone a particularly large repository from 51 |
belaran@999 | 6207 minutes to 17 minutes.</para> |
belaran@999 | 6208 |
belaran@999 | 6209 <para id="x_4b8">Both <command moreinfo="none">ssh</command> and <command moreinfo="none">plink</command> |
belaran@999 | 6210 accept a <option role="cmd-opt-ssh">-C</option> option which |
belaran@999 | 6211 turns on compression. You can easily edit your <filename role="special" moreinfo="none">~/.hgrc</filename> to enable compression for |
belaran@999 | 6212 all of Mercurial's uses of the ssh protocol. Here is how to |
belaran@999 | 6213 do so for regular <command moreinfo="none">ssh</command> on Unix-like systems, |
belaran@999 | 6214 for example.</para> |
belaran@999 | 6215 <programlisting format="linespecific">[ui] |
belaran@999 | 6216 ssh = ssh -C</programlisting> |
belaran@999 | 6217 |
belaran@999 | 6218 <para id="x_4b9">If you use <command moreinfo="none">ssh</command> on a |
belaran@999 | 6219 Unix-like system, you can configure it to always use |
belaran@999 | 6220 compression when talking to your server. To do this, edit |
belaran@999 | 6221 your <filename role="special" moreinfo="none">.ssh/config</filename> file |
belaran@999 | 6222 (which may not yet exist), as follows.</para> |
belaran@999 | 6223 |
belaran@999 | 6224 <programlisting format="linespecific">Host hg |
belaran@999 | 6225 Compression yes |
belaran@999 | 6226 HostName hg.example.com</programlisting> |
belaran@999 | 6227 |
belaran@999 | 6228 <para id="x_4ba">This defines a hostname alias, |
belaran@999 | 6229 <literal moreinfo="none">hg</literal>. When you use that hostname on the |
belaran@999 | 6230 <command moreinfo="none">ssh</command> command line or in a Mercurial |
belaran@999 | 6231 <literal moreinfo="none">ssh</literal>-protocol URL, it will cause |
belaran@999 | 6232 <command moreinfo="none">ssh</command> to connect to |
belaran@999 | 6233 <literal moreinfo="none">hg.example.com</literal> and use compression. This |
belaran@999 | 6234 gives you both a shorter name to type and compression, each of |
belaran@999 | 6235 which is a good thing in its own right.</para> |
belaran@999 | 6236 </sect2> |
belaran@999 | 6237 </sect1> |
belaran@999 | 6238 |
belaran@999 | 6239 <sect1 id="sec:collab:cgi"> |
belaran@999 | 6240 <title>Serving over HTTP using CGI</title> |
belaran@999 | 6241 |
belaran@999 | 6242 <para id="x_6a8">The simplest way to host one or more repositories in a |
belaran@999 | 6243 permanent way is to use a web server and Mercurial's CGI |
belaran@999 | 6244 support.</para> |
belaran@999 | 6245 |
belaran@999 | 6246 <para id="x_4bb">Depending on how ambitious you are, configuring Mercurial's |
belaran@999 | 6247 CGI interface can take anything from a few moments to several |
belaran@999 | 6248 hours.</para> |
belaran@999 | 6249 |
belaran@999 | 6250 <para id="x_4bc">We'll begin with the simplest of examples, and work our way |
belaran@999 | 6251 towards a more complex configuration. Even for the most basic |
belaran@999 | 6252 case, you're almost certainly going to need to read and modify |
belaran@999 | 6253 your web server's configuration.</para> |
belaran@999 | 6254 |
belaran@999 | 6255 <note> |
belaran@999 | 6256 <title>High pain tolerance required</title> |
belaran@999 | 6257 |
belaran@999 | 6258 <para id="x_4bd">Configuring a web server is a complex, fiddly, |
belaran@999 | 6259 and highly system-dependent activity. I can't possibly give |
belaran@999 | 6260 you instructions that will cover anything like all of the |
belaran@999 | 6261 cases you will encounter. Please use your discretion and |
belaran@999 | 6262 judgment in following the sections below. Be prepared to make |
belaran@999 | 6263 plenty of mistakes, and to spend a lot of time reading your |
belaran@999 | 6264 server's error logs.</para> |
belaran@999 | 6265 |
belaran@999 | 6266 <para id="x_6a9">If you don't have a strong stomach for tweaking |
belaran@999 | 6267 configurations over and over, or a compelling need to host |
belaran@999 | 6268 your own services, you might want to try one of the public |
belaran@999 | 6269 hosting services that I mentioned earlier.</para> |
belaran@999 | 6270 </note> |
belaran@999 | 6271 |
belaran@999 | 6272 <sect2> |
belaran@999 | 6273 <title>Web server configuration checklist</title> |
belaran@999 | 6274 |
belaran@999 | 6275 <para id="x_4be">Before you continue, do take a few moments to check a few |
belaran@999 | 6276 aspects of your system's setup.</para> |
belaran@999 | 6277 |
belaran@999 | 6278 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 6279 <listitem><para id="x_4bf">Do you have a web server installed |
belaran@999 | 6280 at all? Mac OS X and some Linux distributions ship with |
belaran@999 | 6281 Apache, but many other systems may not have a web server |
belaran@999 | 6282 installed.</para> |
belaran@999 | 6283 </listitem> |
belaran@999 | 6284 <listitem><para id="x_4c0">If you have a web server installed, is it |
belaran@999 | 6285 actually running? On most systems, even if one is |
belaran@999 | 6286 present, it will be disabled by default.</para> |
belaran@999 | 6287 </listitem> |
belaran@999 | 6288 <listitem><para id="x_4c1">Is your server configured to allow you to run |
belaran@999 | 6289 CGI programs in the directory where you plan to do so? |
belaran@999 | 6290 Most servers default to explicitly disabling the ability |
belaran@999 | 6291 to run CGI programs.</para> |
belaran@999 | 6292 </listitem></orderedlist> |
belaran@999 | 6293 |
belaran@999 | 6294 <para id="x_4c2">If you don't have a web server installed, and don't have |
belaran@999 | 6295 substantial experience configuring Apache, you should consider |
belaran@999 | 6296 using the <literal moreinfo="none">lighttpd</literal> web server instead of |
belaran@999 | 6297 Apache. Apache has a well-deserved reputation for baroque and |
belaran@999 | 6298 confusing configuration. While <literal moreinfo="none">lighttpd</literal> is |
belaran@999 | 6299 less capable in some ways than Apache, most of these |
belaran@999 | 6300 capabilities are not relevant to serving Mercurial |
belaran@999 | 6301 repositories. And <literal moreinfo="none">lighttpd</literal> is undeniably |
belaran@999 | 6302 <emphasis>much</emphasis> easier to get started with than |
belaran@999 | 6303 Apache.</para> |
belaran@999 | 6304 </sect2> |
belaran@999 | 6305 |
belaran@999 | 6306 <sect2> |
belaran@999 | 6307 <title>Basic CGI configuration</title> |
belaran@999 | 6308 |
belaran@999 | 6309 <para id="x_4c3">On Unix-like systems, it's common for users to have a |
belaran@999 | 6310 subdirectory named something like <filename class="directory" moreinfo="none">public_html</filename> in their home |
belaran@999 | 6311 directory, from which they can serve up web pages. A file |
belaran@999 | 6312 named <filename moreinfo="none">foo</filename> in this directory will be |
belaran@999 | 6313 accessible at a URL of the form |
belaran@999 | 6314 <literal moreinfo="none">http://www.example.com/username/foo</literal>.</para> |
belaran@999 | 6315 |
belaran@999 | 6316 <para id="x_4c4">To get started, find the <filename role="special" moreinfo="none">hgweb.cgi</filename> script that should be |
belaran@999 | 6317 present in your Mercurial installation. If you can't quickly |
belaran@999 | 6318 find a local copy on your system, simply download one from the |
belaran@999 | 6319 master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para> |
belaran@999 | 6320 |
belaran@999 | 6321 <para id="x_4c5">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and |
belaran@999 | 6322 ensure that it's executable.</para> |
belaran@999 | 6323 <programlisting format="linespecific">cp .../hgweb.cgi ~/public_html |
belaran@999 | 6324 chmod 755 ~/public_html/hgweb.cgi</programlisting> |
belaran@999 | 6325 <para id="x_4c6">The <literal moreinfo="none">755</literal> argument to |
belaran@999 | 6326 <command moreinfo="none">chmod</command> is a little more general than just |
belaran@999 | 6327 making the script executable: it ensures that the script is |
belaran@999 | 6328 executable by anyone, and that <quote>group</quote> and |
belaran@999 | 6329 <quote>other</quote> write permissions are |
belaran@999 | 6330 <emphasis>not</emphasis> set. If you were to leave those |
belaran@999 | 6331 write permissions enabled, Apache's <literal moreinfo="none">suexec</literal> |
belaran@999 | 6332 subsystem would likely refuse to execute the script. In fact, |
belaran@999 | 6333 <literal moreinfo="none">suexec</literal> also insists that the |
belaran@999 | 6334 <emphasis>directory</emphasis> in which the script resides |
belaran@999 | 6335 must not be writable by others.</para> |
belaran@999 | 6336 <programlisting format="linespecific">chmod 755 ~/public_html</programlisting> |
belaran@999 | 6337 |
belaran@999 | 6338 <sect3 id="sec:collab:wtf"> |
belaran@999 | 6339 <title>What could <emphasis>possibly</emphasis> go |
belaran@999 | 6340 wrong?</title> |
belaran@999 | 6341 |
belaran@999 | 6342 <para id="x_4c7">Once you've copied the CGI script into place, |
belaran@999 | 6343 go into a web browser, and try to open the URL |
belaran@999 | 6344 <literal moreinfo="none">http://myhostname/~myuser/hgweb.cgi</literal>, |
belaran@999 | 6345 <emphasis>but</emphasis> brace yourself for instant failure. |
belaran@999 | 6346 There's a high probability that trying to visit this URL |
belaran@999 | 6347 will fail, and there are many possible reasons for this. In |
belaran@999 | 6348 fact, you're likely to stumble over almost every one of the |
belaran@999 | 6349 possible errors below, so please read carefully. The |
belaran@999 | 6350 following are all of the problems I ran into on a system |
belaran@999 | 6351 running Fedora 7, with a fresh installation of Apache, and a |
belaran@999 | 6352 user account that I created specially to perform this |
belaran@999 | 6353 exercise.</para> |
belaran@999 | 6354 |
belaran@999 | 6355 <para id="x_4c8">Your web server may have per-user directories disabled. |
belaran@999 | 6356 If you're using Apache, search your config file for a |
belaran@999 | 6357 <literal moreinfo="none">UserDir</literal> directive. If there's none |
belaran@999 | 6358 present, per-user directories will be disabled. If one |
belaran@999 | 6359 exists, but its value is <literal moreinfo="none">disabled</literal>, then |
belaran@999 | 6360 per-user directories will be disabled. Otherwise, the |
belaran@999 | 6361 string after <literal moreinfo="none">UserDir</literal> gives the name of |
belaran@999 | 6362 the subdirectory that Apache will look in under your home |
belaran@999 | 6363 directory, for example <filename class="directory" moreinfo="none">public_html</filename>.</para> |
belaran@999 | 6364 |
belaran@999 | 6365 <para id="x_4c9">Your file access permissions may be too restrictive. |
belaran@999 | 6366 The web server must be able to traverse your home directory |
belaran@999 | 6367 and directories under your <filename class="directory" moreinfo="none">public_html</filename> directory, and |
belaran@999 | 6368 read files under the latter too. Here's a quick recipe to |
belaran@999 | 6369 help you to make your permissions more appropriate.</para> |
belaran@999 | 6370 <programlisting format="linespecific">chmod 755 ~ |
belaran@999 | 6371 find ~/public_html -type d -print0 | xargs -0r chmod 755 |
belaran@999 | 6372 find ~/public_html -type f -print0 | xargs -0r chmod 644</programlisting> |
belaran@999 | 6373 |
belaran@999 | 6374 <para id="x_4ca">The other possibility with permissions is that you might |
belaran@999 | 6375 get a completely empty window when you try to load the |
belaran@999 | 6376 script. In this case, it's likely that your access |
belaran@999 | 6377 permissions are <emphasis>too permissive</emphasis>. Apache's |
belaran@999 | 6378 <literal moreinfo="none">suexec</literal> subsystem won't execute a script |
belaran@999 | 6379 that's group- or world-writable, for example.</para> |
belaran@999 | 6380 |
belaran@999 | 6381 <para id="x_4cb">Your web server may be configured to disallow execution |
belaran@999 | 6382 of CGI programs in your per-user web directory. Here's |
belaran@999 | 6383 Apache's default per-user configuration from my Fedora |
belaran@999 | 6384 system.</para> |
belaran@999 | 6385 |
belaran@999 | 6386 <!-- BEGIN ch06/apache-config.lst --> |
belaran@999 | 6387 <programlisting format="linespecific"><Directory /home/*/public_html> |
belaran@999 | 6388 AllowOverride FileInfo AuthConfig Limit |
belaran@999 | 6389 Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec |
belaran@999 | 6390 <Limit GET POST OPTIONS> |
belaran@999 | 6391 Order allow,deny |
belaran@999 | 6392 Allow from all |
belaran@999 | 6393 </Limit> |
belaran@999 | 6394 <LimitExcept GET POST OPTIONS> |
belaran@999 | 6395 Order deny,allow Deny from all |
belaran@999 | 6396 </LimitExcept> |
belaran@999 | 6397 </Directory></programlisting> |
belaran@999 | 6398 <!-- END ch06/apache-config.lst --> |
belaran@999 | 6399 |
belaran@999 | 6400 |
belaran@999 | 6401 <para id="x_4cc">If you find a similar-looking |
belaran@999 | 6402 <literal moreinfo="none">Directory</literal> group in your Apache |
belaran@999 | 6403 configuration, the directive to look at inside it is |
belaran@999 | 6404 <literal moreinfo="none">Options</literal>. Add <literal moreinfo="none">ExecCGI</literal> |
belaran@999 | 6405 to the end of this list if it's missing, and restart the web |
belaran@999 | 6406 server.</para> |
belaran@999 | 6407 |
belaran@999 | 6408 <para id="x_4cd">If you find that Apache serves you the text of the CGI |
belaran@999 | 6409 script instead of executing it, you may need to either |
belaran@999 | 6410 uncomment (if already present) or add a directive like |
belaran@999 | 6411 this.</para> |
belaran@999 | 6412 <programlisting format="linespecific">AddHandler cgi-script .cgi</programlisting> |
belaran@999 | 6413 |
belaran@999 | 6414 <para id="x_4ce">The next possibility is that you might be served with a |
belaran@999 | 6415 colourful Python backtrace claiming that it can't import a |
belaran@999 | 6416 <literal moreinfo="none">mercurial</literal>-related module. This is |
belaran@999 | 6417 actually progress! The server is now capable of executing |
belaran@999 | 6418 your CGI script. This error is only likely to occur if |
belaran@999 | 6419 you're running a private installation of Mercurial, instead |
belaran@999 | 6420 of a system-wide version. Remember that the web server runs |
belaran@999 | 6421 the CGI program without any of the environment variables |
belaran@999 | 6422 that you take for granted in an interactive session. If |
belaran@999 | 6423 this error happens to you, edit your copy of <filename role="special" moreinfo="none">hgweb.cgi</filename> and follow the |
belaran@999 | 6424 directions inside it to correctly set your |
belaran@999 | 6425 <envar>PYTHONPATH</envar> environment variable.</para> |
belaran@999 | 6426 |
belaran@999 | 6427 <para id="x_4cf">Finally, you are <emphasis>certain</emphasis> to be |
belaran@999 | 6428 served with another colourful Python backtrace: this one |
belaran@999 | 6429 will complain that it can't find <filename class="directory" moreinfo="none">/path/to/repository</filename>. Edit |
belaran@999 | 6430 your <filename role="special" moreinfo="none">hgweb.cgi</filename> script |
belaran@999 | 6431 and replace the <filename class="directory" moreinfo="none">/path/to/repository</filename> string |
belaran@999 | 6432 with the complete path to the repository you want to serve |
belaran@999 | 6433 up.</para> |
belaran@999 | 6434 |
belaran@999 | 6435 <para id="x_4d0">At this point, when you try to reload the page, you |
belaran@999 | 6436 should be presented with a nice HTML view of your |
belaran@999 | 6437 repository's history. Whew!</para> |
belaran@999 | 6438 </sect3> |
belaran@999 | 6439 |
belaran@999 | 6440 <sect3> |
belaran@999 | 6441 <title>Configuring lighttpd</title> |
belaran@999 | 6442 |
belaran@999 | 6443 <para id="x_4d1">To be exhaustive in my experiments, I tried configuring |
belaran@999 | 6444 the increasingly popular <literal moreinfo="none">lighttpd</literal> web |
belaran@999 | 6445 server to serve the same repository as I described with |
belaran@999 | 6446 Apache above. I had already overcome all of the problems I |
belaran@999 | 6447 outlined with Apache, many of which are not server-specific. |
belaran@999 | 6448 As a result, I was fairly sure that my file and directory |
belaran@999 | 6449 permissions were good, and that my <filename role="special" moreinfo="none">hgweb.cgi</filename> script was properly |
belaran@999 | 6450 edited.</para> |
belaran@999 | 6451 |
belaran@999 | 6452 <para id="x_4d2">Once I had Apache running, getting |
belaran@999 | 6453 <literal moreinfo="none">lighttpd</literal> to serve the repository was a |
belaran@999 | 6454 snap (in other words, even if you're trying to use |
belaran@999 | 6455 <literal moreinfo="none">lighttpd</literal>, you should read the Apache |
belaran@999 | 6456 section). I first had to edit the |
belaran@999 | 6457 <literal moreinfo="none">mod_access</literal> section of its config file to |
belaran@999 | 6458 enable <literal moreinfo="none">mod_cgi</literal> and |
belaran@999 | 6459 <literal moreinfo="none">mod_userdir</literal>, both of which were disabled |
belaran@999 | 6460 by default on my system. I then added a few lines to the |
belaran@999 | 6461 end of the config file, to configure these modules.</para> |
belaran@999 | 6462 <programlisting format="linespecific">userdir.path = "public_html" |
belaran@999 | 6463 cgi.assign = (".cgi" => "" )</programlisting> |
belaran@999 | 6464 <para id="x_4d3">With this done, <literal moreinfo="none">lighttpd</literal> ran |
belaran@999 | 6465 immediately for me. If I had configured |
belaran@999 | 6466 <literal moreinfo="none">lighttpd</literal> before Apache, I'd almost |
belaran@999 | 6467 certainly have run into many of the same system-level |
belaran@999 | 6468 configuration problems as I did with Apache. However, I |
belaran@999 | 6469 found <literal moreinfo="none">lighttpd</literal> to be noticeably easier to |
belaran@999 | 6470 configure than Apache, even though I've used Apache for over |
belaran@999 | 6471 a decade, and this was my first exposure to |
belaran@999 | 6472 <literal moreinfo="none">lighttpd</literal>.</para> |
belaran@999 | 6473 </sect3> |
belaran@999 | 6474 </sect2> |
belaran@999 | 6475 |
belaran@999 | 6476 <sect2> |
belaran@999 | 6477 <title>Sharing multiple repositories with one CGI script</title> |
belaran@999 | 6478 |
belaran@999 | 6479 <para id="x_4d4">The <filename role="special" moreinfo="none">hgweb.cgi</filename> script |
belaran@999 | 6480 only lets you publish a single repository, which is an |
belaran@999 | 6481 annoying restriction. If you want to publish more than one |
belaran@999 | 6482 without wracking yourself with multiple copies of the same |
belaran@999 | 6483 script, each with different names, a better choice is to use |
belaran@999 | 6484 the <filename role="special" moreinfo="none">hgwebdir.cgi</filename> |
belaran@999 | 6485 script.</para> |
belaran@999 | 6486 |
belaran@999 | 6487 <para id="x_4d5">The procedure to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is only a little more |
belaran@999 | 6488 involved than for <filename role="special" moreinfo="none">hgweb.cgi</filename>. First, you must obtain |
belaran@999 | 6489 a copy of the script. If you don't have one handy, you can |
belaran@999 | 6490 download a copy from the master Mercurial repository at <ulink url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para> |
belaran@999 | 6491 |
belaran@999 | 6492 <para id="x_4d6">You'll need to copy this script into your <filename class="directory" moreinfo="none">public_html</filename> directory, and |
belaran@999 | 6493 ensure that it's executable.</para> |
belaran@999 | 6494 |
belaran@999 | 6495 <programlisting format="linespecific">cp .../hgwebdir.cgi ~/public_html |
belaran@999 | 6496 chmod 755 ~/public_html ~/public_html/hgwebdir.cgi</programlisting> |
belaran@999 | 6497 |
belaran@999 | 6498 <para id="x_4d7">With basic configuration out of the way, try to |
belaran@999 | 6499 visit <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal> |
belaran@999 | 6500 in your browser. It should |
belaran@999 | 6501 display an empty list of repositories. If you get a blank |
belaran@999 | 6502 window or error message, try walking through the list of |
belaran@999 | 6503 potential problems in <xref linkend="sec:collab:wtf"/>.</para> |
belaran@999 | 6504 |
belaran@999 | 6505 <para id="x_4d8">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename> |
belaran@999 | 6506 script relies on an external configuration file. By default, |
belaran@999 | 6507 it searches for a file named <filename role="special" moreinfo="none">hgweb.config</filename> in the same directory |
belaran@999 | 6508 as itself. You'll need to create this file, and make it |
belaran@999 | 6509 world-readable. The format of the file is similar to a |
belaran@999 | 6510 Windows <quote>ini</quote> file, as understood by Python's |
belaran@999 | 6511 <literal moreinfo="none">ConfigParser</literal> |
belaran@999 | 6512 <citation>web:configparser</citation> module.</para> |
belaran@999 | 6513 |
belaran@999 | 6514 <para id="x_4d9">The easiest way to configure <filename role="special" moreinfo="none">hgwebdir.cgi</filename> is with a section |
belaran@999 | 6515 named <literal moreinfo="none">collections</literal>. This will automatically |
belaran@999 | 6516 publish <emphasis>every</emphasis> repository under the |
belaran@999 | 6517 directories you name. The section should look like |
belaran@999 | 6518 this:</para> |
belaran@999 | 6519 <programlisting format="linespecific">[collections] |
belaran@999 | 6520 /my/root = /my/root</programlisting> |
belaran@999 | 6521 <para id="x_4da">Mercurial interprets this by looking at the directory name |
belaran@999 | 6522 on the <emphasis>right</emphasis> hand side of the |
belaran@999 | 6523 <quote><literal moreinfo="none">=</literal></quote> sign; finding repositories |
belaran@999 | 6524 in that directory hierarchy; and using the text on the |
belaran@999 | 6525 <emphasis>left</emphasis> to strip off matching text from the |
belaran@999 | 6526 names it will actually list in the web interface. The |
belaran@999 | 6527 remaining component of a path after this stripping has |
belaran@999 | 6528 occurred is called a <quote>virtual path</quote>.</para> |
belaran@999 | 6529 |
belaran@999 | 6530 <para id="x_4db">Given the example above, if we have a |
belaran@999 | 6531 repository whose local path is <filename class="directory" moreinfo="none">/my/root/this/repo</filename>, the CGI |
belaran@999 | 6532 script will strip the leading <filename class="directory" moreinfo="none">/my/root</filename> from the name, and |
belaran@999 | 6533 publish the repository with a virtual path of <filename class="directory" moreinfo="none">this/repo</filename>. If the base URL for |
belaran@999 | 6534 our CGI script is |
belaran@999 | 6535 <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi</literal>, the |
belaran@999 | 6536 complete URL for that repository will be |
belaran@999 | 6537 <literal moreinfo="none">http://myhostname/~myuser/hgwebdir.cgi/this/repo</literal>.</para> |
belaran@999 | 6538 |
belaran@999 | 6539 <para id="x_4dc">If we replace <filename class="directory" moreinfo="none">/my/root</filename> on the left hand side |
belaran@999 | 6540 of this example with <filename class="directory" moreinfo="none">/my</filename>, then <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will only strip off |
belaran@999 | 6541 <filename class="directory" moreinfo="none">/my</filename> from the repository |
belaran@999 | 6542 name, and will give us a virtual path of <filename class="directory" moreinfo="none">root/this/repo</filename> instead of |
belaran@999 | 6543 <filename class="directory" moreinfo="none">this/repo</filename>.</para> |
belaran@999 | 6544 |
belaran@999 | 6545 <para id="x_4dd">The <filename role="special" moreinfo="none">hgwebdir.cgi</filename> |
belaran@999 | 6546 script will recursively search each directory listed in the |
belaran@999 | 6547 <literal moreinfo="none">collections</literal> section of its configuration |
belaran@999 | 6548 file, but it will <literal moreinfo="none">not</literal> recurse into the |
belaran@999 | 6549 repositories it finds.</para> |
belaran@999 | 6550 |
belaran@999 | 6551 <para id="x_4de">The <literal moreinfo="none">collections</literal> mechanism makes it easy |
belaran@999 | 6552 to publish many repositories in a <quote>fire and |
belaran@999 | 6553 forget</quote> manner. You only need to set up the CGI |
belaran@999 | 6554 script and configuration file one time. Afterwards, you can |
belaran@999 | 6555 publish or unpublish a repository at any time by simply moving |
belaran@999 | 6556 it into, or out of, the directory hierarchy in which you've |
belaran@999 | 6557 configured <filename role="special" moreinfo="none">hgwebdir.cgi</filename> to |
belaran@999 | 6558 look.</para> |
belaran@999 | 6559 |
belaran@999 | 6560 <sect3> |
belaran@999 | 6561 <title>Explicitly specifying which repositories to |
belaran@999 | 6562 publish</title> |
belaran@999 | 6563 |
belaran@999 | 6564 <para id="x_4df">In addition to the <literal moreinfo="none">collections</literal> |
belaran@999 | 6565 mechanism, the <filename role="special" moreinfo="none">hgwebdir.cgi</filename> script allows you |
belaran@999 | 6566 to publish a specific list of repositories. To do so, |
belaran@999 | 6567 create a <literal moreinfo="none">paths</literal> section, with contents of |
belaran@999 | 6568 the following form.</para> |
belaran@999 | 6569 <programlisting format="linespecific">[paths] |
belaran@999 | 6570 repo1 = /my/path/to/some/repo |
belaran@999 | 6571 repo2 = /some/path/to/another</programlisting> |
belaran@999 | 6572 <para id="x_4e0">In this case, the virtual path (the component that will |
belaran@999 | 6573 appear in a URL) is on the left hand side of each |
belaran@999 | 6574 definition, while the path to the repository is on the |
belaran@999 | 6575 right. Notice that there does not need to be any |
belaran@999 | 6576 relationship between the virtual path you choose and the |
belaran@999 | 6577 location of a repository in your filesystem.</para> |
belaran@999 | 6578 |
belaran@999 | 6579 <para id="x_4e1">If you wish, you can use both the |
belaran@999 | 6580 <literal moreinfo="none">collections</literal> and <literal moreinfo="none">paths</literal> |
belaran@999 | 6581 mechanisms simultaneously in a single configuration |
belaran@999 | 6582 file.</para> |
belaran@999 | 6583 |
belaran@999 | 6584 <note> |
belaran@999 | 6585 <title>Beware duplicate virtual paths</title> |
belaran@999 | 6586 |
belaran@999 | 6587 <para id="x_4e2"> If several repositories have the same |
belaran@999 | 6588 virtual path, <filename role="special" moreinfo="none">hgwebdir.cgi</filename> will not report |
belaran@999 | 6589 an error. Instead, it will behave unpredictably.</para> |
belaran@999 | 6590 </note> |
belaran@999 | 6591 </sect3> |
belaran@999 | 6592 </sect2> |
belaran@999 | 6593 |
belaran@999 | 6594 <sect2> |
belaran@999 | 6595 <title>Downloading source archives</title> |
belaran@999 | 6596 |
belaran@999 | 6597 <para id="x_4e3">Mercurial's web interface lets users download an archive |
belaran@999 | 6598 of any revision. This archive will contain a snapshot of the |
belaran@999 | 6599 working directory as of that revision, but it will not contain |
belaran@999 | 6600 a copy of the repository data.</para> |
belaran@999 | 6601 |
belaran@999 | 6602 <para id="x_4e4">By default, this feature is not enabled. To enable it, |
belaran@999 | 6603 you'll need to add an <envar role="rc-item-web">allow_archive</envar> item to the |
belaran@999 | 6604 <literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>; see below for details.</para> |
belaran@999 | 6605 </sect2> |
belaran@999 | 6606 <sect2> |
belaran@999 | 6607 <title>Web configuration options</title> |
belaran@999 | 6608 |
belaran@999 | 6609 <para id="x_4e5">Mercurial's web interfaces (the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 6610 serve</command> command, and the <filename role="special" moreinfo="none">hgweb.cgi</filename> and <filename role="special" moreinfo="none">hgwebdir.cgi</filename> scripts) have a |
belaran@999 | 6611 number of configuration options that you can set. These |
belaran@999 | 6612 belong in a section named <literal role="rc-web" moreinfo="none">web</literal>.</para> |
belaran@999 | 6613 <itemizedlist> |
belaran@999 | 6614 <listitem><para id="x_4e6"><envar role="rc-item-web">allow_archive</envar>: Determines |
belaran@999 | 6615 which (if any) archive download mechanisms Mercurial |
belaran@999 | 6616 supports. If you enable this feature, users of the web |
belaran@999 | 6617 interface will be able to download an archive of whatever |
belaran@999 | 6618 revision of a repository they are viewing. To enable the |
belaran@999 | 6619 archive feature, this item must take the form of a |
belaran@999 | 6620 sequence of words drawn from the list below.</para> |
belaran@999 | 6621 <itemizedlist> |
belaran@999 | 6622 <listitem><para id="x_4e7"><literal moreinfo="none">bz2</literal>: A |
belaran@999 | 6623 <command moreinfo="none">tar</command> archive, compressed using |
belaran@999 | 6624 <literal moreinfo="none">bzip2</literal> compression. This has the |
belaran@999 | 6625 best compression ratio, but uses the most CPU time on |
belaran@999 | 6626 the server.</para> |
belaran@999 | 6627 </listitem> |
belaran@999 | 6628 <listitem><para id="x_4e8"><literal moreinfo="none">gz</literal>: A |
belaran@999 | 6629 <command moreinfo="none">tar</command> archive, compressed using |
belaran@999 | 6630 <literal moreinfo="none">gzip</literal> compression.</para> |
belaran@999 | 6631 </listitem> |
belaran@999 | 6632 <listitem><para id="x_4e9"><literal moreinfo="none">zip</literal>: A |
belaran@999 | 6633 <command moreinfo="none">zip</command> archive, compressed using LZW |
belaran@999 | 6634 compression. This format has the worst compression |
belaran@999 | 6635 ratio, but is widely used in the Windows world.</para> |
belaran@999 | 6636 </listitem> |
belaran@999 | 6637 </itemizedlist> |
belaran@999 | 6638 <para id="x_4ea"> If you provide an empty list, or don't have an |
belaran@999 | 6639 <envar role="rc-item-web">allow_archive</envar> entry at |
belaran@999 | 6640 all, this feature will be disabled. Here is an example of |
belaran@999 | 6641 how to enable all three supported formats.</para> |
belaran@999 | 6642 <programlisting format="linespecific">[web] |
belaran@999 | 6643 allow_archive = bz2 gz zip</programlisting> |
belaran@999 | 6644 </listitem> |
belaran@999 | 6645 <listitem><para id="x_4eb"><envar role="rc-item-web">allowpull</envar>: |
belaran@999 | 6646 Boolean. Determines whether the web interface allows |
belaran@999 | 6647 remote users to <command role="hg-cmd" moreinfo="none">hg pull</command> |
belaran@999 | 6648 and <command role="hg-cmd" moreinfo="none">hg clone</command> this |
belaran@999 | 6649 repository over HTTP. If set to <literal moreinfo="none">no</literal> or |
belaran@999 | 6650 <literal moreinfo="none">false</literal>, only the |
belaran@999 | 6651 <quote>human-oriented</quote> portion of the web interface |
belaran@999 | 6652 is available.</para> |
belaran@999 | 6653 </listitem> |
belaran@999 | 6654 <listitem><para id="x_4ec"><envar role="rc-item-web">contact</envar>: |
belaran@999 | 6655 String. A free-form (but preferably brief) string |
belaran@999 | 6656 identifying the person or group in charge of the |
belaran@999 | 6657 repository. This often contains the name and email |
belaran@999 | 6658 address of a person or mailing list. It often makes sense |
belaran@999 | 6659 to place this entry in a repository's own <filename role="special" moreinfo="none">.hg/hgrc</filename> file, but it can make |
belaran@999 | 6660 sense to use in a global <filename role="special" moreinfo="none">~/.hgrc</filename> if every repository |
belaran@999 | 6661 has a single maintainer.</para> |
belaran@999 | 6662 </listitem> |
belaran@999 | 6663 <listitem><para id="x_4ed"><envar role="rc-item-web">maxchanges</envar>: |
belaran@999 | 6664 Integer. The default maximum number of changesets to |
belaran@999 | 6665 display in a single page of output.</para> |
belaran@999 | 6666 </listitem> |
belaran@999 | 6667 <listitem><para id="x_4ee"><envar role="rc-item-web">maxfiles</envar>: |
belaran@999 | 6668 Integer. The default maximum number of modified files to |
belaran@999 | 6669 display in a single page of output.</para> |
belaran@999 | 6670 </listitem> |
belaran@999 | 6671 <listitem><para id="x_4ef"><envar role="rc-item-web">stripes</envar>: |
belaran@999 | 6672 Integer. If the web interface displays alternating |
belaran@999 | 6673 <quote>stripes</quote> to make it easier to visually align |
belaran@999 | 6674 rows when you are looking at a table, this number controls |
belaran@999 | 6675 the number of rows in each stripe.</para> |
belaran@999 | 6676 </listitem> |
belaran@999 | 6677 <listitem><para id="x_4f0"><envar role="rc-item-web">style</envar>: Controls the template |
belaran@999 | 6678 Mercurial uses to display the web interface. Mercurial |
belaran@999 | 6679 ships with several web templates.</para> |
belaran@999 | 6680 <itemizedlist> |
belaran@999 | 6681 <listitem> |
belaran@999 | 6682 <para id="x_6aa"><literal moreinfo="none">coal</literal> is monochromatic.</para> |
belaran@999 | 6683 </listitem> |
belaran@999 | 6684 <listitem> |
belaran@999 | 6685 <para id="x_6ab"><literal moreinfo="none">gitweb</literal> emulates the visual |
belaran@999 | 6686 style of git's web interface.</para> |
belaran@999 | 6687 </listitem> |
belaran@999 | 6688 <listitem> |
belaran@999 | 6689 <para id="x_6ac"><literal moreinfo="none">monoblue</literal> uses solid blues and |
belaran@999 | 6690 greys.</para> |
belaran@999 | 6691 </listitem> |
belaran@999 | 6692 <listitem> |
belaran@999 | 6693 <para id="x_6ad"><literal moreinfo="none">paper</literal> is the default.</para> |
belaran@999 | 6694 </listitem> |
belaran@999 | 6695 <listitem> |
belaran@999 | 6696 <para id="x_6ae"><literal moreinfo="none">spartan</literal> was the default for a |
belaran@999 | 6697 long time.</para> |
belaran@999 | 6698 </listitem> |
belaran@999 | 6699 </itemizedlist> |
belaran@999 | 6700 <para id="x_6af">You can |
belaran@999 | 6701 also specify a custom template of your own; see |
belaran@999 | 6702 <xref linkend="chap:template"/> for details. Here, you can |
belaran@999 | 6703 see how to enable the <literal moreinfo="none">gitweb</literal> |
belaran@999 | 6704 style.</para> |
belaran@999 | 6705 <programlisting format="linespecific">[web] |
belaran@999 | 6706 style = gitweb</programlisting> |
belaran@999 | 6707 </listitem> |
belaran@999 | 6708 <listitem><para id="x_4f1"><envar role="rc-item-web">templates</envar>: |
belaran@999 | 6709 Path. The directory in which to search for template |
belaran@999 | 6710 files. By default, Mercurial searches in the directory in |
belaran@999 | 6711 which it was installed.</para> |
belaran@999 | 6712 </listitem></itemizedlist> |
belaran@999 | 6713 <para id="x_4f2">If you are using <filename role="special" moreinfo="none">hgwebdir.cgi</filename>, you can place a few |
belaran@999 | 6714 configuration items in a <literal role="rc-web" moreinfo="none">web</literal> |
belaran@999 | 6715 section of the <filename role="special" moreinfo="none">hgweb.config</filename> file instead of a |
belaran@999 | 6716 <filename role="special" moreinfo="none">~/.hgrc</filename> file, for |
belaran@999 | 6717 convenience. These items are <envar role="rc-item-web">motd</envar> and <envar role="rc-item-web">style</envar>.</para> |
belaran@999 | 6718 |
belaran@999 | 6719 <sect3> |
belaran@999 | 6720 <title>Options specific to an individual repository</title> |
belaran@999 | 6721 |
belaran@999 | 6722 <para id="x_4f3">A few <literal role="rc-web" moreinfo="none">web</literal> configuration |
belaran@999 | 6723 items ought to be placed in a repository's local <filename role="special" moreinfo="none">.hg/hgrc</filename>, rather than a user's |
belaran@999 | 6724 or global <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> |
belaran@999 | 6725 <itemizedlist> |
belaran@999 | 6726 <listitem><para id="x_4f4"><envar role="rc-item-web">description</envar>: String. A |
belaran@999 | 6727 free-form (but preferably brief) string that describes |
belaran@999 | 6728 the contents or purpose of the repository.</para> |
belaran@999 | 6729 </listitem> |
belaran@999 | 6730 <listitem><para id="x_4f5"><envar role="rc-item-web">name</envar>: |
belaran@999 | 6731 String. The name to use for the repository in the web |
belaran@999 | 6732 interface. This overrides the default name, which is |
belaran@999 | 6733 the last component of the repository's path.</para> |
belaran@999 | 6734 </listitem></itemizedlist> |
belaran@999 | 6735 </sect3> |
belaran@999 | 6736 |
belaran@999 | 6737 <sect3> |
belaran@999 | 6738 <title>Options specific to the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 6739 serve</command> command</title> |
belaran@999 | 6740 |
belaran@999 | 6741 <para id="x_4f6">Some of the items in the <literal role="rc-web" moreinfo="none">web</literal> section of a <filename role="special" moreinfo="none">~/.hgrc</filename> file are only for use |
belaran@999 | 6742 with the <command role="hg-cmd" moreinfo="none">hg serve</command> |
belaran@999 | 6743 command.</para> |
belaran@999 | 6744 <itemizedlist> |
belaran@999 | 6745 <listitem><para id="x_4f7"><envar role="rc-item-web">accesslog</envar>: |
belaran@999 | 6746 Path. The name of a file into which to write an access |
belaran@999 | 6747 log. By default, the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 6748 serve</command> command writes this information to |
belaran@999 | 6749 standard output, not to a file. Log entries are written |
belaran@999 | 6750 in the standard <quote>combined</quote> file format used |
belaran@999 | 6751 by almost all web servers.</para> |
belaran@999 | 6752 </listitem> |
belaran@999 | 6753 <listitem><para id="x_4f8"><envar role="rc-item-web">address</envar>: |
belaran@999 | 6754 String. The local address on which the server should |
belaran@999 | 6755 listen for incoming connections. By default, the server |
belaran@999 | 6756 listens on all addresses.</para> |
belaran@999 | 6757 </listitem> |
belaran@999 | 6758 <listitem><para id="x_4f9"><envar role="rc-item-web">errorlog</envar>: |
belaran@999 | 6759 Path. The name of a file into which to write an error |
belaran@999 | 6760 log. By default, the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 6761 serve</command> command writes this information to |
belaran@999 | 6762 standard error, not to a file.</para> |
belaran@999 | 6763 </listitem> |
belaran@999 | 6764 <listitem><para id="x_4fa"><envar role="rc-item-web">ipv6</envar>: |
belaran@999 | 6765 Boolean. Whether to use the IPv6 protocol. By default, |
belaran@999 | 6766 IPv6 is not used.</para> |
belaran@999 | 6767 </listitem> |
belaran@999 | 6768 <listitem><para id="x_4fb"><envar role="rc-item-web">port</envar>: |
belaran@999 | 6769 Integer. The TCP port number on which the server should |
belaran@999 | 6770 listen. The default port number used is 8000.</para> |
belaran@999 | 6771 </listitem></itemizedlist> |
belaran@999 | 6772 </sect3> |
belaran@999 | 6773 |
belaran@999 | 6774 <sect3> |
belaran@999 | 6775 <title>Choosing the right <filename role="special" moreinfo="none">~/.hgrc</filename> file to add <literal role="rc-web" moreinfo="none">web</literal> items to</title> |
belaran@999 | 6776 |
belaran@999 | 6777 <para id="x_4fc">It is important to remember that a web server like |
belaran@999 | 6778 Apache or <literal moreinfo="none">lighttpd</literal> will run under a user |
belaran@999 | 6779 ID that is different to yours. CGI scripts run by your |
belaran@999 | 6780 server, such as <filename role="special" moreinfo="none">hgweb.cgi</filename>, will usually also run |
belaran@999 | 6781 under that user ID.</para> |
belaran@999 | 6782 |
belaran@999 | 6783 <para id="x_4fd">If you add <literal role="rc-web" moreinfo="none">web</literal> items to |
belaran@999 | 6784 your own personal <filename role="special" moreinfo="none">~/.hgrc</filename> file, CGI scripts won't read that |
belaran@999 | 6785 <filename role="special" moreinfo="none">~/.hgrc</filename> file. Those |
belaran@999 | 6786 settings will thus only affect the behavior of the <command role="hg-cmd" moreinfo="none">hg serve</command> command when you run it. |
belaran@999 | 6787 To cause CGI scripts to see your settings, either create a |
belaran@999 | 6788 <filename role="special" moreinfo="none">~/.hgrc</filename> file in the |
belaran@999 | 6789 home directory of the user ID that runs your web server, or |
belaran@999 | 6790 add those settings to a system-wide <filename role="special" moreinfo="none">hgrc</filename> file.</para> |
belaran@999 | 6791 </sect3> |
belaran@999 | 6792 </sect2> |
belaran@999 | 6793 </sect1> |
belaran@999 | 6794 |
belaran@999 | 6795 <sect1> |
belaran@999 | 6796 <title>System-wide configuration</title> |
belaran@999 | 6797 |
belaran@999 | 6798 <para id="x_6b0">On Unix-like systems shared by multiple users (such as a |
belaran@999 | 6799 server to which people publish changes), it often makes sense to |
belaran@999 | 6800 set up some global default behaviors, such as what theme to use |
belaran@999 | 6801 in web interfaces.</para> |
belaran@999 | 6802 |
belaran@999 | 6803 <para id="x_6b1">If a file named <filename moreinfo="none">/etc/mercurial/hgrc</filename> |
belaran@999 | 6804 exists, Mercurial will read it at startup time and apply any |
belaran@999 | 6805 configuration settings it finds in that file. It will also look |
belaran@999 | 6806 for files ending in a <literal moreinfo="none">.rc</literal> extension in a |
belaran@999 | 6807 directory named <filename moreinfo="none">/etc/mercurial/hgrc.d</filename>, and |
belaran@999 | 6808 apply any configuration settings it finds in each of those |
belaran@999 | 6809 files.</para> |
belaran@999 | 6810 |
belaran@999 | 6811 <sect2> |
belaran@999 | 6812 <title>Making Mercurial more trusting</title> |
belaran@999 | 6813 |
belaran@999 | 6814 <para id="x_6b2">One situation in which a global <filename moreinfo="none">hgrc</filename> |
belaran@999 | 6815 can be useful is if users are pulling changes owned by other |
belaran@999 | 6816 users. By default, Mercurial will not trust most of the |
belaran@999 | 6817 configuration items in a <filename moreinfo="none">.hg/hgrc</filename> file |
belaran@999 | 6818 inside a repository that is owned by a different user. If we |
belaran@999 | 6819 clone or pull changes from such a repository, Mercurial will |
belaran@999 | 6820 print a warning stating that it does not trust their |
belaran@999 | 6821 <filename moreinfo="none">.hg/hgrc</filename>.</para> |
belaran@999 | 6822 |
belaran@999 | 6823 <para id="x_6b3">If everyone in a particular Unix group is on the same team |
belaran@999 | 6824 and <emphasis>should</emphasis> trust each other's |
belaran@999 | 6825 configuration settings, or we want to trust particular users, |
belaran@999 | 6826 we can override Mercurial's skeptical defaults by creating a |
belaran@999 | 6827 system-wide <filename moreinfo="none">hgrc</filename> file such as the |
belaran@999 | 6828 following:</para> |
belaran@999 | 6829 |
belaran@999 | 6830 <programlisting format="linespecific"># Save this as e.g. /etc/mercurial/hgrc.d/trust.rc |
belaran@999 | 6831 [trusted] |
belaran@999 | 6832 # Trust all entries in any hgrc file owned by the "editors" or |
belaran@999 | 6833 # "www-data" groups. |
belaran@999 | 6834 groups = editors, www-data |
belaran@999 | 6835 |
belaran@999 | 6836 # Trust entries in hgrc files owned by the following users. |
belaran@999 | 6837 users = apache, bobo |
belaran@999 | 6838 </programlisting> |
belaran@999 | 6839 </sect2> |
belaran@999 | 6840 </sect1> |
belaran@999 | 6841 </chapter> |
belaran@999 | 6842 |
belaran@999 | 6843 <!-- |
belaran@999 | 6844 local variables: |
belaran@999 | 6845 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 6846 end: |
belaran@999 | 6847 --> |
belaran@999 | 6848 |
belaran@999 | 6849 <!-- BEGIN ch07 --> |
belaran@999 | 6850 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 6851 |
belaran@999 | 6852 <chapter id="chap:names"> |
belaran@999 | 6853 <?dbhtml filename="file-names-and-pattern-matching.html"?> |
belaran@999 | 6854 <title>File names and pattern matching</title> |
belaran@999 | 6855 |
belaran@999 | 6856 <para id="x_543">Mercurial provides mechanisms that let you work with file |
belaran@999 | 6857 names in a consistent and expressive way.</para> |
belaran@999 | 6858 |
belaran@999 | 6859 <sect1> |
belaran@999 | 6860 <title>Simple file naming</title> |
belaran@999 | 6861 |
belaran@999 | 6862 <para id="x_544">Mercurial uses a unified piece of machinery <quote>under the |
belaran@999 | 6863 hood</quote> to handle file names. Every command behaves |
belaran@999 | 6864 uniformly with respect to file names. The way in which commands |
belaran@999 | 6865 work with file names is as follows.</para> |
belaran@999 | 6866 |
belaran@999 | 6867 <para id="x_545">If you explicitly name real files on the command line, |
belaran@999 | 6868 Mercurial works with exactly those files, as you would expect. |
belaran@999 | 6869 <!-- BEGIN filenames.files --> |
belaran@999 | 6870 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add COPYING README examples/simple.py</userinput> |
belaran@999 | 6871 </screen> |
belaran@999 | 6872 <!-- END filenames.files --> |
belaran@999 | 6873 </para> |
belaran@999 | 6874 |
belaran@999 | 6875 <para id="x_546">When you provide a directory name, Mercurial will interpret |
belaran@999 | 6876 this as <quote>operate on every file in this directory and its |
belaran@999 | 6877 subdirectories</quote>. Mercurial traverses the files and |
belaran@999 | 6878 subdirectories in a directory in alphabetical order. When it |
belaran@999 | 6879 encounters a subdirectory, it will traverse that subdirectory |
belaran@999 | 6880 before continuing with the current directory.</para> |
belaran@999 | 6881 |
belaran@999 | 6882 <!-- BEGIN filenames.dirs --> |
belaran@999 | 6883 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status src</userinput> |
belaran@999 | 6884 ? src/main.py |
belaran@999 | 6885 ? src/watcher/_watcher.c |
belaran@999 | 6886 ? src/watcher/watcher.py |
belaran@999 | 6887 ? src/xyzzy.txt |
belaran@999 | 6888 </screen> |
belaran@999 | 6889 <!-- END filenames.dirs --> |
belaran@999 | 6890 |
belaran@999 | 6891 </sect1> |
belaran@999 | 6892 |
belaran@999 | 6893 <sect1> |
belaran@999 | 6894 <title>Running commands without any file names</title> |
belaran@999 | 6895 |
belaran@999 | 6896 <para id="x_547">Mercurial's commands that work with file names have useful |
belaran@999 | 6897 default behaviors when you invoke them without providing any |
belaran@999 | 6898 file names or patterns. What kind of behavior you should |
belaran@999 | 6899 expect depends on what the command does. Here are a few rules |
belaran@999 | 6900 of thumb you can use to predict what a command is likely to do |
belaran@999 | 6901 if you don't give it any names to work with.</para> |
belaran@999 | 6902 <itemizedlist> |
belaran@999 | 6903 <listitem><para id="x_548">Most commands will operate on the entire working |
belaran@999 | 6904 directory. This is what the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 6905 add</command> command does, for example.</para> |
belaran@999 | 6906 </listitem> |
belaran@999 | 6907 <listitem><para id="x_549">If the command has effects that are difficult or |
belaran@999 | 6908 impossible to reverse, it will force you to explicitly |
belaran@999 | 6909 provide at least one name or pattern (see below). This |
belaran@999 | 6910 protects you from accidentally deleting files by running |
belaran@999 | 6911 <command role="hg-cmd" moreinfo="none">hg remove</command> with no |
belaran@999 | 6912 arguments, for example.</para> |
belaran@999 | 6913 </listitem></itemizedlist> |
belaran@999 | 6914 |
belaran@999 | 6915 <para id="x_54a">It's easy to work around these default behaviors if they |
belaran@999 | 6916 don't suit you. If a command normally operates on the whole |
belaran@999 | 6917 working directory, you can invoke it on just the current |
belaran@999 | 6918 directory and its subdirectories by giving it the name |
belaran@999 | 6919 <quote><filename class="directory" moreinfo="none">.</filename></quote>.</para> |
belaran@999 | 6920 |
belaran@999 | 6921 <!-- BEGIN filenames.wdir-subdir --> |
belaran@999 | 6922 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd src</userinput> |
belaran@999 | 6923 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n</userinput> |
belaran@999 | 6924 adding ../MANIFEST.in |
belaran@999 | 6925 adding ../examples/performant.py |
belaran@999 | 6926 adding ../setup.py |
belaran@999 | 6927 adding main.py |
belaran@999 | 6928 adding watcher/_watcher.c |
belaran@999 | 6929 adding watcher/watcher.py |
belaran@999 | 6930 adding xyzzy.txt |
belaran@999 | 6931 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add -n .</userinput> |
belaran@999 | 6932 adding main.py |
belaran@999 | 6933 adding watcher/_watcher.c |
belaran@999 | 6934 adding watcher/watcher.py |
belaran@999 | 6935 adding xyzzy.txt |
belaran@999 | 6936 </screen> |
belaran@999 | 6937 <!-- END filenames.wdir-subdir --> |
belaran@999 | 6938 |
belaran@999 | 6939 |
belaran@999 | 6940 <para id="x_54b">Along the same lines, some commands normally print file |
belaran@999 | 6941 names relative to the root of the repository, even if you're |
belaran@999 | 6942 invoking them from a subdirectory. Such a command will print |
belaran@999 | 6943 file names relative to your subdirectory if you give it explicit |
belaran@999 | 6944 names. Here, we're going to run <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 6945 status</command> from a subdirectory, and get it to operate on |
belaran@999 | 6946 the entire working directory while printing file names relative |
belaran@999 | 6947 to our subdirectory, by passing it the output of the <command role="hg-cmd" moreinfo="none">hg root</command> command.</para> |
belaran@999 | 6948 |
belaran@999 | 6949 <!-- BEGIN filenames.wdir-relname --> |
belaran@999 | 6950 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 6951 A COPYING |
belaran@999 | 6952 A README |
belaran@999 | 6953 A examples/simple.py |
belaran@999 | 6954 ? MANIFEST.in |
belaran@999 | 6955 ? examples/performant.py |
belaran@999 | 6956 ? setup.py |
belaran@999 | 6957 ? src/main.py |
belaran@999 | 6958 ? src/watcher/_watcher.c |
belaran@999 | 6959 ? src/watcher/watcher.py |
belaran@999 | 6960 ? src/xyzzy.txt |
belaran@999 | 6961 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput> |
belaran@999 | 6962 A ../COPYING |
belaran@999 | 6963 A ../README |
belaran@999 | 6964 A ../examples/simple.py |
belaran@999 | 6965 ? ../MANIFEST.in |
belaran@999 | 6966 ? ../examples/performant.py |
belaran@999 | 6967 ? ../setup.py |
belaran@999 | 6968 ? main.py |
belaran@999 | 6969 ? watcher/_watcher.c |
belaran@999 | 6970 ? watcher/watcher.py |
belaran@999 | 6971 ? xyzzy.txt |
belaran@999 | 6972 </screen> |
belaran@999 | 6973 <!-- END filenames.wdir-relname --> |
belaran@999 | 6974 |
belaran@999 | 6975 </sect1> |
belaran@999 | 6976 |
belaran@999 | 6977 <sect1> |
belaran@999 | 6978 <title>Telling you what's going on</title> |
belaran@999 | 6979 |
belaran@999 | 6980 <para id="x_54c">The <command role="hg-cmd" moreinfo="none">hg add</command> example in the |
belaran@999 | 6981 preceding section illustrates something else that's helpful |
belaran@999 | 6982 about Mercurial commands. If a command operates on a file that |
belaran@999 | 6983 you didn't name explicitly on the command line, it will usually |
belaran@999 | 6984 print the name of the file, so that you will not be surprised |
belaran@999 | 6985 what's going on.</para> |
belaran@999 | 6986 |
belaran@999 | 6987 <para id="x_54d">The principle here is of <emphasis>least |
belaran@999 | 6988 surprise</emphasis>. If you've exactly named a file on the |
belaran@999 | 6989 command line, there's no point in repeating it back at you. If |
belaran@999 | 6990 Mercurial is acting on a file <emphasis>implicitly</emphasis>, e.g. |
belaran@999 | 6991 because you provided no names, or a directory, or a pattern (see |
belaran@999 | 6992 below), it is safest to tell you what files it's operating on.</para> |
belaran@999 | 6993 |
belaran@999 | 6994 <para id="x_54e">For commands that behave this way, you can silence them |
belaran@999 | 6995 using the <option role="hg-opt-global">-q</option> option. You |
belaran@999 | 6996 can also get them to print the name of every file, even those |
belaran@999 | 6997 you've named explicitly, using the <option role="hg-opt-global">-v</option> option.</para> |
belaran@999 | 6998 </sect1> |
belaran@999 | 6999 |
belaran@999 | 7000 <sect1> |
belaran@999 | 7001 <title>Using patterns to identify files</title> |
belaran@999 | 7002 |
belaran@999 | 7003 <para id="x_54f">In addition to working with file and directory names, |
belaran@999 | 7004 Mercurial lets you use <emphasis>patterns</emphasis> to identify |
belaran@999 | 7005 files. Mercurial's pattern handling is expressive.</para> |
belaran@999 | 7006 |
belaran@999 | 7007 <para id="x_550">On Unix-like systems (Linux, MacOS, etc.), the job of |
belaran@999 | 7008 matching file names to patterns normally falls to the shell. On |
belaran@999 | 7009 these systems, you must explicitly tell Mercurial that a name is |
belaran@999 | 7010 a pattern. On Windows, the shell does not expand patterns, so |
belaran@999 | 7011 Mercurial will automatically identify names that are patterns, |
belaran@999 | 7012 and expand them for you.</para> |
belaran@999 | 7013 |
belaran@999 | 7014 <para id="x_551">To provide a pattern in place of a regular name on the |
belaran@999 | 7015 command line, the mechanism is simple:</para> |
belaran@999 | 7016 <programlisting format="linespecific">syntax:patternbody</programlisting> |
belaran@999 | 7017 <para id="x_552">That is, a pattern is identified by a short text string that |
belaran@999 | 7018 says what kind of pattern this is, followed by a colon, followed |
belaran@999 | 7019 by the actual pattern.</para> |
belaran@999 | 7020 |
belaran@999 | 7021 <para id="x_553">Mercurial supports two kinds of pattern syntax. The most |
belaran@999 | 7022 frequently used is called <literal moreinfo="none">glob</literal>; this is the |
belaran@999 | 7023 same kind of pattern matching used by the Unix shell, and should |
belaran@999 | 7024 be familiar to Windows command prompt users, too.</para> |
belaran@999 | 7025 |
belaran@999 | 7026 <para id="x_554">When Mercurial does automatic pattern matching on Windows, |
belaran@999 | 7027 it uses <literal moreinfo="none">glob</literal> syntax. You can thus omit the |
belaran@999 | 7028 <quote><literal moreinfo="none">glob:</literal></quote> prefix on Windows, but |
belaran@999 | 7029 it's safe to use it, too.</para> |
belaran@999 | 7030 |
belaran@999 | 7031 <para id="x_555">The <literal moreinfo="none">re</literal> syntax is more powerful; it lets |
belaran@999 | 7032 you specify patterns using regular expressions, also known as |
belaran@999 | 7033 regexps.</para> |
belaran@999 | 7034 |
belaran@999 | 7035 <para id="x_556">By the way, in the examples that follow, notice that I'm |
belaran@999 | 7036 careful to wrap all of my patterns in quote characters, so that |
belaran@999 | 7037 they won't get expanded by the shell before Mercurial sees |
belaran@999 | 7038 them.</para> |
belaran@999 | 7039 |
belaran@999 | 7040 <sect2> |
belaran@999 | 7041 <title>Shell-style <literal moreinfo="none">glob</literal> patterns</title> |
belaran@999 | 7042 |
belaran@999 | 7043 <para id="x_557">This is an overview of the kinds of patterns you can use |
belaran@999 | 7044 when you're matching on glob patterns.</para> |
belaran@999 | 7045 |
belaran@999 | 7046 <para id="x_558">The <quote><literal moreinfo="none">*</literal></quote> character matches |
belaran@999 | 7047 any string, within a single directory.</para> |
belaran@999 | 7048 |
belaran@999 | 7049 <!-- BEGIN filenames.glob.star --> |
belaran@999 | 7050 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add 'glob:*.py'</userinput> |
belaran@999 | 7051 adding main.py |
belaran@999 | 7052 </screen> |
belaran@999 | 7053 <!-- END filenames.glob.star --> |
belaran@999 | 7054 |
belaran@999 | 7055 |
belaran@999 | 7056 <para id="x_559">The <quote><literal moreinfo="none">**</literal></quote> pattern matches |
belaran@999 | 7057 any string, and crosses directory boundaries. It's not a |
belaran@999 | 7058 standard Unix glob token, but it's accepted by several popular |
belaran@999 | 7059 Unix shells, and is very useful.</para> |
belaran@999 | 7060 |
belaran@999 | 7061 <!-- BEGIN filenames.glob.starstar --> |
belaran@999 | 7062 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 7063 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput> |
belaran@999 | 7064 A examples/simple.py |
belaran@999 | 7065 A src/main.py |
belaran@999 | 7066 ? examples/performant.py |
belaran@999 | 7067 ? setup.py |
belaran@999 | 7068 ? src/watcher/watcher.py |
belaran@999 | 7069 </screen> |
belaran@999 | 7070 <!-- END filenames.glob.starstar --> |
belaran@999 | 7071 |
belaran@999 | 7072 |
belaran@999 | 7073 <para id="x_55a">The <quote><literal moreinfo="none">?</literal></quote> pattern matches |
belaran@999 | 7074 any single character.</para> |
belaran@999 | 7075 |
belaran@999 | 7076 <!-- BEGIN filenames.glob.question --> |
belaran@999 | 7077 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.?'</userinput> |
belaran@999 | 7078 ? src/watcher/_watcher.c |
belaran@999 | 7079 </screen> |
belaran@999 | 7080 <!-- END filenames.glob.question --> |
belaran@999 | 7081 |
belaran@999 | 7082 |
belaran@999 | 7083 <para id="x_55b">The <quote><literal moreinfo="none">[</literal></quote> character begins a |
belaran@999 | 7084 <emphasis>character class</emphasis>. This matches any single |
belaran@999 | 7085 character within the class. The class ends with a |
belaran@999 | 7086 <quote><literal moreinfo="none">]</literal></quote> character. A class may |
belaran@999 | 7087 contain multiple <emphasis>range</emphasis>s of the form |
belaran@999 | 7088 <quote><literal moreinfo="none">a-f</literal></quote>, which is shorthand for |
belaran@999 | 7089 <quote><literal moreinfo="none">abcdef</literal></quote>.</para> |
belaran@999 | 7090 |
belaran@999 | 7091 <!-- BEGIN filenames.glob.range --> |
belaran@999 | 7092 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**[nr-t]'</userinput> |
belaran@999 | 7093 ? MANIFEST.in |
belaran@999 | 7094 ? src/xyzzy.txt |
belaran@999 | 7095 </screen> |
belaran@999 | 7096 <!-- END filenames.glob.range --> |
belaran@999 | 7097 |
belaran@999 | 7098 |
belaran@999 | 7099 <para id="x_55c">If the first character after the |
belaran@999 | 7100 <quote><literal moreinfo="none">[</literal></quote> in a character class is a |
belaran@999 | 7101 <quote><literal moreinfo="none">!</literal></quote>, it |
belaran@999 | 7102 <emphasis>negates</emphasis> the class, making it match any |
belaran@999 | 7103 single character not in the class.</para> |
belaran@999 | 7104 |
belaran@999 | 7105 <para id="x_55d">A <quote><literal moreinfo="none">{</literal></quote> begins a group of |
belaran@999 | 7106 subpatterns, where the whole group matches if any subpattern |
belaran@999 | 7107 in the group matches. The <quote><literal moreinfo="none">,</literal></quote> |
belaran@999 | 7108 character separates subpatterns, and |
belaran@999 | 7109 <quote><literal moreinfo="none">}</literal></quote> ends the group.</para> |
belaran@999 | 7110 |
belaran@999 | 7111 <!-- BEGIN filenames.glob.group --> |
belaran@999 | 7112 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.{in,py}'</userinput> |
belaran@999 | 7113 ? MANIFEST.in |
belaran@999 | 7114 ? setup.py |
belaran@999 | 7115 </screen> |
belaran@999 | 7116 <!-- END filenames.glob.group --> |
belaran@999 | 7117 |
belaran@999 | 7118 |
belaran@999 | 7119 <sect3> |
belaran@999 | 7120 <title>Watch out!</title> |
belaran@999 | 7121 |
belaran@999 | 7122 <para id="x_55e">Don't forget that if you want to match a pattern in any |
belaran@999 | 7123 directory, you should not be using the |
belaran@999 | 7124 <quote><literal moreinfo="none">*</literal></quote> match-any token, as this |
belaran@999 | 7125 will only match within one directory. Instead, use the |
belaran@999 | 7126 <quote><literal moreinfo="none">**</literal></quote> token. This small |
belaran@999 | 7127 example illustrates the difference between the two.</para> |
belaran@999 | 7128 |
belaran@999 | 7129 <!-- BEGIN filenames.glob.star-starstar --> |
belaran@999 | 7130 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:*.py'</userinput> |
belaran@999 | 7131 ? setup.py |
belaran@999 | 7132 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status 'glob:**.py'</userinput> |
belaran@999 | 7133 A examples/simple.py |
belaran@999 | 7134 A src/main.py |
belaran@999 | 7135 ? examples/performant.py |
belaran@999 | 7136 ? setup.py |
belaran@999 | 7137 ? src/watcher/watcher.py |
belaran@999 | 7138 </screen> |
belaran@999 | 7139 <!-- END filenames.glob.star-starstar --> |
belaran@999 | 7140 |
belaran@999 | 7141 </sect3> |
belaran@999 | 7142 </sect2> |
belaran@999 | 7143 |
belaran@999 | 7144 <sect2> |
belaran@999 | 7145 <title>Regular expression matching with <literal moreinfo="none">re</literal> |
belaran@999 | 7146 patterns</title> |
belaran@999 | 7147 |
belaran@999 | 7148 <para id="x_55f">Mercurial accepts the same regular expression syntax as |
belaran@999 | 7149 the Python programming language (it uses Python's regexp |
belaran@999 | 7150 engine internally). This is based on the Perl language's |
belaran@999 | 7151 regexp syntax, which is the most popular dialect in use (it's |
belaran@999 | 7152 also used in Java, for example).</para> |
belaran@999 | 7153 |
belaran@999 | 7154 <para id="x_560">I won't discuss Mercurial's regexp dialect in any detail |
belaran@999 | 7155 here, as regexps are not often used. Perl-style regexps are |
belaran@999 | 7156 in any case already exhaustively documented on a multitude of |
belaran@999 | 7157 web sites, and in many books. Instead, I will focus here on a |
belaran@999 | 7158 few things you should know if you find yourself needing to use |
belaran@999 | 7159 regexps with Mercurial.</para> |
belaran@999 | 7160 |
belaran@999 | 7161 <para id="x_561">A regexp is matched against an entire file name, relative |
belaran@999 | 7162 to the root of the repository. In other words, even if you're |
belaran@999 | 7163 already in subbdirectory <filename class="directory" moreinfo="none">foo</filename>, if you want to match files |
belaran@999 | 7164 under this directory, your pattern must start with |
belaran@999 | 7165 <quote><literal moreinfo="none">foo/</literal></quote>.</para> |
belaran@999 | 7166 |
belaran@999 | 7167 <para id="x_562">One thing to note, if you're familiar with Perl-style |
belaran@999 | 7168 regexps, is that Mercurial's are <emphasis>rooted</emphasis>. |
belaran@999 | 7169 That is, a regexp starts matching against the beginning of a |
belaran@999 | 7170 string; it doesn't look for a match anywhere within the |
belaran@999 | 7171 string. To match anywhere in a string, start your pattern |
belaran@999 | 7172 with <quote><literal moreinfo="none">.*</literal></quote>.</para> |
belaran@999 | 7173 </sect2> |
belaran@999 | 7174 </sect1> |
belaran@999 | 7175 |
belaran@999 | 7176 <sect1> |
belaran@999 | 7177 <title>Filtering files</title> |
belaran@999 | 7178 |
belaran@999 | 7179 <para id="x_563">Not only does Mercurial give you a variety of ways to |
belaran@999 | 7180 specify files; it lets you further winnow those files using |
belaran@999 | 7181 <emphasis>filters</emphasis>. Commands that work with file |
belaran@999 | 7182 names accept two filtering options.</para> |
belaran@999 | 7183 <itemizedlist> |
belaran@999 | 7184 <listitem><para id="x_564"><option role="hg-opt-global">-I</option>, or |
belaran@999 | 7185 <option role="hg-opt-global">--include</option>, lets you |
belaran@999 | 7186 specify a pattern that file names must match in order to be |
belaran@999 | 7187 processed.</para> |
belaran@999 | 7188 </listitem> |
belaran@999 | 7189 <listitem><para id="x_565"><option role="hg-opt-global">-X</option>, or |
belaran@999 | 7190 <option role="hg-opt-global">--exclude</option>, gives you a |
belaran@999 | 7191 way to <emphasis>avoid</emphasis> processing files, if they |
belaran@999 | 7192 match this pattern.</para> |
belaran@999 | 7193 </listitem></itemizedlist> |
belaran@999 | 7194 <para id="x_566">You can provide multiple <option role="hg-opt-global">-I</option> and <option role="hg-opt-global">-X</option> options on the command line, |
belaran@999 | 7195 and intermix them as you please. Mercurial interprets the |
belaran@999 | 7196 patterns you provide using glob syntax by default (but you can |
belaran@999 | 7197 use regexps if you need to).</para> |
belaran@999 | 7198 |
belaran@999 | 7199 <para id="x_567">You can read a <option role="hg-opt-global">-I</option> |
belaran@999 | 7200 filter as <quote>process only the files that match this |
belaran@999 | 7201 filter</quote>.</para> |
belaran@999 | 7202 |
belaran@999 | 7203 <!-- BEGIN filenames.filter.include --> |
belaran@999 | 7204 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -I '*.in'</userinput> |
belaran@999 | 7205 ? MANIFEST.in |
belaran@999 | 7206 </screen> |
belaran@999 | 7207 <!-- END filenames.filter.include --> |
belaran@999 | 7208 |
belaran@999 | 7209 |
belaran@999 | 7210 <para id="x_568">The <option role="hg-opt-global">-X</option> filter is best |
belaran@999 | 7211 read as <quote>process only the files that don't match this |
belaran@999 | 7212 pattern</quote>.</para> |
belaran@999 | 7213 |
belaran@999 | 7214 <!-- BEGIN filenames.filter.exclude --> |
belaran@999 | 7215 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status -X '**.py' src</userinput> |
belaran@999 | 7216 ? src/watcher/_watcher.c |
belaran@999 | 7217 ? src/xyzzy.txt |
belaran@999 | 7218 </screen> |
belaran@999 | 7219 <!-- END filenames.filter.exclude --> |
belaran@999 | 7220 |
belaran@999 | 7221 </sect1> |
belaran@999 | 7222 |
belaran@999 | 7223 <sect1> |
belaran@999 | 7224 <title>Permanently ignoring unwanted files and directories</title> |
belaran@999 | 7225 |
belaran@999 | 7226 <para id="x_569">When you create a new repository, the chances are |
belaran@999 | 7227 that over time it will grow to contain files that ought to |
belaran@999 | 7228 <emphasis>not</emphasis> be managed by Mercurial, but which you |
belaran@999 | 7229 don't want to see listed every time you run <command moreinfo="none">hg |
belaran@999 | 7230 status</command>. For instance, <quote>build products</quote> |
belaran@999 | 7231 are files that are created as part of a build but which should |
belaran@999 | 7232 not be managed by a revision control system. The most common |
belaran@999 | 7233 build products are output files produced by software tools such |
belaran@999 | 7234 as compilers. As another example, many text editors litter a |
belaran@999 | 7235 directory with lock files, temporary working files, and backup |
belaran@999 | 7236 files, which it also makes no sense to manage.</para> |
belaran@999 | 7237 |
belaran@999 | 7238 <para id="x_6b4">To have Mercurial permanently ignore such files, create a |
belaran@999 | 7239 file named <filename moreinfo="none">.hgignore</filename> in the root of your |
belaran@999 | 7240 repository. You <emphasis>should</emphasis> <command moreinfo="none">hg |
belaran@999 | 7241 add</command> this file so that it gets tracked with the rest of |
belaran@999 | 7242 your repository contents, since your collaborators will probably |
belaran@999 | 7243 find it useful too.</para> |
belaran@999 | 7244 |
belaran@999 | 7245 <para id="x_6b5">By default, the <filename moreinfo="none">.hgignore</filename> file should |
belaran@999 | 7246 contain a list of regular expressions, one per line. Empty |
belaran@999 | 7247 lines are skipped. Most people prefer to describe the files they |
belaran@999 | 7248 want to ignore using the <quote>glob</quote> syntax that we |
belaran@999 | 7249 described above, so a typical <filename moreinfo="none">.hgignore</filename> |
belaran@999 | 7250 file will start with this directive:</para> |
belaran@999 | 7251 |
belaran@999 | 7252 <programlisting format="linespecific">syntax: glob</programlisting> |
belaran@999 | 7253 |
belaran@999 | 7254 <para id="x_6b6">This tells Mercurial to interpret the lines that follow as |
belaran@999 | 7255 glob patterns, not regular expressions.</para> |
belaran@999 | 7256 |
belaran@999 | 7257 <para id="x_6b7">Here is a typical-looking <filename moreinfo="none">.hgignore</filename> |
belaran@999 | 7258 file.</para> |
belaran@999 | 7259 |
belaran@999 | 7260 <programlisting format="linespecific">syntax: glob |
belaran@999 | 7261 # This line is a comment, and will be skipped. |
belaran@999 | 7262 # Empty lines are skipped too. |
belaran@999 | 7263 |
belaran@999 | 7264 # Backup files left behind by the Emacs editor. |
belaran@999 | 7265 *~ |
belaran@999 | 7266 |
belaran@999 | 7267 # Lock files used by the Emacs editor. |
belaran@999 | 7268 # Notice that the "#" character is quoted with a backslash. |
belaran@999 | 7269 # This prevents it from being interpreted as starting a comment. |
belaran@999 | 7270 .\#* |
belaran@999 | 7271 |
belaran@999 | 7272 # Temporary files used by the vim editor. |
belaran@999 | 7273 .*.swp |
belaran@999 | 7274 |
belaran@999 | 7275 # A hidden file created by the Mac OS X Finder. |
belaran@999 | 7276 .DS_Store |
belaran@999 | 7277 </programlisting> |
belaran@999 | 7278 </sect1> |
belaran@999 | 7279 |
belaran@999 | 7280 <sect1 id="sec:names:case"> |
belaran@999 | 7281 <title>Case sensitivity</title> |
belaran@999 | 7282 |
belaran@999 | 7283 <para id="x_56a">If you're working in a mixed development environment that |
belaran@999 | 7284 contains both Linux (or other Unix) systems and Macs or Windows |
belaran@999 | 7285 systems, you should keep in the back of your mind the knowledge |
belaran@999 | 7286 that they treat the case (<quote>N</quote> versus |
belaran@999 | 7287 <quote>n</quote>) of file names in incompatible ways. This is |
belaran@999 | 7288 not very likely to affect you, and it's easy to deal with if it |
belaran@999 | 7289 does, but it could surprise you if you don't know about |
belaran@999 | 7290 it.</para> |
belaran@999 | 7291 |
belaran@999 | 7292 <para id="x_56b">Operating systems and filesystems differ in the way they |
belaran@999 | 7293 handle the <emphasis>case</emphasis> of characters in file and |
belaran@999 | 7294 directory names. There are three common ways to handle case in |
belaran@999 | 7295 names.</para> |
belaran@999 | 7296 <itemizedlist> |
belaran@999 | 7297 <listitem><para id="x_56c">Completely case insensitive. Uppercase and |
belaran@999 | 7298 lowercase versions of a letter are treated as identical, |
belaran@999 | 7299 both when creating a file and during subsequent accesses. |
belaran@999 | 7300 This is common on older DOS-based systems.</para> |
belaran@999 | 7301 </listitem> |
belaran@999 | 7302 <listitem><para id="x_56d">Case preserving, but insensitive. When a file |
belaran@999 | 7303 or directory is created, the case of its name is stored, and |
belaran@999 | 7304 can be retrieved and displayed by the operating system. |
belaran@999 | 7305 When an existing file is being looked up, its case is |
belaran@999 | 7306 ignored. This is the standard arrangement on Windows and |
belaran@999 | 7307 MacOS. The names <filename moreinfo="none">foo</filename> and |
belaran@999 | 7308 <filename moreinfo="none">FoO</filename> identify the same file. This |
belaran@999 | 7309 treatment of uppercase and lowercase letters as |
belaran@999 | 7310 interchangeable is also referred to as <emphasis>case |
belaran@999 | 7311 folding</emphasis>.</para> |
belaran@999 | 7312 </listitem> |
belaran@999 | 7313 <listitem><para id="x_56e">Case sensitive. The case of a name |
belaran@999 | 7314 is significant at all times. The names |
belaran@999 | 7315 <filename moreinfo="none">foo</filename> and <filename moreinfo="none">FoO</filename> |
belaran@999 | 7316 identify different files. This is the way Linux and Unix |
belaran@999 | 7317 systems normally work.</para> |
belaran@999 | 7318 </listitem></itemizedlist> |
belaran@999 | 7319 |
belaran@999 | 7320 <para id="x_56f">On Unix-like systems, it is possible to have any or all of |
belaran@999 | 7321 the above ways of handling case in action at once. For example, |
belaran@999 | 7322 if you use a USB thumb drive formatted with a FAT32 filesystem |
belaran@999 | 7323 on a Linux system, Linux will handle names on that filesystem in |
belaran@999 | 7324 a case preserving, but insensitive, way.</para> |
belaran@999 | 7325 |
belaran@999 | 7326 <sect2> |
belaran@999 | 7327 <title>Safe, portable repository storage</title> |
belaran@999 | 7328 |
belaran@999 | 7329 <para id="x_570">Mercurial's repository storage mechanism is <emphasis>case |
belaran@999 | 7330 safe</emphasis>. It translates file names so that they can |
belaran@999 | 7331 be safely stored on both case sensitive and case insensitive |
belaran@999 | 7332 filesystems. This means that you can use normal file copying |
belaran@999 | 7333 tools to transfer a Mercurial repository onto, for example, a |
belaran@999 | 7334 USB thumb drive, and safely move that drive and repository |
belaran@999 | 7335 back and forth between a Mac, a PC running Windows, and a |
belaran@999 | 7336 Linux box.</para> |
belaran@999 | 7337 |
belaran@999 | 7338 </sect2> |
belaran@999 | 7339 <sect2> |
belaran@999 | 7340 <title>Detecting case conflicts</title> |
belaran@999 | 7341 |
belaran@999 | 7342 <para id="x_571">When operating in the working directory, Mercurial honours |
belaran@999 | 7343 the naming policy of the filesystem where the working |
belaran@999 | 7344 directory is located. If the filesystem is case preserving, |
belaran@999 | 7345 but insensitive, Mercurial will treat names that differ only |
belaran@999 | 7346 in case as the same.</para> |
belaran@999 | 7347 |
belaran@999 | 7348 <para id="x_572">An important aspect of this approach is that it is |
belaran@999 | 7349 possible to commit a changeset on a case sensitive (typically |
belaran@999 | 7350 Linux or Unix) filesystem that will cause trouble for users on |
belaran@999 | 7351 case insensitive (usually Windows and MacOS) users. If a |
belaran@999 | 7352 Linux user commits changes to two files, one named |
belaran@999 | 7353 <filename moreinfo="none">myfile.c</filename> and the other named |
belaran@999 | 7354 <filename moreinfo="none">MyFile.C</filename>, they will be stored correctly |
belaran@999 | 7355 in the repository. And in the working directories of other |
belaran@999 | 7356 Linux users, they will be correctly represented as separate |
belaran@999 | 7357 files.</para> |
belaran@999 | 7358 |
belaran@999 | 7359 <para id="x_573">If a Windows or Mac user pulls this change, they will not |
belaran@999 | 7360 initially have a problem, because Mercurial's repository |
belaran@999 | 7361 storage mechanism is case safe. However, once they try to |
belaran@999 | 7362 <command role="hg-cmd" moreinfo="none">hg update</command> the working |
belaran@999 | 7363 directory to that changeset, or <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7364 merge</command> with that changeset, Mercurial will spot the |
belaran@999 | 7365 conflict between the two file names that the filesystem would |
belaran@999 | 7366 treat as the same, and forbid the update or merge from |
belaran@999 | 7367 occurring.</para> |
belaran@999 | 7368 </sect2> |
belaran@999 | 7369 |
belaran@999 | 7370 <sect2> |
belaran@999 | 7371 <title>Fixing a case conflict</title> |
belaran@999 | 7372 |
belaran@999 | 7373 <para id="x_574">If you are using Windows or a Mac in a mixed environment |
belaran@999 | 7374 where some of your collaborators are using Linux or Unix, and |
belaran@999 | 7375 Mercurial reports a case folding conflict when you try to |
belaran@999 | 7376 <command role="hg-cmd" moreinfo="none">hg update</command> or <command role="hg-cmd" moreinfo="none">hg merge</command>, the procedure to fix the |
belaran@999 | 7377 problem is simple.</para> |
belaran@999 | 7378 |
belaran@999 | 7379 <para id="x_575">Just find a nearby Linux or Unix box, clone the problem |
belaran@999 | 7380 repository onto it, and use Mercurial's <command role="hg-cmd" moreinfo="none">hg rename</command> command to change the |
belaran@999 | 7381 names of any offending files or directories so that they will |
belaran@999 | 7382 no longer cause case folding conflicts. Commit this change, |
belaran@999 | 7383 <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg push</command> it across to your Windows or |
belaran@999 | 7384 MacOS system, and <command role="hg-cmd" moreinfo="none">hg update</command> |
belaran@999 | 7385 to the revision with the non-conflicting names.</para> |
belaran@999 | 7386 |
belaran@999 | 7387 <para id="x_576">The changeset with case-conflicting names will remain in |
belaran@999 | 7388 your project's history, and you still won't be able to |
belaran@999 | 7389 <command role="hg-cmd" moreinfo="none">hg update</command> your working |
belaran@999 | 7390 directory to that changeset on a Windows or MacOS system, but |
belaran@999 | 7391 you can continue development unimpeded.</para> |
belaran@999 | 7392 </sect2> |
belaran@999 | 7393 </sect1> |
belaran@999 | 7394 </chapter> |
belaran@999 | 7395 |
belaran@999 | 7396 <!-- |
belaran@999 | 7397 local variables: |
belaran@999 | 7398 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 7399 end: |
belaran@999 | 7400 --> |
belaran@999 | 7401 |
belaran@999 | 7402 <!-- BEGIN ch08 --> |
belaran@999 | 7403 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 7404 |
belaran@999 | 7405 <chapter id="chap:branch"> |
belaran@999 | 7406 <?dbhtml filename="managing-releases-and-branchy-development.html"?> |
belaran@999 | 7407 <title>Managing releases and branchy development</title> |
belaran@999 | 7408 |
belaran@999 | 7409 <para id="x_369">Mercurial provides several mechanisms for you to manage a |
belaran@999 | 7410 project that is making progress on multiple fronts at once. To |
belaran@999 | 7411 understand these mechanisms, let's first take a brief look at a |
belaran@999 | 7412 fairly normal software project structure.</para> |
belaran@999 | 7413 |
belaran@999 | 7414 <para id="x_36a">Many software projects issue periodic <quote>major</quote> |
belaran@999 | 7415 releases that contain substantial new features. In parallel, they |
belaran@999 | 7416 may issue <quote>minor</quote> releases. These are usually |
belaran@999 | 7417 identical to the major releases off which they're based, but with |
belaran@999 | 7418 a few bugs fixed.</para> |
belaran@999 | 7419 |
belaran@999 | 7420 <para id="x_36b">In this chapter, we'll start by talking about how to keep |
belaran@999 | 7421 records of project milestones such as releases. We'll then |
belaran@999 | 7422 continue on to talk about the flow of work between different |
belaran@999 | 7423 phases of a project, and how Mercurial can help you to isolate and |
belaran@999 | 7424 manage this work.</para> |
belaran@999 | 7425 |
belaran@999 | 7426 <sect1> |
belaran@999 | 7427 <title>Giving a persistent name to a revision</title> |
belaran@999 | 7428 |
belaran@999 | 7429 <para id="x_36c">Once you decide that you'd like to call a particular |
belaran@999 | 7430 revision a <quote>release</quote>, it's a good idea to record |
belaran@999 | 7431 the identity of that revision. This will let you reproduce that |
belaran@999 | 7432 release at a later date, for whatever purpose you might need at |
belaran@999 | 7433 the time (reproducing a bug, porting to a new platform, etc). |
belaran@999 | 7434 <!-- BEGIN tag.init --> |
belaran@999 | 7435 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mytag</userinput> |
belaran@999 | 7436 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mytag</userinput> |
belaran@999 | 7437 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello > myfile</userinput> |
belaran@999 | 7438 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Initial commit'</userinput> |
belaran@999 | 7439 adding myfile |
belaran@999 | 7440 </screen> |
belaran@999 | 7441 <!-- END tag.init --> |
belaran@999 | 7442 </para> |
belaran@999 | 7443 |
belaran@999 | 7444 <para id="x_36d">Mercurial lets you give a permanent name to any revision |
belaran@999 | 7445 using the <command role="hg-cmd" moreinfo="none">hg tag</command> command. Not |
belaran@999 | 7446 surprisingly, these names are called <quote>tags</quote>.</para> |
belaran@999 | 7447 |
belaran@999 | 7448 <!-- BEGIN tag.tag --> |
belaran@999 | 7449 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput> |
belaran@999 | 7450 </screen> |
belaran@999 | 7451 <!-- END tag.tag --> |
belaran@999 | 7452 |
belaran@999 | 7453 |
belaran@999 | 7454 <para id="x_36e">A tag is nothing more than a <quote>symbolic name</quote> |
belaran@999 | 7455 for a revision. Tags exist purely for your convenience, so that |
belaran@999 | 7456 you have a handy permanent way to refer to a revision; Mercurial |
belaran@999 | 7457 doesn't interpret the tag names you use in any way. Neither |
belaran@999 | 7458 does Mercurial place any restrictions on the name of a tag, |
belaran@999 | 7459 beyond a few that are necessary to ensure that a tag can be |
belaran@999 | 7460 parsed unambiguously. A tag name cannot contain any of the |
belaran@999 | 7461 following characters:</para> |
belaran@999 | 7462 <itemizedlist> |
belaran@999 | 7463 <listitem><para id="x_36f">Colon (ASCII 58, |
belaran@999 | 7464 <quote><literal moreinfo="none">:</literal></quote>)</para> |
belaran@999 | 7465 </listitem> |
belaran@999 | 7466 <listitem><para id="x_370">Carriage return (ASCII 13, |
belaran@999 | 7467 <quote><literal moreinfo="none">\r</literal></quote>)</para> |
belaran@999 | 7468 </listitem> |
belaran@999 | 7469 <listitem><para id="x_371">Newline (ASCII 10, |
belaran@999 | 7470 <quote><literal moreinfo="none">\n</literal></quote>)</para> |
belaran@999 | 7471 </listitem></itemizedlist> |
belaran@999 | 7472 |
belaran@999 | 7473 <para id="x_372">You can use the <command role="hg-cmd" moreinfo="none">hg tags</command> |
belaran@999 | 7474 command to display the tags present in your repository. In the |
belaran@999 | 7475 output, each tagged revision is identified first by its name, |
belaran@999 | 7476 then by revision number, and finally by the unique hash of the |
belaran@999 | 7477 revision.</para> |
belaran@999 | 7478 |
belaran@999 | 7479 <!-- BEGIN tag.tags --> |
belaran@999 | 7480 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> |
belaran@999 | 7481 tip 1:f283c2669b38 |
belaran@999 | 7482 v1.0 0:0c957785065f |
belaran@999 | 7483 </screen> |
belaran@999 | 7484 <!-- END tag.tags --> |
belaran@999 | 7485 |
belaran@999 | 7486 |
belaran@999 | 7487 <para id="x_373">Notice that <literal moreinfo="none">tip</literal> is listed in the output |
belaran@999 | 7488 of <command role="hg-cmd" moreinfo="none">hg tags</command>. The |
belaran@999 | 7489 <literal moreinfo="none">tip</literal> tag is a special <quote>floating</quote> |
belaran@999 | 7490 tag, which always identifies the newest revision in the |
belaran@999 | 7491 repository.</para> |
belaran@999 | 7492 |
belaran@999 | 7493 <para id="x_374">In the output of the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7494 tags</command> command, tags are listed in reverse order, by |
belaran@999 | 7495 revision number. This usually means that recent tags are listed |
belaran@999 | 7496 before older tags. It also means that <literal moreinfo="none">tip</literal> is |
belaran@999 | 7497 always going to be the first tag listed in the output of |
belaran@999 | 7498 <command role="hg-cmd" moreinfo="none">hg tags</command>.</para> |
belaran@999 | 7499 |
belaran@999 | 7500 <para id="x_375">When you run <command role="hg-cmd" moreinfo="none">hg log</command>, if it |
belaran@999 | 7501 displays a revision that has tags associated with it, it will |
belaran@999 | 7502 print those tags.</para> |
belaran@999 | 7503 |
belaran@999 | 7504 <!-- BEGIN tag.log --> |
belaran@999 | 7505 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log</userinput> |
belaran@999 | 7506 changeset: 1:f283c2669b38 |
belaran@999 | 7507 tag: tip |
belaran@999 | 7508 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7509 date: Sun Aug 16 14:05:16 2009 +0000 |
belaran@999 | 7510 summary: Added tag v1.0 for changeset 0c957785065f |
belaran@999 | 7511 |
belaran@999 | 7512 changeset: 0:0c957785065f |
belaran@999 | 7513 tag: v1.0 |
belaran@999 | 7514 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7515 date: Sun Aug 16 14:05:15 2009 +0000 |
belaran@999 | 7516 summary: Initial commit |
belaran@999 | 7517 |
belaran@999 | 7518 </screen> |
belaran@999 | 7519 <!-- END tag.log --> |
belaran@999 | 7520 |
belaran@999 | 7521 |
belaran@999 | 7522 <para id="x_376">Any time you need to provide a revision ID to a Mercurial |
belaran@999 | 7523 command, the command will accept a tag name in its place. |
belaran@999 | 7524 Internally, Mercurial will translate your tag name into the |
belaran@999 | 7525 corresponding revision ID, then use that.</para> |
belaran@999 | 7526 |
belaran@999 | 7527 <!-- BEGIN tag.log.v1.0 --> |
belaran@999 | 7528 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye > myfile2</userinput> |
belaran@999 | 7529 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Second commit'</userinput> |
belaran@999 | 7530 adding myfile2 |
belaran@999 | 7531 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r v1.0</userinput> |
belaran@999 | 7532 changeset: 0:0c957785065f |
belaran@999 | 7533 tag: v1.0 |
belaran@999 | 7534 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7535 date: Sun Aug 16 14:05:15 2009 +0000 |
belaran@999 | 7536 summary: Initial commit |
belaran@999 | 7537 |
belaran@999 | 7538 </screen> |
belaran@999 | 7539 <!-- END tag.log.v1.0 --> |
belaran@999 | 7540 |
belaran@999 | 7541 |
belaran@999 | 7542 <para id="x_377">There's no limit on the number of tags you can have in a |
belaran@999 | 7543 repository, or on the number of tags that a single revision can |
belaran@999 | 7544 have. As a practical matter, it's not a great idea to have |
belaran@999 | 7545 <quote>too many</quote> (a number which will vary from project |
belaran@999 | 7546 to project), simply because tags are supposed to help you to |
belaran@999 | 7547 find revisions. If you have lots of tags, the ease of using |
belaran@999 | 7548 them to identify revisions diminishes rapidly.</para> |
belaran@999 | 7549 |
belaran@999 | 7550 <para id="x_378">For example, if your project has milestones as frequent as |
belaran@999 | 7551 every few days, it's perfectly reasonable to tag each one of |
belaran@999 | 7552 those. But if you have a continuous build system that makes |
belaran@999 | 7553 sure every revision can be built cleanly, you'd be introducing a |
belaran@999 | 7554 lot of noise if you were to tag every clean build. Instead, you |
belaran@999 | 7555 could tag failed builds (on the assumption that they're rare!), |
belaran@999 | 7556 or simply not use tags to track buildability.</para> |
belaran@999 | 7557 |
belaran@999 | 7558 <para id="x_379">If you want to remove a tag that you no longer want, use |
belaran@999 | 7559 <command role="hg-cmd" moreinfo="none">hg tag --remove</command>.</para> |
belaran@999 | 7560 |
belaran@999 | 7561 <!-- BEGIN tag.remove --> |
belaran@999 | 7562 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag --remove v1.0</userinput> |
belaran@999 | 7563 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> |
belaran@999 | 7564 tip 3:0f446f1d1f7f |
belaran@999 | 7565 </screen> |
belaran@999 | 7566 <!-- END tag.remove --> |
belaran@999 | 7567 |
belaran@999 | 7568 |
belaran@999 | 7569 <para id="x_37a">You can also modify a tag at any time, so that it identifies |
belaran@999 | 7570 a different revision, by simply issuing a new <command role="hg-cmd" moreinfo="none">hg tag</command> command. You'll have to use the |
belaran@999 | 7571 <option role="hg-opt-tag">-f</option> option to tell Mercurial |
belaran@999 | 7572 that you <emphasis>really</emphasis> want to update the |
belaran@999 | 7573 tag.</para> |
belaran@999 | 7574 |
belaran@999 | 7575 <!-- BEGIN tag.replace --> |
belaran@999 | 7576 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 1 v1.1</userinput> |
belaran@999 | 7577 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> |
belaran@999 | 7578 tip 4:12fc7bf92915 |
belaran@999 | 7579 v1.1 1:f283c2669b38 |
belaran@999 | 7580 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -r 2 v1.1</userinput> |
belaran@999 | 7581 abort: tag 'v1.1' already exists (use -f to force) |
belaran@999 | 7582 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag -f -r 2 v1.1</userinput> |
belaran@999 | 7583 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tags</userinput> |
belaran@999 | 7584 tip 5:17e25cf010af |
belaran@999 | 7585 v1.1 2:737882b3cc76 |
belaran@999 | 7586 </screen> |
belaran@999 | 7587 <!-- END tag.replace --> |
belaran@999 | 7588 |
belaran@999 | 7589 |
belaran@999 | 7590 <para id="x_37b">There will still be a permanent record of the previous |
belaran@999 | 7591 identity of the tag, but Mercurial will no longer use it. |
belaran@999 | 7592 There's thus no penalty to tagging the wrong revision; all you |
belaran@999 | 7593 have to do is turn around and tag the correct revision once you |
belaran@999 | 7594 discover your error.</para> |
belaran@999 | 7595 |
belaran@999 | 7596 <para id="x_37c">Mercurial stores tags in a normal revision-controlled file |
belaran@999 | 7597 in your repository. If you've created any tags, you'll find |
belaran@999 | 7598 them in a file in the root of your repository named <filename role="special" moreinfo="none">.hgtags</filename>. When you run the <command role="hg-cmd" moreinfo="none">hg tag</command> command, Mercurial modifies |
belaran@999 | 7599 this file, then automatically commits the change to it. This |
belaran@999 | 7600 means that every time you run <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7601 tag</command>, you'll see a corresponding changeset in the |
belaran@999 | 7602 output of <command role="hg-cmd" moreinfo="none">hg log</command>.</para> |
belaran@999 | 7603 |
belaran@999 | 7604 <!-- BEGIN tag.tip --> |
belaran@999 | 7605 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 7606 changeset: 5:17e25cf010af |
belaran@999 | 7607 tag: tip |
belaran@999 | 7608 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7609 date: Sun Aug 16 14:05:16 2009 +0000 |
belaran@999 | 7610 summary: Added tag v1.1 for changeset 737882b3cc76 |
belaran@999 | 7611 |
belaran@999 | 7612 </screen> |
belaran@999 | 7613 <!-- END tag.tip --> |
belaran@999 | 7614 |
belaran@999 | 7615 |
belaran@999 | 7616 <sect2> |
belaran@999 | 7617 <title>Handling tag conflicts during a merge</title> |
belaran@999 | 7618 |
belaran@999 | 7619 <para id="x_37d">You won't often need to care about the <filename role="special" moreinfo="none">.hgtags</filename> file, but it sometimes |
belaran@999 | 7620 makes its presence known during a merge. The format of the |
belaran@999 | 7621 file is simple: it consists of a series of lines. Each line |
belaran@999 | 7622 starts with a changeset hash, followed by a space, followed by |
belaran@999 | 7623 the name of a tag.</para> |
belaran@999 | 7624 |
belaran@999 | 7625 <para id="x_37e">If you're resolving a conflict in the <filename role="special" moreinfo="none">.hgtags</filename> file during a merge, |
belaran@999 | 7626 there's one twist to modifying the <filename role="special" moreinfo="none">.hgtags</filename> file: when Mercurial is |
belaran@999 | 7627 parsing the tags in a repository, it |
belaran@999 | 7628 <emphasis>never</emphasis> reads the working copy of the |
belaran@999 | 7629 <filename role="special" moreinfo="none">.hgtags</filename> file. Instead, it |
belaran@999 | 7630 reads the <emphasis>most recently committed</emphasis> |
belaran@999 | 7631 revision of the file.</para> |
belaran@999 | 7632 |
belaran@999 | 7633 <para id="x_37f">An unfortunate consequence of this design is that you |
belaran@999 | 7634 can't actually verify that your merged <filename role="special" moreinfo="none">.hgtags</filename> file is correct until |
belaran@999 | 7635 <emphasis>after</emphasis> you've committed a change. So if |
belaran@999 | 7636 you find yourself resolving a conflict on <filename role="special" moreinfo="none">.hgtags</filename> during a merge, be sure to |
belaran@999 | 7637 run <command role="hg-cmd" moreinfo="none">hg tags</command> after you commit. |
belaran@999 | 7638 If it finds an error in the <filename role="special" moreinfo="none">.hgtags</filename> file, it will report the |
belaran@999 | 7639 location of the error, which you can then fix and commit. You |
belaran@999 | 7640 should then run <command role="hg-cmd" moreinfo="none">hg tags</command> |
belaran@999 | 7641 again, just to be sure that your fix is correct.</para> |
belaran@999 | 7642 </sect2> |
belaran@999 | 7643 |
belaran@999 | 7644 <sect2> |
belaran@999 | 7645 <title>Tags and cloning</title> |
belaran@999 | 7646 |
belaran@999 | 7647 <para id="x_380">You may have noticed that the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7648 clone</command> command has a <option role="hg-opt-clone">-r</option> option that lets you clone |
belaran@999 | 7649 an exact copy of the repository as of a particular changeset. |
belaran@999 | 7650 The new clone will not contain any project history that comes |
belaran@999 | 7651 after the revision you specified. This has an interaction |
belaran@999 | 7652 with tags that can surprise the unwary.</para> |
belaran@999 | 7653 |
belaran@999 | 7654 <para id="x_381">Recall that a tag is stored as a revision to |
belaran@999 | 7655 the <filename role="special" moreinfo="none">.hgtags</filename> file. When you |
belaran@999 | 7656 create a tag, the changeset in which its recorded refers to an |
belaran@999 | 7657 older changeset. When you run <command role="hg-cmd" moreinfo="none">hg clone |
belaran@999 | 7658 -r foo</command> to clone a repository as of tag |
belaran@999 | 7659 <literal moreinfo="none">foo</literal>, the new clone <emphasis>will not |
belaran@999 | 7660 contain any revision newer than the one the tag refers to, |
belaran@999 | 7661 including the revision where the tag was created</emphasis>. |
belaran@999 | 7662 The result is that you'll get exactly the right subset of the |
belaran@999 | 7663 project's history in the new repository, but |
belaran@999 | 7664 <emphasis>not</emphasis> the tag you might have |
belaran@999 | 7665 expected.</para> |
belaran@999 | 7666 </sect2> |
belaran@999 | 7667 |
belaran@999 | 7668 <sect2> |
belaran@999 | 7669 <title>When permanent tags are too much</title> |
belaran@999 | 7670 |
belaran@999 | 7671 <para id="x_382">Since Mercurial's tags are revision controlled and carried |
belaran@999 | 7672 around with a project's history, everyone you work with will |
belaran@999 | 7673 see the tags you create. But giving names to revisions has |
belaran@999 | 7674 uses beyond simply noting that revision |
belaran@999 | 7675 <literal moreinfo="none">4237e45506ee</literal> is really |
belaran@999 | 7676 <literal moreinfo="none">v2.0.2</literal>. If you're trying to track down a |
belaran@999 | 7677 subtle bug, you might want a tag to remind you of something |
belaran@999 | 7678 like <quote>Anne saw the symptoms with this |
belaran@999 | 7679 revision</quote>.</para> |
belaran@999 | 7680 |
belaran@999 | 7681 <para id="x_383">For cases like this, what you might want to use are |
belaran@999 | 7682 <emphasis>local</emphasis> tags. You can create a local tag |
belaran@999 | 7683 with the <option role="hg-opt-tag">-l</option> option to the |
belaran@999 | 7684 <command role="hg-cmd" moreinfo="none">hg tag</command> command. This will |
belaran@999 | 7685 store the tag in a file called <filename role="special" moreinfo="none">.hg/localtags</filename>. Unlike <filename role="special" moreinfo="none">.hgtags</filename>, <filename role="special" moreinfo="none">.hg/localtags</filename> is not revision |
belaran@999 | 7686 controlled. Any tags you create using <option role="hg-opt-tag">-l</option> remain strictly local to the |
belaran@999 | 7687 repository you're currently working in.</para> |
belaran@999 | 7688 </sect2> |
belaran@999 | 7689 </sect1> |
belaran@999 | 7690 |
belaran@999 | 7691 <sect1> |
belaran@999 | 7692 <title>The flow of changes—big picture vs. little</title> |
belaran@999 | 7693 |
belaran@999 | 7694 <para id="x_384">To return to the outline I sketched at the |
belaran@999 | 7695 beginning of the chapter, let's think about a project that has |
belaran@999 | 7696 multiple concurrent pieces of work under development at |
belaran@999 | 7697 once.</para> |
belaran@999 | 7698 |
belaran@999 | 7699 <para id="x_385">There might be a push for a new <quote>main</quote> release; |
belaran@999 | 7700 a new minor bugfix release to the last main release; and an |
belaran@999 | 7701 unexpected <quote>hot fix</quote> to an old release that is now |
belaran@999 | 7702 in maintenance mode.</para> |
belaran@999 | 7703 |
belaran@999 | 7704 <para id="x_386">The usual way people refer to these different concurrent |
belaran@999 | 7705 directions of development is as <quote>branches</quote>. |
belaran@999 | 7706 However, we've already seen numerous times that Mercurial treats |
belaran@999 | 7707 <emphasis>all of history</emphasis> as a series of branches and |
belaran@999 | 7708 merges. Really, what we have here is two ideas that are |
belaran@999 | 7709 peripherally related, but which happen to share a name.</para> |
belaran@999 | 7710 <itemizedlist> |
belaran@999 | 7711 <listitem><para id="x_387"><quote>Big picture</quote> branches represent |
belaran@999 | 7712 the sweep of a project's evolution; people give them names, |
belaran@999 | 7713 and talk about them in conversation.</para> |
belaran@999 | 7714 </listitem> |
belaran@999 | 7715 <listitem><para id="x_388"><quote>Little picture</quote> branches are |
belaran@999 | 7716 artefacts of the day-to-day activity of developing and |
belaran@999 | 7717 merging changes. They expose the narrative of how the code |
belaran@999 | 7718 was developed.</para> |
belaran@999 | 7719 </listitem></itemizedlist> |
belaran@999 | 7720 </sect1> |
belaran@999 | 7721 |
belaran@999 | 7722 <sect1> |
belaran@999 | 7723 <title>Managing big-picture branches in repositories</title> |
belaran@999 | 7724 |
belaran@999 | 7725 <para id="x_389">The easiest way to isolate a <quote>big picture</quote> |
belaran@999 | 7726 branch in Mercurial is in a dedicated repository. If you have |
belaran@999 | 7727 an existing shared repository—let's call it |
belaran@999 | 7728 <literal moreinfo="none">myproject</literal>—that reaches a |
belaran@999 | 7729 <quote>1.0</quote> milestone, you can start to prepare for |
belaran@999 | 7730 future maintenance releases on top of version 1.0 by tagging the |
belaran@999 | 7731 revision from which you prepared the 1.0 release.</para> |
belaran@999 | 7732 |
belaran@999 | 7733 <!-- BEGIN branch-repo.tag --> |
belaran@999 | 7734 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject</userinput> |
belaran@999 | 7735 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tag v1.0</userinput> |
belaran@999 | 7736 </screen> |
belaran@999 | 7737 <!-- END branch-repo.tag --> |
belaran@999 | 7738 |
belaran@999 | 7739 |
belaran@999 | 7740 <para id="x_38a">You can then clone a new shared |
belaran@999 | 7741 <literal moreinfo="none">myproject-1.0.1</literal> repository as of that |
belaran@999 | 7742 tag.</para> |
belaran@999 | 7743 |
belaran@999 | 7744 <!-- BEGIN branch-repo.clone --> |
belaran@999 | 7745 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 7746 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-1.0.1</userinput> |
belaran@999 | 7747 updating working directory |
belaran@999 | 7748 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 7749 </screen> |
belaran@999 | 7750 <!-- END branch-repo.clone --> |
belaran@999 | 7751 |
belaran@999 | 7752 |
belaran@999 | 7753 <para id="x_38b">Afterwards, if someone needs to work on a bug fix that ought |
belaran@999 | 7754 to go into an upcoming 1.0.1 minor release, they clone the |
belaran@999 | 7755 <literal moreinfo="none">myproject-1.0.1</literal> repository, make their |
belaran@999 | 7756 changes, and push them back.</para> |
belaran@999 | 7757 |
belaran@999 | 7758 <!-- BEGIN branch-repo.bugfix --> |
belaran@999 | 7759 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject-1.0.1 my-1.0.1-bugfix</userinput> |
belaran@999 | 7760 updating working directory |
belaran@999 | 7761 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 7762 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-1.0.1-bugfix</userinput> |
belaran@999 | 7763 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'I fixed a bug using only echo!' >> myfile</userinput> |
belaran@999 | 7764 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Important fix for 1.0.1'</userinput> |
belaran@999 | 7765 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> |
belaran@999 | 7766 pushing to /tmp/branch-repo3rVLLS/myproject-1.0.1 |
belaran@999 | 7767 searching for changes |
belaran@999 | 7768 adding changesets |
belaran@999 | 7769 adding manifests |
belaran@999 | 7770 adding file changes |
belaran@999 | 7771 added 1 changesets with 1 changes to 1 files |
belaran@999 | 7772 </screen> |
belaran@999 | 7773 <!-- END branch-repo.bugfix --> |
belaran@999 | 7774 |
belaran@999 | 7775 |
belaran@999 | 7776 <para id="x_38c">Meanwhile, development for |
belaran@999 | 7777 the next major release can continue, isolated and unabated, in |
belaran@999 | 7778 the <literal moreinfo="none">myproject</literal> repository.</para> |
belaran@999 | 7779 |
belaran@999 | 7780 <!-- BEGIN branch-repo.new --> |
belaran@999 | 7781 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 7782 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject my-feature</userinput> |
belaran@999 | 7783 updating working directory |
belaran@999 | 7784 2 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 7785 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd my-feature</userinput> |
belaran@999 | 7786 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'This sure is an exciting new feature!' > mynewfile</userinput> |
belaran@999 | 7787 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New feature'</userinput> |
belaran@999 | 7788 adding mynewfile |
belaran@999 | 7789 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> |
belaran@999 | 7790 pushing to /tmp/branch-repo3rVLLS/myproject |
belaran@999 | 7791 searching for changes |
belaran@999 | 7792 adding changesets |
belaran@999 | 7793 adding manifests |
belaran@999 | 7794 adding file changes |
belaran@999 | 7795 added 1 changesets with 1 changes to 1 files |
belaran@999 | 7796 </screen> |
belaran@999 | 7797 <!-- END branch-repo.new --> |
belaran@999 | 7798 |
belaran@999 | 7799 </sect1> |
belaran@999 | 7800 |
belaran@999 | 7801 <sect1> |
belaran@999 | 7802 <title>Don't repeat yourself: merging across branches</title> |
belaran@999 | 7803 |
belaran@999 | 7804 <para id="x_38d">In many cases, if you have a bug to fix on a maintenance |
belaran@999 | 7805 branch, the chances are good that the bug exists on your |
belaran@999 | 7806 project's main branch (and possibly other maintenance branches, |
belaran@999 | 7807 too). It's a rare developer who wants to fix the same bug |
belaran@999 | 7808 multiple times, so let's look at a few ways that Mercurial can |
belaran@999 | 7809 help you to manage these bugfixes without duplicating your |
belaran@999 | 7810 work.</para> |
belaran@999 | 7811 |
belaran@999 | 7812 <para id="x_38e">In the simplest instance, all you need to do is pull changes |
belaran@999 | 7813 from your maintenance branch into your local clone of the target |
belaran@999 | 7814 branch.</para> |
belaran@999 | 7815 |
belaran@999 | 7816 <!-- BEGIN branch-repo.pull --> |
belaran@999 | 7817 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 7818 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone myproject myproject-merge</userinput> |
belaran@999 | 7819 updating working directory |
belaran@999 | 7820 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 7821 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myproject-merge</userinput> |
belaran@999 | 7822 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../myproject-1.0.1</userinput> |
belaran@999 | 7823 pulling from ../myproject-1.0.1 |
belaran@999 | 7824 searching for changes |
belaran@999 | 7825 adding changesets |
belaran@999 | 7826 adding manifests |
belaran@999 | 7827 adding file changes |
belaran@999 | 7828 added 1 changesets with 1 changes to 1 files (+1 heads) |
belaran@999 | 7829 (run 'hg heads' to see heads, 'hg merge' to merge) |
belaran@999 | 7830 </screen> |
belaran@999 | 7831 <!-- END branch-repo.pull --> |
belaran@999 | 7832 |
belaran@999 | 7833 |
belaran@999 | 7834 <para id="x_38f">You'll then need to merge the heads of the two branches, and |
belaran@999 | 7835 push back to the main branch.</para> |
belaran@999 | 7836 |
belaran@999 | 7837 <!-- BEGIN branch-repo.merge --> |
belaran@999 | 7838 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 7839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 7840 (branch merge, don't forget to commit) |
belaran@999 | 7841 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge bugfix from 1.0.1 branch'</userinput> |
belaran@999 | 7842 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg push</userinput> |
belaran@999 | 7843 pushing to /tmp/branch-repo3rVLLS/myproject |
belaran@999 | 7844 searching for changes |
belaran@999 | 7845 adding changesets |
belaran@999 | 7846 adding manifests |
belaran@999 | 7847 adding file changes |
belaran@999 | 7848 added 2 changesets with 1 changes to 1 files |
belaran@999 | 7849 </screen> |
belaran@999 | 7850 <!-- END branch-repo.merge --> |
belaran@999 | 7851 |
belaran@999 | 7852 </sect1> |
belaran@999 | 7853 |
belaran@999 | 7854 <sect1> |
belaran@999 | 7855 <title>Naming branches within one repository</title> |
belaran@999 | 7856 |
belaran@999 | 7857 <para id="x_390">In most instances, isolating branches in repositories is the |
belaran@999 | 7858 right approach. Its simplicity makes it easy to understand; and |
belaran@999 | 7859 so it's hard to make mistakes. There's a one-to-one |
belaran@999 | 7860 relationship between branches you're working in and directories |
belaran@999 | 7861 on your system. This lets you use normal (non-Mercurial-aware) |
belaran@999 | 7862 tools to work on files within a branch/repository.</para> |
belaran@999 | 7863 |
belaran@999 | 7864 <para id="x_391">If you're more in the <quote>power user</quote> category |
belaran@999 | 7865 (<emphasis>and</emphasis> your collaborators are too), there is |
belaran@999 | 7866 an alternative way of handling branches that you can consider. |
belaran@999 | 7867 I've already mentioned the human-level distinction between |
belaran@999 | 7868 <quote>small picture</quote> and <quote>big picture</quote> |
belaran@999 | 7869 branches. While Mercurial works with multiple <quote>small |
belaran@999 | 7870 picture</quote> branches in a repository all the time (for |
belaran@999 | 7871 example after you pull changes in, but before you merge them), |
belaran@999 | 7872 it can <emphasis>also</emphasis> work with multiple <quote>big |
belaran@999 | 7873 picture</quote> branches.</para> |
belaran@999 | 7874 |
belaran@999 | 7875 <para id="x_392">The key to working this way is that Mercurial lets you |
belaran@999 | 7876 assign a persistent <emphasis>name</emphasis> to a branch. |
belaran@999 | 7877 There always exists a branch named <literal moreinfo="none">default</literal>. |
belaran@999 | 7878 Even before you start naming branches yourself, you can find |
belaran@999 | 7879 traces of the <literal moreinfo="none">default</literal> branch if you look for |
belaran@999 | 7880 them.</para> |
belaran@999 | 7881 |
belaran@999 | 7882 <para id="x_393">As an example, when you run the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7883 commit</command> command, and it pops up your editor so that |
belaran@999 | 7884 you can enter a commit message, look for a line that contains |
belaran@999 | 7885 the text <quote><literal moreinfo="none">HG: branch default</literal></quote> at |
belaran@999 | 7886 the bottom. This is telling you that your commit will occur on |
belaran@999 | 7887 the branch named <literal moreinfo="none">default</literal>.</para> |
belaran@999 | 7888 |
belaran@999 | 7889 <para id="x_394">To start working with named branches, use the <command role="hg-cmd" moreinfo="none">hg branches</command> command. This command |
belaran@999 | 7890 lists the named branches already present in your repository, |
belaran@999 | 7891 telling you which changeset is the tip of each.</para> |
belaran@999 | 7892 |
belaran@999 | 7893 <!-- BEGIN branch-named.branches --> |
belaran@999 | 7894 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 7895 changeset: 0:90897f9e54e3 |
belaran@999 | 7896 tag: tip |
belaran@999 | 7897 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7898 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 7899 summary: Initial commit |
belaran@999 | 7900 |
belaran@999 | 7901 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput> |
belaran@999 | 7902 default 0:90897f9e54e3 |
belaran@999 | 7903 </screen> |
belaran@999 | 7904 <!-- END branch-named.branches --> |
belaran@999 | 7905 |
belaran@999 | 7906 |
belaran@999 | 7907 <para id="x_395">Since you haven't created any named branches yet, the only |
belaran@999 | 7908 one that exists is <literal moreinfo="none">default</literal>.</para> |
belaran@999 | 7909 |
belaran@999 | 7910 <para id="x_396">To find out what the <quote>current</quote> branch is, run |
belaran@999 | 7911 the <command role="hg-cmd" moreinfo="none">hg branch</command> command, giving |
belaran@999 | 7912 it no arguments. This tells you what branch the parent of the |
belaran@999 | 7913 current changeset is on.</para> |
belaran@999 | 7914 |
belaran@999 | 7915 <!-- BEGIN branch-named.branch --> |
belaran@999 | 7916 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> |
belaran@999 | 7917 default |
belaran@999 | 7918 </screen> |
belaran@999 | 7919 <!-- END branch-named.branch --> |
belaran@999 | 7920 |
belaran@999 | 7921 |
belaran@999 | 7922 <para id="x_397">To create a new branch, run the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7923 branch</command> command again. This time, give it one |
belaran@999 | 7924 argument: the name of the branch you want to create.</para> |
belaran@999 | 7925 |
belaran@999 | 7926 <!-- BEGIN branch-named.create --> |
belaran@999 | 7927 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch foo</userinput> |
belaran@999 | 7928 marked working directory as branch foo |
belaran@999 | 7929 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> |
belaran@999 | 7930 foo |
belaran@999 | 7931 </screen> |
belaran@999 | 7932 <!-- END branch-named.create --> |
belaran@999 | 7933 |
belaran@999 | 7934 |
belaran@999 | 7935 <para id="x_398">After you've created a branch, you might wonder what effect |
belaran@999 | 7936 the <command role="hg-cmd" moreinfo="none">hg branch</command> command has had. |
belaran@999 | 7937 What do the <command role="hg-cmd" moreinfo="none">hg status</command> and |
belaran@999 | 7938 <command role="hg-cmd" moreinfo="none">hg tip</command> commands report?</para> |
belaran@999 | 7939 |
belaran@999 | 7940 <!-- BEGIN branch-named.status --> |
belaran@999 | 7941 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 7942 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 7943 changeset: 0:90897f9e54e3 |
belaran@999 | 7944 tag: tip |
belaran@999 | 7945 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7946 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 7947 summary: Initial commit |
belaran@999 | 7948 |
belaran@999 | 7949 </screen> |
belaran@999 | 7950 <!-- END branch-named.status --> |
belaran@999 | 7951 |
belaran@999 | 7952 |
belaran@999 | 7953 <para id="x_399">Nothing has changed in the |
belaran@999 | 7954 working directory, and there's been no new history created. As |
belaran@999 | 7955 this suggests, running the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7956 branch</command> command has no permanent effect; it only |
belaran@999 | 7957 tells Mercurial what branch name to use the |
belaran@999 | 7958 <emphasis>next</emphasis> time you commit a changeset.</para> |
belaran@999 | 7959 |
belaran@999 | 7960 <para id="x_39a">When you commit a change, Mercurial records the name of the |
belaran@999 | 7961 branch on which you committed. Once you've switched from the |
belaran@999 | 7962 <literal moreinfo="none">default</literal> branch to another and committed, |
belaran@999 | 7963 you'll see the name of the new branch show up in the output of |
belaran@999 | 7964 <command role="hg-cmd" moreinfo="none">hg log</command>, <command role="hg-cmd" moreinfo="none">hg tip</command>, and other commands that |
belaran@999 | 7965 display the same kind of output.</para> |
belaran@999 | 7966 |
belaran@999 | 7967 <!-- BEGIN branch-named.commit --> |
belaran@999 | 7968 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'hello again' >> myfile</userinput> |
belaran@999 | 7969 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Second commit'</userinput> |
belaran@999 | 7970 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 7971 changeset: 1:5656f8ffdd49 |
belaran@999 | 7972 branch: foo |
belaran@999 | 7973 tag: tip |
belaran@999 | 7974 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 7975 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 7976 summary: Second commit |
belaran@999 | 7977 |
belaran@999 | 7978 </screen> |
belaran@999 | 7979 <!-- END branch-named.commit --> |
belaran@999 | 7980 |
belaran@999 | 7981 |
belaran@999 | 7982 <para id="x_39b">The <command role="hg-cmd" moreinfo="none">hg log</command>-like commands |
belaran@999 | 7983 will print the branch name of every changeset that's not on the |
belaran@999 | 7984 <literal moreinfo="none">default</literal> branch. As a result, if you never |
belaran@999 | 7985 use named branches, you'll never see this information.</para> |
belaran@999 | 7986 |
belaran@999 | 7987 <para id="x_39c">Once you've named a branch and committed a change with that |
belaran@999 | 7988 name, every subsequent commit that descends from that change |
belaran@999 | 7989 will inherit the same branch name. You can change the name of a |
belaran@999 | 7990 branch at any time, using the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 7991 branch</command> command.</para> |
belaran@999 | 7992 |
belaran@999 | 7993 <!-- BEGIN branch-named.rebranch --> |
belaran@999 | 7994 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> |
belaran@999 | 7995 foo |
belaran@999 | 7996 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch bar</userinput> |
belaran@999 | 7997 marked working directory as branch bar |
belaran@999 | 7998 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo new file > newfile</userinput> |
belaran@999 | 7999 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'Third commit'</userinput> |
belaran@999 | 8000 adding newfile |
belaran@999 | 8001 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 8002 changeset: 2:c59d680fc2ec |
belaran@999 | 8003 branch: bar |
belaran@999 | 8004 tag: tip |
belaran@999 | 8005 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8006 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 8007 summary: Third commit |
belaran@999 | 8008 |
belaran@999 | 8009 </screen> |
belaran@999 | 8010 <!-- END branch-named.rebranch --> |
belaran@999 | 8011 |
belaran@999 | 8012 |
belaran@999 | 8013 <para id="x_39d">In practice, this is something you won't do very often, as |
belaran@999 | 8014 branch names tend to have fairly long lifetimes. (This isn't a |
belaran@999 | 8015 rule, just an observation.)</para> |
belaran@999 | 8016 </sect1> |
belaran@999 | 8017 |
belaran@999 | 8018 <sect1> |
belaran@999 | 8019 <title>Dealing with multiple named branches in a |
belaran@999 | 8020 repository</title> |
belaran@999 | 8021 |
belaran@999 | 8022 <para id="x_39e">If you have more than one named branch in a repository, |
belaran@999 | 8023 Mercurial will remember the branch that your working directory |
belaran@999 | 8024 is on when you start a command like <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8025 update</command> or <command role="hg-cmd" moreinfo="none">hg pull |
belaran@999 | 8026 -u</command>. It will update the working directory to the tip |
belaran@999 | 8027 of this branch, no matter what the <quote>repo-wide</quote> tip |
belaran@999 | 8028 is. To update to a revision that's on a different named branch, |
belaran@999 | 8029 you may need to use the <option role="hg-opt-update">-C</option> |
belaran@999 | 8030 option to <command role="hg-cmd" moreinfo="none">hg update</command>.</para> |
belaran@999 | 8031 |
belaran@999 | 8032 <para id="x_39f">This behavior is a little subtle, so let's see it in |
belaran@999 | 8033 action. First, let's remind ourselves what branch we're |
belaran@999 | 8034 currently on, and what branches are in our repository.</para> |
belaran@999 | 8035 |
belaran@999 | 8036 <!-- BEGIN branch-named.parents --> |
belaran@999 | 8037 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 8038 changeset: 2:c59d680fc2ec |
belaran@999 | 8039 branch: bar |
belaran@999 | 8040 tag: tip |
belaran@999 | 8041 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8042 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 8043 summary: Third commit |
belaran@999 | 8044 |
belaran@999 | 8045 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branches</userinput> |
belaran@999 | 8046 bar 2:c59d680fc2ec |
belaran@999 | 8047 foo 1:5656f8ffdd49 (inactive) |
belaran@999 | 8048 default 0:90897f9e54e3 (inactive) |
belaran@999 | 8049 </screen> |
belaran@999 | 8050 <!-- END branch-named.parents --> |
belaran@999 | 8051 |
belaran@999 | 8052 |
belaran@999 | 8053 <para id="x_3a0">We're on the <literal moreinfo="none">bar</literal> branch, but there also |
belaran@999 | 8054 exists an older <command role="hg-cmd" moreinfo="none">hg foo</command> |
belaran@999 | 8055 branch.</para> |
belaran@999 | 8056 |
belaran@999 | 8057 <para id="x_3a1">We can <command role="hg-cmd" moreinfo="none">hg update</command> back and |
belaran@999 | 8058 forth between the tips of the <literal moreinfo="none">foo</literal> and |
belaran@999 | 8059 <literal moreinfo="none">bar</literal> branches without needing to use the |
belaran@999 | 8060 <option role="hg-opt-update">-C</option> option, because this |
belaran@999 | 8061 only involves going backwards and forwards linearly through our |
belaran@999 | 8062 change history.</para> |
belaran@999 | 8063 |
belaran@999 | 8064 <!-- BEGIN branch-named.update-switchy --> |
belaran@999 | 8065 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput> |
belaran@999 | 8066 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
belaran@999 | 8067 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 8068 changeset: 1:5656f8ffdd49 |
belaran@999 | 8069 branch: foo |
belaran@999 | 8070 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8071 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 8072 summary: Second commit |
belaran@999 | 8073 |
belaran@999 | 8074 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update bar</userinput> |
belaran@999 | 8075 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 8076 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 8077 changeset: 2:c59d680fc2ec |
belaran@999 | 8078 branch: bar |
belaran@999 | 8079 tag: tip |
belaran@999 | 8080 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8081 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 8082 summary: Third commit |
belaran@999 | 8083 |
belaran@999 | 8084 </screen> |
belaran@999 | 8085 <!-- END branch-named.update-switchy --> |
belaran@999 | 8086 |
belaran@999 | 8087 |
belaran@999 | 8088 <para id="x_3a2">If we go back to the <literal moreinfo="none">foo</literal> branch and then |
belaran@999 | 8089 run <command role="hg-cmd" moreinfo="none">hg update</command>, it will keep us |
belaran@999 | 8090 on <literal moreinfo="none">foo</literal>, not move us to the tip of |
belaran@999 | 8091 <literal moreinfo="none">bar</literal>.</para> |
belaran@999 | 8092 |
belaran@999 | 8093 <!-- BEGIN branch-named.update-nothing --> |
belaran@999 | 8094 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update foo</userinput> |
belaran@999 | 8095 0 files updated, 0 files merged, 1 files removed, 0 files unresolved |
belaran@999 | 8096 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg update</userinput> |
belaran@999 | 8097 0 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 8098 </screen> |
belaran@999 | 8099 <!-- END branch-named.update-nothing --> |
belaran@999 | 8100 |
belaran@999 | 8101 |
belaran@999 | 8102 <para id="x_3a3">Committing a new change on the <literal moreinfo="none">foo</literal> branch |
belaran@999 | 8103 introduces a new head.</para> |
belaran@999 | 8104 |
belaran@999 | 8105 <!-- BEGIN branch-named.foo-commit --> |
belaran@999 | 8106 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo something > somefile</userinput> |
belaran@999 | 8107 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'New file'</userinput> |
belaran@999 | 8108 adding somefile |
belaran@999 | 8109 created new head |
belaran@999 | 8110 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> |
belaran@999 | 8111 changeset: 3:4dd2f7a37288 |
belaran@999 | 8112 branch: foo |
belaran@999 | 8113 tag: tip |
belaran@999 | 8114 parent: 1:5656f8ffdd49 |
belaran@999 | 8115 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8116 date: Sun Aug 16 14:04:43 2009 +0000 |
belaran@999 | 8117 summary: New file |
belaran@999 | 8118 |
belaran@999 | 8119 changeset: 2:c59d680fc2ec |
belaran@999 | 8120 branch: bar |
belaran@999 | 8121 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8122 date: Sun Aug 16 14:04:42 2009 +0000 |
belaran@999 | 8123 summary: Third commit |
belaran@999 | 8124 |
belaran@999 | 8125 </screen> |
belaran@999 | 8126 <!-- END branch-named.foo-commit --> |
belaran@999 | 8127 |
belaran@999 | 8128 </sect1> |
belaran@999 | 8129 |
belaran@999 | 8130 <sect1> |
belaran@999 | 8131 <title>Branch names and merging</title> |
belaran@999 | 8132 |
belaran@999 | 8133 <para id="x_3a4">As you've probably noticed, merges in Mercurial are not |
belaran@999 | 8134 symmetrical. Let's say our repository has two heads, 17 and 23. |
belaran@999 | 8135 If I <command role="hg-cmd" moreinfo="none">hg update</command> to 17 and then |
belaran@999 | 8136 <command role="hg-cmd" moreinfo="none">hg merge</command> with 23, Mercurial |
belaran@999 | 8137 records 17 as the first parent of the merge, and 23 as the |
belaran@999 | 8138 second. Whereas if I <command role="hg-cmd" moreinfo="none">hg update</command> |
belaran@999 | 8139 to 23 and then <command role="hg-cmd" moreinfo="none">hg merge</command> with |
belaran@999 | 8140 17, it records 23 as the first parent, and 17 as the |
belaran@999 | 8141 second.</para> |
belaran@999 | 8142 |
belaran@999 | 8143 <para id="x_3a5">This affects Mercurial's choice of branch name when you |
belaran@999 | 8144 merge. After a merge, Mercurial will retain the branch name of |
belaran@999 | 8145 the first parent when you commit the result of the merge. If |
belaran@999 | 8146 your first parent's branch name is <literal moreinfo="none">foo</literal>, and |
belaran@999 | 8147 you merge with <literal moreinfo="none">bar</literal>, the branch name will |
belaran@999 | 8148 still be <literal moreinfo="none">foo</literal> after you merge.</para> |
belaran@999 | 8149 |
belaran@999 | 8150 <para id="x_3a6">It's not unusual for a repository to contain multiple heads, |
belaran@999 | 8151 each with the same branch name. Let's say I'm working on the |
belaran@999 | 8152 <literal moreinfo="none">foo</literal> branch, and so are you. We commit |
belaran@999 | 8153 different changes; I pull your changes; I now have two heads, |
belaran@999 | 8154 each claiming to be on the <literal moreinfo="none">foo</literal> branch. The |
belaran@999 | 8155 result of a merge will be a single head on the |
belaran@999 | 8156 <literal moreinfo="none">foo</literal> branch, as you might hope.</para> |
belaran@999 | 8157 |
belaran@999 | 8158 <para id="x_3a7">But if I'm working on the <literal moreinfo="none">bar</literal> branch, and |
belaran@999 | 8159 I merge work from the <literal moreinfo="none">foo</literal> branch, the result |
belaran@999 | 8160 will remain on the <literal moreinfo="none">bar</literal> branch.</para> |
belaran@999 | 8161 |
belaran@999 | 8162 <!-- BEGIN branch-named.merge --> |
belaran@999 | 8163 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg branch</userinput> |
belaran@999 | 8164 bar |
belaran@999 | 8165 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge foo</userinput> |
belaran@999 | 8166 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 8167 (branch merge, don't forget to commit) |
belaran@999 | 8168 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Merge'</userinput> |
belaran@999 | 8169 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 8170 changeset: 4:9f05d4ef3efe |
belaran@999 | 8171 branch: bar |
belaran@999 | 8172 tag: tip |
belaran@999 | 8173 parent: 2:c59d680fc2ec |
belaran@999 | 8174 parent: 3:4dd2f7a37288 |
belaran@999 | 8175 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8176 date: Sun Aug 16 14:04:44 2009 +0000 |
belaran@999 | 8177 summary: Merge |
belaran@999 | 8178 |
belaran@999 | 8179 </screen> |
belaran@999 | 8180 <!-- END branch-named.merge --> |
belaran@999 | 8181 |
belaran@999 | 8182 |
belaran@999 | 8183 <para id="x_3a8">To give a more concrete example, if I'm working on the |
belaran@999 | 8184 <literal moreinfo="none">bleeding-edge</literal> branch, and I want to bring in |
belaran@999 | 8185 the latest fixes from the <literal moreinfo="none">stable</literal> branch, |
belaran@999 | 8186 Mercurial will choose the <quote>right</quote> |
belaran@999 | 8187 (<literal moreinfo="none">bleeding-edge</literal>) branch name when I pull and |
belaran@999 | 8188 merge from <literal moreinfo="none">stable</literal>.</para> |
belaran@999 | 8189 </sect1> |
belaran@999 | 8190 |
belaran@999 | 8191 <sect1> |
belaran@999 | 8192 <title>Branch naming is generally useful</title> |
belaran@999 | 8193 |
belaran@999 | 8194 <para id="x_3a9">You shouldn't think of named branches as applicable only to |
belaran@999 | 8195 situations where you have multiple long-lived branches |
belaran@999 | 8196 cohabiting in a single repository. They're very useful even in |
belaran@999 | 8197 the one-branch-per-repository case.</para> |
belaran@999 | 8198 |
belaran@999 | 8199 <para id="x_3aa">In the simplest case, giving a name to each branch gives you |
belaran@999 | 8200 a permanent record of which branch a changeset originated on. |
belaran@999 | 8201 This gives you more context when you're trying to follow the |
belaran@999 | 8202 history of a long-lived branchy project.</para> |
belaran@999 | 8203 |
belaran@999 | 8204 <para id="x_3ab">If you're working with shared repositories, you can set up a |
belaran@999 | 8205 <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook on each |
belaran@999 | 8206 that will block incoming changes that have the |
belaran@999 | 8207 <quote>wrong</quote> branch name. This provides a simple, but |
belaran@999 | 8208 effective, defence against people accidentally pushing changes |
belaran@999 | 8209 from a <quote>bleeding edge</quote> branch to a |
belaran@999 | 8210 <quote>stable</quote> branch. Such a hook might look like this |
belaran@999 | 8211 inside the shared repo's <filename role="special" moreinfo="none"> |
belaran@999 | 8212 /.hgrc</filename>.</para> |
belaran@999 | 8213 <programlisting format="linespecific">[hooks] |
belaran@999 | 8214 pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch</programlisting> |
belaran@999 | 8215 </sect1> |
belaran@999 | 8216 </chapter> |
belaran@999 | 8217 |
belaran@999 | 8218 <!-- |
belaran@999 | 8219 local variables: |
belaran@999 | 8220 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 8221 end: |
belaran@999 | 8222 --> |
belaran@999 | 8223 |
belaran@999 | 8224 <!-- BEGIN ch09 --> |
belaran@999 | 8225 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 8226 |
belaran@999 | 8227 <chapter id="chap:undo"> |
belaran@999 | 8228 <?dbhtml filename="finding-and-fixing-mistakes.html"?> |
belaran@999 | 8229 <title>Finding and fixing mistakes</title> |
belaran@999 | 8230 |
belaran@999 | 8231 <para id="x_d2">To err might be human, but to really handle the consequences |
belaran@999 | 8232 well takes a top-notch revision control system. In this chapter, |
belaran@999 | 8233 we'll discuss some of the techniques you can use when you find |
belaran@999 | 8234 that a problem has crept into your project. Mercurial has some |
belaran@999 | 8235 highly capable features that will help you to isolate the sources |
belaran@999 | 8236 of problems, and to handle them appropriately.</para> |
belaran@999 | 8237 |
belaran@999 | 8238 <sect1> |
belaran@999 | 8239 <title>Erasing local history</title> |
belaran@999 | 8240 |
belaran@999 | 8241 <sect2> |
belaran@999 | 8242 <title>The accidental commit</title> |
belaran@999 | 8243 |
belaran@999 | 8244 <para id="x_d3">I have the occasional but persistent problem of typing |
belaran@999 | 8245 rather more quickly than I can think, which sometimes results |
belaran@999 | 8246 in me committing a changeset that is either incomplete or |
belaran@999 | 8247 plain wrong. In my case, the usual kind of incomplete |
belaran@999 | 8248 changeset is one in which I've created a new source file, but |
belaran@999 | 8249 forgotten to <command role="hg-cmd" moreinfo="none">hg add</command> it. A |
belaran@999 | 8250 <quote>plain wrong</quote> changeset is not as common, but no |
belaran@999 | 8251 less annoying.</para> |
belaran@999 | 8252 |
belaran@999 | 8253 </sect2> |
belaran@999 | 8254 <sect2 id="sec:undo:rollback"> |
belaran@999 | 8255 <title>Rolling back a transaction</title> |
belaran@999 | 8256 |
belaran@999 | 8257 <para id="x_d4">In <xref linkend="sec:concepts:txn"/>, I |
belaran@999 | 8258 mentioned that Mercurial treats each modification of a |
belaran@999 | 8259 repository as a <emphasis>transaction</emphasis>. Every time |
belaran@999 | 8260 you commit a changeset or pull changes from another |
belaran@999 | 8261 repository, Mercurial remembers what you did. You can undo, |
belaran@999 | 8262 or <emphasis>roll back</emphasis>, exactly one of these |
belaran@999 | 8263 actions using the <command role="hg-cmd" moreinfo="none">hg rollback</command> |
belaran@999 | 8264 command. (See <xref linkend="sec:undo:rollback-after-push"/> |
belaran@999 | 8265 for an important caveat about the use of this command.)</para> |
belaran@999 | 8266 |
belaran@999 | 8267 <para id="x_d5">Here's a mistake that I often find myself making: |
belaran@999 | 8268 committing a change in which I've created a new file, but |
belaran@999 | 8269 forgotten to <command role="hg-cmd" moreinfo="none">hg add</command> |
belaran@999 | 8270 it.</para> |
belaran@999 | 8271 |
belaran@999 | 8272 <!-- BEGIN rollback.commit --> |
belaran@999 | 8273 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8274 M a |
belaran@999 | 8275 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo b > b</userinput> |
belaran@999 | 8276 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b'</userinput> |
belaran@999 | 8277 </screen> |
belaran@999 | 8278 <!-- END rollback.commit --> |
belaran@999 | 8279 |
belaran@999 | 8280 |
belaran@999 | 8281 <para id="x_d6">Looking at the output of <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8282 status</command> after the commit immediately confirms the |
belaran@999 | 8283 error.</para> |
belaran@999 | 8284 |
belaran@999 | 8285 <!-- BEGIN rollback.status --> |
belaran@999 | 8286 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8287 ? b |
belaran@999 | 8288 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 8289 changeset: 1:246e2aada1c5 |
belaran@999 | 8290 tag: tip |
belaran@999 | 8291 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8292 date: Sun Aug 16 14:05:14 2009 +0000 |
belaran@999 | 8293 summary: Add file b |
belaran@999 | 8294 |
belaran@999 | 8295 </screen> |
belaran@999 | 8296 <!-- END rollback.status --> |
belaran@999 | 8297 |
belaran@999 | 8298 |
belaran@999 | 8299 <para id="x_d7">The commit captured the changes to the file |
belaran@999 | 8300 <filename moreinfo="none">a</filename>, but not the new file |
belaran@999 | 8301 <filename moreinfo="none">b</filename>. If I were to push this changeset to a |
belaran@999 | 8302 repository that I shared with a colleague, the chances are |
belaran@999 | 8303 high that something in <filename moreinfo="none">a</filename> would refer to |
belaran@999 | 8304 <filename moreinfo="none">b</filename>, which would not be present in their |
belaran@999 | 8305 repository when they pulled my changes. I would thus become |
belaran@999 | 8306 the object of some indignation.</para> |
belaran@999 | 8307 |
belaran@999 | 8308 <para id="x_d8">However, luck is with me—I've caught my error |
belaran@999 | 8309 before I pushed the changeset. I use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, and Mercurial |
belaran@999 | 8310 makes that last changeset vanish.</para> |
belaran@999 | 8311 |
belaran@999 | 8312 <!-- BEGIN rollback.rollback --> |
belaran@999 | 8313 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput> |
belaran@999 | 8314 rolling back last transaction |
belaran@999 | 8315 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 8316 changeset: 0:c37ce4157509 |
belaran@999 | 8317 tag: tip |
belaran@999 | 8318 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8319 date: Sun Aug 16 14:05:14 2009 +0000 |
belaran@999 | 8320 summary: First commit |
belaran@999 | 8321 |
belaran@999 | 8322 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8323 M a |
belaran@999 | 8324 ? b |
belaran@999 | 8325 </screen> |
belaran@999 | 8326 <!-- END rollback.rollback --> |
belaran@999 | 8327 |
belaran@999 | 8328 |
belaran@999 | 8329 <para id="x_d9">Notice that the changeset is no longer present in the |
belaran@999 | 8330 repository's history, and the working directory once again |
belaran@999 | 8331 thinks that the file <filename moreinfo="none">a</filename> is modified. The |
belaran@999 | 8332 commit and rollback have left the working directory exactly as |
belaran@999 | 8333 it was prior to the commit; the changeset has been completely |
belaran@999 | 8334 erased. I can now safely <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8335 add</command> the file <filename moreinfo="none">b</filename>, and rerun my |
belaran@999 | 8336 commit.</para> |
belaran@999 | 8337 |
belaran@999 | 8338 <!-- BEGIN rollback.add --> |
belaran@999 | 8339 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add b</userinput> |
belaran@999 | 8340 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'Add file b, this time for real'</userinput> |
belaran@999 | 8341 </screen> |
belaran@999 | 8342 <!-- END rollback.add --> |
belaran@999 | 8343 |
belaran@999 | 8344 |
belaran@999 | 8345 </sect2> |
belaran@999 | 8346 <sect2> |
belaran@999 | 8347 <title>The erroneous pull</title> |
belaran@999 | 8348 |
belaran@999 | 8349 <para id="x_da">It's common practice with Mercurial to maintain separate |
belaran@999 | 8350 development branches of a project in different repositories. |
belaran@999 | 8351 Your development team might have one shared repository for |
belaran@999 | 8352 your project's <quote>0.9</quote> release, and another, |
belaran@999 | 8353 containing different changes, for the <quote>1.0</quote> |
belaran@999 | 8354 release.</para> |
belaran@999 | 8355 |
belaran@999 | 8356 <para id="x_db">Given this, you can imagine that the consequences could be |
belaran@999 | 8357 messy if you had a local <quote>0.9</quote> repository, and |
belaran@999 | 8358 accidentally pulled changes from the shared <quote>1.0</quote> |
belaran@999 | 8359 repository into it. At worst, you could be paying |
belaran@999 | 8360 insufficient attention, and push those changes into the shared |
belaran@999 | 8361 <quote>0.9</quote> tree, confusing your entire team (but don't |
belaran@999 | 8362 worry, we'll return to this horror scenario later). However, |
belaran@999 | 8363 it's more likely that you'll notice immediately, because |
belaran@999 | 8364 Mercurial will display the URL it's pulling from, or you will |
belaran@999 | 8365 see it pull a suspiciously large number of changes into the |
belaran@999 | 8366 repository.</para> |
belaran@999 | 8367 |
belaran@999 | 8368 <para id="x_dc">The <command role="hg-cmd" moreinfo="none">hg rollback</command> command |
belaran@999 | 8369 will work nicely to expunge all of the changesets that you |
belaran@999 | 8370 just pulled. Mercurial groups all changes from one <command role="hg-cmd" moreinfo="none">hg pull</command> into a single transaction, |
belaran@999 | 8371 so one <command role="hg-cmd" moreinfo="none">hg rollback</command> is all you |
belaran@999 | 8372 need to undo this mistake.</para> |
belaran@999 | 8373 |
belaran@999 | 8374 </sect2> |
belaran@999 | 8375 <sect2 id="sec:undo:rollback-after-push"> |
belaran@999 | 8376 <title>Rolling back is useless once you've pushed</title> |
belaran@999 | 8377 |
belaran@999 | 8378 <para id="x_dd">The value of the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8379 rollback</command> command drops to zero once you've pushed |
belaran@999 | 8380 your changes to another repository. Rolling back a change |
belaran@999 | 8381 makes it disappear entirely, but <emphasis>only</emphasis> in |
belaran@999 | 8382 the repository in which you perform the <command role="hg-cmd" moreinfo="none">hg rollback</command>. Because a rollback |
belaran@999 | 8383 eliminates history, there's no way for the disappearance of a |
belaran@999 | 8384 change to propagate between repositories.</para> |
belaran@999 | 8385 |
belaran@999 | 8386 <para id="x_de">If you've pushed a change to another |
belaran@999 | 8387 repository—particularly if it's a shared |
belaran@999 | 8388 repository—it has essentially <quote>escaped into the |
belaran@999 | 8389 wild,</quote> and you'll have to recover from your mistake |
belaran@999 | 8390 in a different way. If you push a changeset somewhere, then |
belaran@999 | 8391 roll it back, then pull from the repository you pushed to, the |
belaran@999 | 8392 changeset you thought you'd gotten rid of will simply reappear |
belaran@999 | 8393 in your repository.</para> |
belaran@999 | 8394 |
belaran@999 | 8395 <para id="x_df">(If you absolutely know for sure that the change |
belaran@999 | 8396 you want to roll back is the most recent change in the |
belaran@999 | 8397 repository that you pushed to, <emphasis>and</emphasis> you |
belaran@999 | 8398 know that nobody else could have pulled it from that |
belaran@999 | 8399 repository, you can roll back the changeset there, too, but |
belaran@999 | 8400 you really should not expect this to work reliably. Sooner or |
belaran@999 | 8401 later a change really will make it into a repository that you |
belaran@999 | 8402 don't directly control (or have forgotten about), and come |
belaran@999 | 8403 back to bite you.)</para> |
belaran@999 | 8404 |
belaran@999 | 8405 </sect2> |
belaran@999 | 8406 <sect2> |
belaran@999 | 8407 <title>You can only roll back once</title> |
belaran@999 | 8408 |
belaran@999 | 8409 <para id="x_e0">Mercurial stores exactly one transaction in its |
belaran@999 | 8410 transaction log; that transaction is the most recent one that |
belaran@999 | 8411 occurred in the repository. This means that you can only roll |
belaran@999 | 8412 back one transaction. If you expect to be able to roll back |
belaran@999 | 8413 one transaction, then its predecessor, this is not the |
belaran@999 | 8414 behavior you will get.</para> |
belaran@999 | 8415 |
belaran@999 | 8416 <!-- BEGIN rollback.twice --> |
belaran@999 | 8417 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput> |
belaran@999 | 8418 rolling back last transaction |
belaran@999 | 8419 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg rollback</userinput> |
belaran@999 | 8420 no rollback information available |
belaran@999 | 8421 </screen> |
belaran@999 | 8422 <!-- END rollback.twice --> |
belaran@999 | 8423 |
belaran@999 | 8424 |
belaran@999 | 8425 <para id="x_e1">Once you've rolled back one transaction in a repository, |
belaran@999 | 8426 you can't roll back again in that repository until you perform |
belaran@999 | 8427 another commit or pull.</para> |
belaran@999 | 8428 |
belaran@999 | 8429 </sect2> |
belaran@999 | 8430 </sect1> |
belaran@999 | 8431 <sect1> |
belaran@999 | 8432 <title>Reverting the mistaken change</title> |
belaran@999 | 8433 |
belaran@999 | 8434 <para id="x_e2">If you make a modification to a file, and decide that you |
belaran@999 | 8435 really didn't want to change the file at all, and you haven't |
belaran@999 | 8436 yet committed your changes, the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8437 revert</command> command is the one you'll need. It looks at |
belaran@999 | 8438 the changeset that's the parent of the working directory, and |
belaran@999 | 8439 restores the contents of the file to their state as of that |
belaran@999 | 8440 changeset. (That's a long-winded way of saying that, in the |
belaran@999 | 8441 normal case, it undoes your modifications.)</para> |
belaran@999 | 8442 |
belaran@999 | 8443 <para id="x_e3">Let's illustrate how the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8444 revert</command> command works with yet another small example. |
belaran@999 | 8445 We'll begin by modifying a file that Mercurial is already |
belaran@999 | 8446 tracking.</para> |
belaran@999 | 8447 |
belaran@999 | 8448 <!-- BEGIN daily.revert.modify --> |
belaran@999 | 8449 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput> |
belaran@999 | 8450 original content |
belaran@999 | 8451 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo unwanted change >> file</userinput> |
belaran@999 | 8452 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff file</userinput> |
belaran@999 | 8453 diff -r 2eacf948d309 file |
belaran@999 | 8454 --- a/file Sun Aug 16 14:05:00 2009 +0000 |
belaran@999 | 8455 +++ b/file Sun Aug 16 14:05:00 2009 +0000 |
belaran@999 | 8456 @@ -1,1 +1,2 @@ |
belaran@999 | 8457 original content |
belaran@999 | 8458 +unwanted change |
belaran@999 | 8459 </screen> |
belaran@999 | 8460 <!-- END daily.revert.modify --> |
belaran@999 | 8461 |
belaran@999 | 8462 |
belaran@999 | 8463 <para id="x_e4">If we don't |
belaran@999 | 8464 want that change, we can simply <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8465 revert</command> the file.</para> |
belaran@999 | 8466 |
belaran@999 | 8467 <!-- BEGIN daily.revert.unmodify --> |
belaran@999 | 8468 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8469 M file |
belaran@999 | 8470 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput> |
belaran@999 | 8471 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file</userinput> |
belaran@999 | 8472 original content |
belaran@999 | 8473 </screen> |
belaran@999 | 8474 <!-- END daily.revert.unmodify --> |
belaran@999 | 8475 |
belaran@999 | 8476 |
belaran@999 | 8477 <para id="x_e5">The <command role="hg-cmd" moreinfo="none">hg revert</command> command |
belaran@999 | 8478 provides us with an extra degree of safety by saving our |
belaran@999 | 8479 modified file with a <filename moreinfo="none">.orig</filename> |
belaran@999 | 8480 extension.</para> |
belaran@999 | 8481 |
belaran@999 | 8482 <!-- BEGIN daily.revert.status --> |
belaran@999 | 8483 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8484 ? file.orig |
belaran@999 | 8485 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file.orig</userinput> |
belaran@999 | 8486 original content |
belaran@999 | 8487 unwanted change |
belaran@999 | 8488 </screen> |
belaran@999 | 8489 <!-- END daily.revert.status --> |
belaran@999 | 8490 |
belaran@999 | 8491 |
belaran@999 | 8492 <tip> |
belaran@999 | 8493 <title>Be careful with <filename moreinfo="none">.orig</filename> files</title> |
belaran@999 | 8494 |
belaran@999 | 8495 <para id="x_6b8">It's extremely unlikely that you are either using |
belaran@999 | 8496 Mercurial to manage files with <filename moreinfo="none">.orig</filename> |
belaran@999 | 8497 extensions or that you even care about the contents of such |
belaran@999 | 8498 files. Just in case, though, it's useful to remember that |
belaran@999 | 8499 <command role="hg-cmd" moreinfo="none">hg revert</command> will |
belaran@999 | 8500 unconditionally overwrite an existing file with a |
belaran@999 | 8501 <filename moreinfo="none">.orig</filename> extension. For instance, if you |
belaran@999 | 8502 already have a file named <filename moreinfo="none">foo.orig</filename> when |
belaran@999 | 8503 you revert <filename moreinfo="none">foo</filename>, the contents of |
belaran@999 | 8504 <filename moreinfo="none">foo.orig</filename> will be clobbered.</para> |
belaran@999 | 8505 </tip> |
belaran@999 | 8506 |
belaran@999 | 8507 <para id="x_e6">Here is a summary of the cases that the <command role="hg-cmd" moreinfo="none">hg revert</command> command can deal with. We |
belaran@999 | 8508 will describe each of these in more detail in the section that |
belaran@999 | 8509 follows.</para> |
belaran@999 | 8510 <itemizedlist> |
belaran@999 | 8511 <listitem><para id="x_e7">If you modify a file, it will restore the file |
belaran@999 | 8512 to its unmodified state.</para> |
belaran@999 | 8513 </listitem> |
belaran@999 | 8514 <listitem><para id="x_e8">If you <command role="hg-cmd" moreinfo="none">hg add</command> a |
belaran@999 | 8515 file, it will undo the <quote>added</quote> state of the |
belaran@999 | 8516 file, but leave the file itself untouched.</para> |
belaran@999 | 8517 </listitem> |
belaran@999 | 8518 <listitem><para id="x_e9">If you delete a file without telling Mercurial, |
belaran@999 | 8519 it will restore the file to its unmodified contents.</para> |
belaran@999 | 8520 </listitem> |
belaran@999 | 8521 <listitem><para id="x_ea">If you use the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8522 remove</command> command to remove a file, it will undo |
belaran@999 | 8523 the <quote>removed</quote> state of the file, and restore |
belaran@999 | 8524 the file to its unmodified contents.</para> |
belaran@999 | 8525 </listitem></itemizedlist> |
belaran@999 | 8526 |
belaran@999 | 8527 <sect2 id="sec:undo:mgmt"> |
belaran@999 | 8528 <title>File management errors</title> |
belaran@999 | 8529 |
belaran@999 | 8530 <para id="x_eb">The <command role="hg-cmd" moreinfo="none">hg revert</command> command is |
belaran@999 | 8531 useful for more than just modified files. It lets you reverse |
belaran@999 | 8532 the results of all of Mercurial's file management |
belaran@999 | 8533 commands—<command role="hg-cmd" moreinfo="none">hg add</command>, |
belaran@999 | 8534 <command role="hg-cmd" moreinfo="none">hg remove</command>, and so on.</para> |
belaran@999 | 8535 |
belaran@999 | 8536 <para id="x_ec">If you <command role="hg-cmd" moreinfo="none">hg add</command> a file, |
belaran@999 | 8537 then decide that in fact you don't want Mercurial to track it, |
belaran@999 | 8538 use <command role="hg-cmd" moreinfo="none">hg revert</command> to undo the |
belaran@999 | 8539 add. Don't worry; Mercurial will not modify the file in any |
belaran@999 | 8540 way. It will just <quote>unmark</quote> the file.</para> |
belaran@999 | 8541 |
belaran@999 | 8542 <!-- BEGIN daily.revert.add --> |
belaran@999 | 8543 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo oops > oops</userinput> |
belaran@999 | 8544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add oops</userinput> |
belaran@999 | 8545 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status oops</userinput> |
belaran@999 | 8546 A oops |
belaran@999 | 8547 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert oops</userinput> |
belaran@999 | 8548 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8549 ? oops |
belaran@999 | 8550 </screen> |
belaran@999 | 8551 <!-- END daily.revert.add --> |
belaran@999 | 8552 |
belaran@999 | 8553 |
belaran@999 | 8554 <para id="x_ed">Similarly, if you ask Mercurial to <command role="hg-cmd" moreinfo="none">hg remove</command> a file, you can use |
belaran@999 | 8555 <command role="hg-cmd" moreinfo="none">hg revert</command> to restore it to |
belaran@999 | 8556 the contents it had as of the parent of the working directory. |
belaran@999 | 8557 <!-- BEGIN daily.revert.remove --> |
belaran@999 | 8558 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg remove file</userinput> |
belaran@999 | 8559 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8560 R file |
belaran@999 | 8561 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput> |
belaran@999 | 8562 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8563 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput> |
belaran@999 | 8564 file |
belaran@999 | 8565 </screen> |
belaran@999 | 8566 <!-- END daily.revert.remove --> |
belaran@999 | 8567 This works just as |
belaran@999 | 8568 well for a file that you deleted by hand, without telling |
belaran@999 | 8569 Mercurial (recall that in Mercurial terminology, this kind of |
belaran@999 | 8570 file is called <quote>missing</quote>).</para> |
belaran@999 | 8571 |
belaran@999 | 8572 <!-- BEGIN daily.revert.missing --> |
belaran@999 | 8573 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">rm file</userinput> |
belaran@999 | 8574 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8575 ! file |
belaran@999 | 8576 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert file</userinput> |
belaran@999 | 8577 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls file</userinput> |
belaran@999 | 8578 file |
belaran@999 | 8579 </screen> |
belaran@999 | 8580 <!-- END daily.revert.missing --> |
belaran@999 | 8581 |
belaran@999 | 8582 |
belaran@999 | 8583 <para id="x_ee">If you revert a <command role="hg-cmd" moreinfo="none">hg copy</command>, |
belaran@999 | 8584 the copied-to file remains in your working directory |
belaran@999 | 8585 afterwards, untracked. Since a copy doesn't affect the |
belaran@999 | 8586 copied-from file in any way, Mercurial doesn't do anything |
belaran@999 | 8587 with the copied-from file.</para> |
belaran@999 | 8588 |
belaran@999 | 8589 <!-- BEGIN daily.revert.copy --> |
belaran@999 | 8590 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg copy file new-file</userinput> |
belaran@999 | 8591 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg revert new-file</userinput> |
belaran@999 | 8592 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 8593 ? new-file |
belaran@999 | 8594 </screen> |
belaran@999 | 8595 <!-- END daily.revert.copy --> |
belaran@999 | 8596 |
belaran@999 | 8597 </sect2> |
belaran@999 | 8598 </sect1> |
belaran@999 | 8599 |
belaran@999 | 8600 <sect1> |
belaran@999 | 8601 <title>Dealing with committed changes</title> |
belaran@999 | 8602 |
belaran@999 | 8603 <para id="x_f5">Consider a case where you have committed a change |
belaran@999 | 8604 <emphasis>a</emphasis>, and another change |
belaran@999 | 8605 <emphasis>b</emphasis> on top of it; you then realise that |
belaran@999 | 8606 change <emphasis>a</emphasis> was incorrect. Mercurial lets you |
belaran@999 | 8607 <quote>back out</quote> an entire changeset automatically, and |
belaran@999 | 8608 building blocks that let you reverse part of a changeset by |
belaran@999 | 8609 hand.</para> |
belaran@999 | 8610 |
belaran@999 | 8611 <para id="x_f6">Before you read this section, here's something to |
belaran@999 | 8612 keep in mind: the <command role="hg-cmd" moreinfo="none">hg backout</command> |
belaran@999 | 8613 command undoes the effect of a change by |
belaran@999 | 8614 <emphasis>adding</emphasis> to your repository's history, not by |
belaran@999 | 8615 modifying or erasing it. It's the right tool to use if you're |
belaran@999 | 8616 fixing bugs, but not if you're trying to undo some change that |
belaran@999 | 8617 has catastrophic consequences. To deal with those, see |
belaran@999 | 8618 <xref linkend="sec:undo:aaaiiieee"/>.</para> |
belaran@999 | 8619 |
belaran@999 | 8620 <sect2> |
belaran@999 | 8621 <title>Backing out a changeset</title> |
belaran@999 | 8622 |
belaran@999 | 8623 <para id="x_f7">The <command role="hg-cmd" moreinfo="none">hg backout</command> command |
belaran@999 | 8624 lets you <quote>undo</quote> the effects of an entire |
belaran@999 | 8625 changeset in an automated fashion. Because Mercurial's |
belaran@999 | 8626 history is immutable, this command <emphasis>does |
belaran@999 | 8627 not</emphasis> get rid of the changeset you want to undo. |
belaran@999 | 8628 Instead, it creates a new changeset that |
belaran@999 | 8629 <emphasis>reverses</emphasis> the effect of the to-be-undone |
belaran@999 | 8630 changeset.</para> |
belaran@999 | 8631 |
belaran@999 | 8632 <para id="x_f8">The operation of the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8633 backout</command> command is a little intricate, so let's |
belaran@999 | 8634 illustrate it with some examples. First, we'll create a |
belaran@999 | 8635 repository with some simple changes.</para> |
belaran@999 | 8636 |
belaran@999 | 8637 <!-- BEGIN backout.init --> |
belaran@999 | 8638 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput> |
belaran@999 | 8639 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput> |
belaran@999 | 8640 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo first change >> myfile</userinput> |
belaran@999 | 8641 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add myfile</userinput> |
belaran@999 | 8642 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'first change'</userinput> |
belaran@999 | 8643 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo second change >> myfile</userinput> |
belaran@999 | 8644 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'second change'</userinput> |
belaran@999 | 8645 </screen> |
belaran@999 | 8646 <!-- END backout.init --> |
belaran@999 | 8647 |
belaran@999 | 8648 |
belaran@999 | 8649 <para id="x_f9">The <command role="hg-cmd" moreinfo="none">hg backout</command> command |
belaran@999 | 8650 takes a single changeset ID as its argument; this is the |
belaran@999 | 8651 changeset to back out. Normally, <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8652 backout</command> will drop you into a text editor to write |
belaran@999 | 8653 a commit message, so you can record why you're backing the |
belaran@999 | 8654 change out. In this example, we provide a commit message on |
belaran@999 | 8655 the command line using the <option role="hg-opt-backout">-m</option> option.</para> |
belaran@999 | 8656 |
belaran@999 | 8657 </sect2> |
belaran@999 | 8658 <sect2> |
belaran@999 | 8659 <title>Backing out the tip changeset</title> |
belaran@999 | 8660 |
belaran@999 | 8661 <para id="x_fa">We're going to start by backing out the last changeset we |
belaran@999 | 8662 committed.</para> |
belaran@999 | 8663 |
belaran@999 | 8664 <!-- BEGIN backout.simple --> |
belaran@999 | 8665 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' tip</userinput> |
belaran@999 | 8666 reverting myfile |
belaran@999 | 8667 changeset 2:611a0cae251c backs out changeset 1:43700a9b3ec8 |
belaran@999 | 8668 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 8669 first change |
belaran@999 | 8670 </screen> |
belaran@999 | 8671 <!-- END backout.simple --> |
belaran@999 | 8672 |
belaran@999 | 8673 |
belaran@999 | 8674 <para id="x_fb">You can see that the second line from |
belaran@999 | 8675 <filename moreinfo="none">myfile</filename> is no longer present. Taking a |
belaran@999 | 8676 look at the output of <command role="hg-cmd" moreinfo="none">hg log</command> |
belaran@999 | 8677 gives us an idea of what the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 8678 backout</command> command has done. |
belaran@999 | 8679 <!-- BEGIN backout.simple.log --> |
belaran@999 | 8680 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput> |
belaran@999 | 8681 2[tip] 611a0cae251c 2009-08-16 14:04 +0000 bos |
belaran@999 | 8682 back out second change |
belaran@999 | 8683 |
belaran@999 | 8684 1 43700a9b3ec8 2009-08-16 14:04 +0000 bos |
belaran@999 | 8685 second change |
belaran@999 | 8686 |
belaran@999 | 8687 0 f2ef23d503fd 2009-08-16 14:04 +0000 bos |
belaran@999 | 8688 first change |
belaran@999 | 8689 |
belaran@999 | 8690 </screen> |
belaran@999 | 8691 <!-- END backout.simple.log --> |
belaran@999 | 8692 Notice that the new changeset |
belaran@999 | 8693 that <command role="hg-cmd" moreinfo="none">hg backout</command> has created |
belaran@999 | 8694 is a child of the changeset we backed out. It's easier to see |
belaran@999 | 8695 this in <xref linkend="fig:undo:backout"/>, which presents a |
belaran@999 | 8696 graphical view of the change history. As you can see, the |
belaran@999 | 8697 history is nice and linear.</para> |
belaran@999 | 8698 |
belaran@999 | 8699 <figure id="fig:undo:backout" float="0"> |
belaran@999 | 8700 <title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title> |
belaran@999 | 8701 <mediaobject> |
belaran@999 | 8702 <imageobject><imagedata fileref="figs/undo-simple.png"/></imageobject> |
belaran@999 | 8703 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 8704 </mediaobject> |
belaran@999 | 8705 </figure> |
belaran@999 | 8706 |
belaran@999 | 8707 </sect2> |
belaran@999 | 8708 <sect2> |
belaran@999 | 8709 <title>Backing out a non-tip change</title> |
belaran@999 | 8710 |
belaran@999 | 8711 <para id="x_fd">If you want to back out a change other than the last one |
belaran@999 | 8712 you committed, pass the <option role="hg-opt-backout">--merge</option> option to the |
belaran@999 | 8713 <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para> |
belaran@999 | 8714 |
belaran@999 | 8715 <!-- BEGIN backout.non-tip.clone --> |
belaran@999 | 8716 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 8717 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo non-tip-repo</userinput> |
belaran@999 | 8718 requesting all changes |
belaran@999 | 8719 adding changesets |
belaran@999 | 8720 adding manifests |
belaran@999 | 8721 adding file changes |
belaran@999 | 8722 added 2 changesets with 2 changes to 1 files |
belaran@999 | 8723 updating working directory |
belaran@999 | 8724 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 8725 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd non-tip-repo</userinput> |
belaran@999 | 8726 </screen> |
belaran@999 | 8727 <!-- END backout.non-tip.clone --> |
belaran@999 | 8728 |
belaran@999 | 8729 |
belaran@999 | 8730 <para id="x_fe">This makes backing out any changeset a |
belaran@999 | 8731 <quote>one-shot</quote> operation that's usually simple and |
belaran@999 | 8732 fast.</para> |
belaran@999 | 8733 |
belaran@999 | 8734 <!-- BEGIN backout.non-tip.backout --> |
belaran@999 | 8735 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change >> myfile</userinput> |
belaran@999 | 8736 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput> |
belaran@999 | 8737 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout --merge -m 'back out second change' 1</userinput> |
belaran@999 | 8738 reverting myfile |
belaran@999 | 8739 created new head |
belaran@999 | 8740 changeset 3:611a0cae251c backs out changeset 1:43700a9b3ec8 |
belaran@999 | 8741 merging with changeset 3:611a0cae251c |
belaran@999 | 8742 merging myfile |
belaran@999 | 8743 0 files updated, 1 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 8744 (branch merge, don't forget to commit) |
belaran@999 | 8745 </screen> |
belaran@999 | 8746 <!-- END backout.non-tip.backout --> |
belaran@999 | 8747 |
belaran@999 | 8748 |
belaran@999 | 8749 <para id="x_ff">If you take a look at the contents of |
belaran@999 | 8750 <filename moreinfo="none">myfile</filename> after the backout finishes, you'll |
belaran@999 | 8751 see that the first and third changes are present, but not the |
belaran@999 | 8752 second.</para> |
belaran@999 | 8753 |
belaran@999 | 8754 <!-- BEGIN backout.non-tip.cat --> |
belaran@999 | 8755 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 8756 first change |
belaran@999 | 8757 third change |
belaran@999 | 8758 </screen> |
belaran@999 | 8759 <!-- END backout.non-tip.cat --> |
belaran@999 | 8760 |
belaran@999 | 8761 |
belaran@999 | 8762 <para id="x_100">As the graphical history in <xref linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial |
belaran@999 | 8763 still commits one change in this kind of situation (the |
belaran@999 | 8764 box-shaped node is the ones that Mercurial commits |
belaran@999 | 8765 automatically), but the revision graph now looks different. |
belaran@999 | 8766 Before Mercurial begins the backout process, it first |
belaran@999 | 8767 remembers what the current parent of the working directory is. |
belaran@999 | 8768 It then backs out the target changeset, and commits that as a |
belaran@999 | 8769 changeset. Finally, it merges back to the previous parent of |
belaran@999 | 8770 the working directory, but notice that it <emphasis>does not |
belaran@999 | 8771 commit</emphasis> the result of the merge. The repository |
belaran@999 | 8772 now contains two heads, and the working directory is in a |
belaran@999 | 8773 merge state.</para> |
belaran@999 | 8774 |
belaran@999 | 8775 <figure id="fig:undo:backout-non-tip" float="0"> |
belaran@999 | 8776 <title>Automated backout of a non-tip change using the |
belaran@999 | 8777 <command role="hg-cmd" moreinfo="none">hg backout</command> command</title> |
belaran@999 | 8778 <mediaobject> |
belaran@999 | 8779 <imageobject><imagedata fileref="figs/undo-non-tip.png"/></imageobject> |
belaran@999 | 8780 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 8781 </mediaobject> |
belaran@999 | 8782 </figure> |
belaran@999 | 8783 |
belaran@999 | 8784 <para id="x_103">The result is that you end up <quote>back where you |
belaran@999 | 8785 were</quote>, only with some extra history that undoes the |
belaran@999 | 8786 effect of the changeset you wanted to back out.</para> |
belaran@999 | 8787 |
belaran@999 | 8788 <para id="x_6b9">You might wonder why Mercurial does not commit the result |
belaran@999 | 8789 of the merge that it performed. The reason lies in Mercurial |
belaran@999 | 8790 behaving conservatively: a merge naturally has more scope for |
belaran@999 | 8791 error than simply undoing the effect of the tip changeset, |
belaran@999 | 8792 so your work will be safest if you first inspect (and test!) |
belaran@999 | 8793 the result of the merge, <emphasis>then</emphasis> commit |
belaran@999 | 8794 it.</para> |
belaran@999 | 8795 |
belaran@999 | 8796 <sect3> |
belaran@999 | 8797 <title>Always use the <option role="hg-opt-backout">--merge</option> option</title> |
belaran@999 | 8798 |
belaran@999 | 8799 <para id="x_104">In fact, since the <option role="hg-opt-backout">--merge</option> option will do the |
belaran@999 | 8800 <quote>right thing</quote> whether or not the changeset |
belaran@999 | 8801 you're backing out is the tip (i.e. it won't try to merge if |
belaran@999 | 8802 it's backing out the tip, since there's no need), you should |
belaran@999 | 8803 <emphasis>always</emphasis> use this option when you run the |
belaran@999 | 8804 <command role="hg-cmd" moreinfo="none">hg backout</command> command.</para> |
belaran@999 | 8805 |
belaran@999 | 8806 </sect3> |
belaran@999 | 8807 </sect2> |
belaran@999 | 8808 <sect2> |
belaran@999 | 8809 <title>Gaining more control of the backout process</title> |
belaran@999 | 8810 |
belaran@999 | 8811 <para id="x_105">While I've recommended that you always use the <option role="hg-opt-backout">--merge</option> option when backing |
belaran@999 | 8812 out a change, the <command role="hg-cmd" moreinfo="none">hg backout</command> |
belaran@999 | 8813 command lets you decide how to merge a backout changeset. |
belaran@999 | 8814 Taking control of the backout process by hand is something you |
belaran@999 | 8815 will rarely need to do, but it can be useful to understand |
belaran@999 | 8816 what the <command role="hg-cmd" moreinfo="none">hg backout</command> command |
belaran@999 | 8817 is doing for you automatically. To illustrate this, let's |
belaran@999 | 8818 clone our first repository, but omit the backout change that |
belaran@999 | 8819 it contains.</para> |
belaran@999 | 8820 |
belaran@999 | 8821 <!-- BEGIN backout.manual.clone --> |
belaran@999 | 8822 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 8823 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone -r1 myrepo newrepo</userinput> |
belaran@999 | 8824 requesting all changes |
belaran@999 | 8825 adding changesets |
belaran@999 | 8826 adding manifests |
belaran@999 | 8827 adding file changes |
belaran@999 | 8828 added 2 changesets with 2 changes to 1 files |
belaran@999 | 8829 updating working directory |
belaran@999 | 8830 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 8831 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd newrepo</userinput> |
belaran@999 | 8832 </screen> |
belaran@999 | 8833 <!-- END backout.manual.clone --> |
belaran@999 | 8834 |
belaran@999 | 8835 |
belaran@999 | 8836 <para id="x_106">As with our |
belaran@999 | 8837 earlier example, We'll commit a third changeset, then back out |
belaran@999 | 8838 its parent, and see what happens.</para> |
belaran@999 | 8839 |
belaran@999 | 8840 <!-- BEGIN backout.manual.backout --> |
belaran@999 | 8841 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo third change >> myfile</userinput> |
belaran@999 | 8842 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'third change'</userinput> |
belaran@999 | 8843 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg backout -m 'back out second change' 1</userinput> |
belaran@999 | 8844 reverting myfile |
belaran@999 | 8845 created new head |
belaran@999 | 8846 changeset 3:bf906ee0baae backs out changeset 1:43700a9b3ec8 |
belaran@999 | 8847 the backout changeset is a new head - do not forget to merge |
belaran@999 | 8848 (use "backout --merge" if you want to auto-merge) |
belaran@999 | 8849 </screen> |
belaran@999 | 8850 <!-- END backout.manual.backout --> |
belaran@999 | 8851 |
belaran@999 | 8852 |
belaran@999 | 8853 <para id="x_107">Our new changeset is again a descendant of the changeset |
belaran@999 | 8854 we backout out; it's thus a new head, <emphasis>not</emphasis> |
belaran@999 | 8855 a descendant of the changeset that was the tip. The <command role="hg-cmd" moreinfo="none">hg backout</command> command was quite |
belaran@999 | 8856 explicit in telling us this.</para> |
belaran@999 | 8857 |
belaran@999 | 8858 <!-- BEGIN backout.manual.log --> |
belaran@999 | 8859 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput> |
belaran@999 | 8860 3[tip]:1 bf906ee0baae 2009-08-16 14:04 +0000 bos |
belaran@999 | 8861 back out second change |
belaran@999 | 8862 |
belaran@999 | 8863 2 2521379001ad 2009-08-16 14:04 +0000 bos |
belaran@999 | 8864 third change |
belaran@999 | 8865 |
belaran@999 | 8866 1 43700a9b3ec8 2009-08-16 14:04 +0000 bos |
belaran@999 | 8867 second change |
belaran@999 | 8868 |
belaran@999 | 8869 0 f2ef23d503fd 2009-08-16 14:04 +0000 bos |
belaran@999 | 8870 first change |
belaran@999 | 8871 |
belaran@999 | 8872 </screen> |
belaran@999 | 8873 <!-- END backout.manual.log --> |
belaran@999 | 8874 |
belaran@999 | 8875 |
belaran@999 | 8876 <para id="x_108">Again, it's easier to see what has happened by looking at |
belaran@999 | 8877 a graph of the revision history, in <xref linkend="fig:undo:backout-manual"/>. This makes it clear |
belaran@999 | 8878 that when we use <command role="hg-cmd" moreinfo="none">hg backout</command> |
belaran@999 | 8879 to back out a change other than the tip, Mercurial adds a new |
belaran@999 | 8880 head to the repository (the change it committed is |
belaran@999 | 8881 box-shaped).</para> |
belaran@999 | 8882 |
belaran@999 | 8883 <figure id="fig:undo:backout-manual" float="0"> |
belaran@999 | 8884 <title>Backing out a change using the <command role="hg-cmd" moreinfo="none">hg backout</command> command</title> |
belaran@999 | 8885 <mediaobject> |
belaran@999 | 8886 <imageobject><imagedata fileref="figs/undo-manual.png"/></imageobject> |
belaran@999 | 8887 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 8888 </mediaobject> |
belaran@999 | 8889 </figure> |
belaran@999 | 8890 |
belaran@999 | 8891 <para id="x_10a">After the <command role="hg-cmd" moreinfo="none">hg backout</command> |
belaran@999 | 8892 command has completed, it leaves the new |
belaran@999 | 8893 <quote>backout</quote> changeset as the parent of the working |
belaran@999 | 8894 directory.</para> |
belaran@999 | 8895 |
belaran@999 | 8896 <!-- BEGIN backout.manual.parents --> |
belaran@999 | 8897 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg parents</userinput> |
belaran@999 | 8898 changeset: 2:2521379001ad |
belaran@999 | 8899 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8900 date: Sun Aug 16 14:04:37 2009 +0000 |
belaran@999 | 8901 summary: third change |
belaran@999 | 8902 |
belaran@999 | 8903 </screen> |
belaran@999 | 8904 <!-- END backout.manual.parents --> |
belaran@999 | 8905 |
belaran@999 | 8906 |
belaran@999 | 8907 <para id="x_10b">Now we have two isolated sets of changes.</para> |
belaran@999 | 8908 |
belaran@999 | 8909 <!-- BEGIN backout.manual.heads --> |
belaran@999 | 8910 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg heads</userinput> |
belaran@999 | 8911 changeset: 3:bf906ee0baae |
belaran@999 | 8912 tag: tip |
belaran@999 | 8913 parent: 1:43700a9b3ec8 |
belaran@999 | 8914 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8915 date: Sun Aug 16 14:04:37 2009 +0000 |
belaran@999 | 8916 summary: back out second change |
belaran@999 | 8917 |
belaran@999 | 8918 changeset: 2:2521379001ad |
belaran@999 | 8919 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 8920 date: Sun Aug 16 14:04:37 2009 +0000 |
belaran@999 | 8921 summary: third change |
belaran@999 | 8922 |
belaran@999 | 8923 </screen> |
belaran@999 | 8924 <!-- END backout.manual.heads --> |
belaran@999 | 8925 |
belaran@999 | 8926 |
belaran@999 | 8927 <para id="x_10c">Let's think about what we expect to see as the contents of |
belaran@999 | 8928 <filename moreinfo="none">myfile</filename> now. The first change should be |
belaran@999 | 8929 present, because we've never backed it out. The second change |
belaran@999 | 8930 should be missing, as that's the change we backed out. Since |
belaran@999 | 8931 the history graph shows the third change as a separate head, |
belaran@999 | 8932 we <emphasis>don't</emphasis> expect to see the third change |
belaran@999 | 8933 present in <filename moreinfo="none">myfile</filename>.</para> |
belaran@999 | 8934 |
belaran@999 | 8935 <!-- BEGIN backout.manual.cat --> |
belaran@999 | 8936 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 8937 first change |
belaran@999 | 8938 </screen> |
belaran@999 | 8939 <!-- END backout.manual.cat --> |
belaran@999 | 8940 |
belaran@999 | 8941 |
belaran@999 | 8942 <para id="x_10d">To get the third change back into the file, we just do a |
belaran@999 | 8943 normal merge of our two heads.</para> |
belaran@999 | 8944 |
belaran@999 | 8945 <!-- BEGIN backout.manual.merge --> |
belaran@999 | 8946 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg merge</userinput> |
belaran@999 | 8947 abort: outstanding uncommitted changes |
belaran@999 | 8948 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'merged backout with previous tip'</userinput> |
belaran@999 | 8949 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat myfile</userinput> |
belaran@999 | 8950 first change |
belaran@999 | 8951 </screen> |
belaran@999 | 8952 <!-- END backout.manual.merge --> |
belaran@999 | 8953 |
belaran@999 | 8954 |
belaran@999 | 8955 <para id="x_10e">Afterwards, the graphical history of our |
belaran@999 | 8956 repository looks like |
belaran@999 | 8957 <xref linkend="fig:undo:backout-manual-merge"/>.</para> |
belaran@999 | 8958 |
belaran@999 | 8959 <figure id="fig:undo:backout-manual-merge" float="0"> |
belaran@999 | 8960 <title>Manually merging a backout change</title> |
belaran@999 | 8961 <mediaobject> |
belaran@999 | 8962 <imageobject><imagedata fileref="figs/undo-manual-merge.png"/></imageobject> |
belaran@999 | 8963 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 8964 </mediaobject> |
belaran@999 | 8965 </figure> |
belaran@999 | 8966 |
belaran@999 | 8967 </sect2> |
belaran@999 | 8968 <sect2> |
belaran@999 | 8969 <title>Why <command role="hg-cmd" moreinfo="none">hg backout</command> works as |
belaran@999 | 8970 it does</title> |
belaran@999 | 8971 |
belaran@999 | 8972 <para id="x_110">Here's a brief description of how the <command role="hg-cmd" moreinfo="none">hg backout</command> command works.</para> |
belaran@999 | 8973 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 8974 <listitem><para id="x_111">It ensures that the working directory is |
belaran@999 | 8975 <quote>clean</quote>, i.e. that the output of <command role="hg-cmd" moreinfo="none">hg status</command> would be empty.</para> |
belaran@999 | 8976 </listitem> |
belaran@999 | 8977 <listitem><para id="x_112">It remembers the current parent of the working |
belaran@999 | 8978 directory. Let's call this changeset |
belaran@999 | 8979 <literal moreinfo="none">orig</literal>.</para> |
belaran@999 | 8980 </listitem> |
belaran@999 | 8981 <listitem><para id="x_113">It does the equivalent of a <command role="hg-cmd" moreinfo="none">hg update</command> to sync the working |
belaran@999 | 8982 directory to the changeset you want to back out. Let's |
belaran@999 | 8983 call this changeset <literal moreinfo="none">backout</literal>.</para> |
belaran@999 | 8984 </listitem> |
belaran@999 | 8985 <listitem><para id="x_114">It finds the parent of that changeset. Let's |
belaran@999 | 8986 call that changeset <literal moreinfo="none">parent</literal>.</para> |
belaran@999 | 8987 </listitem> |
belaran@999 | 8988 <listitem><para id="x_115">For each file that the |
belaran@999 | 8989 <literal moreinfo="none">backout</literal> changeset affected, it does the |
belaran@999 | 8990 equivalent of a <command role="hg-cmd" moreinfo="none">hg revert -r |
belaran@999 | 8991 parent</command> on that file, to restore it to the |
belaran@999 | 8992 contents it had before that changeset was |
belaran@999 | 8993 committed.</para> |
belaran@999 | 8994 </listitem> |
belaran@999 | 8995 <listitem><para id="x_116">It commits the result as a new changeset. |
belaran@999 | 8996 This changeset has <literal moreinfo="none">backout</literal> as its |
belaran@999 | 8997 parent.</para> |
belaran@999 | 8998 </listitem> |
belaran@999 | 8999 <listitem><para id="x_117">If you specify <option role="hg-opt-backout">--merge</option> on the command |
belaran@999 | 9000 line, it merges with <literal moreinfo="none">orig</literal>, and commits |
belaran@999 | 9001 the result of the merge.</para> |
belaran@999 | 9002 </listitem></orderedlist> |
belaran@999 | 9003 |
belaran@999 | 9004 <para id="x_118">An alternative way to implement the <command role="hg-cmd" moreinfo="none">hg backout</command> command would be to |
belaran@999 | 9005 <command role="hg-cmd" moreinfo="none">hg export</command> the |
belaran@999 | 9006 to-be-backed-out changeset as a diff, then use the <option role="cmd-opt-patch">--reverse</option> option to the |
belaran@999 | 9007 <command moreinfo="none">patch</command> command to reverse the effect of the |
belaran@999 | 9008 change without fiddling with the working directory. This |
belaran@999 | 9009 sounds much simpler, but it would not work nearly as |
belaran@999 | 9010 well.</para> |
belaran@999 | 9011 |
belaran@999 | 9012 <para id="x_119">The reason that <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9013 backout</command> does an update, a commit, a merge, and |
belaran@999 | 9014 another commit is to give the merge machinery the best chance |
belaran@999 | 9015 to do a good job when dealing with all the changes |
belaran@999 | 9016 <emphasis>between</emphasis> the change you're backing out and |
belaran@999 | 9017 the current tip.</para> |
belaran@999 | 9018 |
belaran@999 | 9019 <para id="x_11a">If you're backing out a changeset that's 100 revisions |
belaran@999 | 9020 back in your project's history, the chances that the |
belaran@999 | 9021 <command moreinfo="none">patch</command> command will be able to apply a |
belaran@999 | 9022 reverse diff cleanly are not good, because intervening changes |
belaran@999 | 9023 are likely to have <quote>broken the context</quote> that |
belaran@999 | 9024 <command moreinfo="none">patch</command> uses to determine whether it can |
belaran@999 | 9025 apply a patch (if this sounds like gibberish, see <xref linkend="sec:mq:patch"/> for a |
belaran@999 | 9026 discussion of the <command moreinfo="none">patch</command> command). Also, |
belaran@999 | 9027 Mercurial's merge machinery will handle files and directories |
belaran@999 | 9028 being renamed, permission changes, and modifications to binary |
belaran@999 | 9029 files, none of which <command moreinfo="none">patch</command> can deal |
belaran@999 | 9030 with.</para> |
belaran@999 | 9031 |
belaran@999 | 9032 </sect2> |
belaran@999 | 9033 </sect1> |
belaran@999 | 9034 <sect1 id="sec:undo:aaaiiieee"> |
belaran@999 | 9035 <title>Changes that should never have been</title> |
belaran@999 | 9036 |
belaran@999 | 9037 <para id="x_11b">Most of the time, the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9038 backout</command> command is exactly what you need if you want |
belaran@999 | 9039 to undo the effects of a change. It leaves a permanent record |
belaran@999 | 9040 of exactly what you did, both when committing the original |
belaran@999 | 9041 changeset and when you cleaned up after it.</para> |
belaran@999 | 9042 |
belaran@999 | 9043 <para id="x_11c">On rare occasions, though, you may find that you've |
belaran@999 | 9044 committed a change that really should not be present in the |
belaran@999 | 9045 repository at all. For example, it would be very unusual, and |
belaran@999 | 9046 usually considered a mistake, to commit a software project's |
belaran@999 | 9047 object files as well as its source files. Object files have |
belaran@999 | 9048 almost no intrinsic value, and they're <emphasis>big</emphasis>, |
belaran@999 | 9049 so they increase the size of the repository and the amount of |
belaran@999 | 9050 time it takes to clone or pull changes.</para> |
belaran@999 | 9051 |
belaran@999 | 9052 <para id="x_11d">Before I discuss the options that you have if you commit a |
belaran@999 | 9053 <quote>brown paper bag</quote> change (the kind that's so bad |
belaran@999 | 9054 that you want to pull a brown paper bag over your head), let me |
belaran@999 | 9055 first discuss some approaches that probably won't work.</para> |
belaran@999 | 9056 |
belaran@999 | 9057 <para id="x_11e">Since Mercurial treats history as |
belaran@999 | 9058 accumulative—every change builds on top of all changes |
belaran@999 | 9059 that preceded it—you generally can't just make disastrous |
belaran@999 | 9060 changes disappear. The one exception is when you've just |
belaran@999 | 9061 committed a change, and it hasn't been pushed or pulled into |
belaran@999 | 9062 another repository. That's when you can safely use the <command role="hg-cmd" moreinfo="none">hg rollback</command> command, as I detailed in |
belaran@999 | 9063 <xref linkend="sec:undo:rollback"/>.</para> |
belaran@999 | 9064 |
belaran@999 | 9065 <para id="x_11f">After you've pushed a bad change to another repository, you |
belaran@999 | 9066 <emphasis>could</emphasis> still use <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9067 rollback</command> to make your local copy of the change |
belaran@999 | 9068 disappear, but it won't have the consequences you want. The |
belaran@999 | 9069 change will still be present in the remote repository, so it |
belaran@999 | 9070 will reappear in your local repository the next time you |
belaran@999 | 9071 pull.</para> |
belaran@999 | 9072 |
belaran@999 | 9073 <para id="x_120">If a situation like this arises, and you know which |
belaran@999 | 9074 repositories your bad change has propagated into, you can |
belaran@999 | 9075 <emphasis>try</emphasis> to get rid of the change from |
belaran@999 | 9076 <emphasis>every</emphasis> one of those repositories. This is, |
belaran@999 | 9077 of course, not a satisfactory solution: if you miss even a |
belaran@999 | 9078 single repository while you're expunging, the change is still |
belaran@999 | 9079 <quote>in the wild</quote>, and could propagate further.</para> |
belaran@999 | 9080 |
belaran@999 | 9081 <para id="x_121">If you've committed one or more changes |
belaran@999 | 9082 <emphasis>after</emphasis> the change that you'd like to see |
belaran@999 | 9083 disappear, your options are further reduced. Mercurial doesn't |
belaran@999 | 9084 provide a way to <quote>punch a hole</quote> in history, leaving |
belaran@999 | 9085 changesets intact.</para> |
belaran@999 | 9086 |
belaran@999 | 9087 <sect2> |
belaran@999 | 9088 <title>Backing out a merge</title> |
belaran@999 | 9089 |
belaran@999 | 9090 <para id="x_6ba">Since merges are often complicated, it is not unheard of |
belaran@999 | 9091 for a merge to be mangled badly, but committed erroneously. |
belaran@999 | 9092 Mercurial provides an important safeguard against bad merges |
belaran@999 | 9093 by refusing to commit unresolved files, but human ingenuity |
belaran@999 | 9094 guarantees that it is still possible to mess a merge up and |
belaran@999 | 9095 commit it.</para> |
belaran@999 | 9096 |
belaran@999 | 9097 <para id="x_6bb">Given a bad merge that has been committed, usually the |
belaran@999 | 9098 best way to approach it is to simply try to repair the damage |
belaran@999 | 9099 by hand. A complete disaster that cannot be easily fixed up |
belaran@999 | 9100 by hand ought to be very rare, but the <command role="hg-cmd" moreinfo="none">hg backout</command> command may help in |
belaran@999 | 9101 making the cleanup easier. It offers a <option role="hg-opt-backout">--parent</option> option, which lets |
belaran@999 | 9102 you specify which parent to revert to when backing out a |
belaran@999 | 9103 merge.</para> |
belaran@999 | 9104 |
belaran@999 | 9105 <figure id="fig:undo:bad-merge-1" float="0"> |
belaran@999 | 9106 <title>A bad merge</title> |
belaran@999 | 9107 <mediaobject> |
belaran@999 | 9108 <imageobject><imagedata fileref="figs/bad-merge-1.png"/></imageobject> |
belaran@999 | 9109 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 9110 </mediaobject> |
belaran@999 | 9111 </figure> |
belaran@999 | 9112 |
belaran@999 | 9113 <para id="x_6bc">Suppose we have a revision graph like that in <xref linkend="fig:undo:bad-merge-1"/>. What we'd like is to |
belaran@999 | 9114 <emphasis>redo</emphasis> the merge of revisions 2 and |
belaran@999 | 9115 3.</para> |
belaran@999 | 9116 |
belaran@999 | 9117 <para id="x_6bd">One way to do so would be as follows.</para> |
belaran@999 | 9118 |
belaran@999 | 9119 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 9120 <listitem> |
belaran@999 | 9121 <para id="x_6be">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4 |
belaran@999 | 9122 --parent=2</command>. This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision |
belaran@999 | 9123 4, which is the bad merge, and to when deciding which |
belaran@999 | 9124 revision to prefer, to choose parent 2, one of the parents |
belaran@999 | 9125 of the merge. The effect can be seen in <xref linkend="fig:undo:bad-merge-2"/>.</para> |
belaran@999 | 9126 <figure id="fig:undo:bad-merge-2" float="0"> |
belaran@999 | 9127 <title>Backing out the merge, favoring one parent</title> |
belaran@999 | 9128 <mediaobject> |
belaran@999 | 9129 <imageobject><imagedata fileref="figs/bad-merge-2.png"/></imageobject> |
belaran@999 | 9130 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 9131 </mediaobject> |
belaran@999 | 9132 </figure> |
belaran@999 | 9133 </listitem> |
belaran@999 | 9134 |
belaran@999 | 9135 <listitem> |
belaran@999 | 9136 <para id="x_6bf">Call <command role="hg-cmd" moreinfo="none">hg backout --rev=4 |
belaran@999 | 9137 --parent=3</command>. This tells <command role="hg-cmd" moreinfo="none">hg backout</command> to back out revision |
belaran@999 | 9138 4 again, but this time to choose parent 3, the other |
belaran@999 | 9139 parent of the merge. The result is visible in <xref linkend="fig:undo:bad-merge-3"/>, in which the repository |
belaran@999 | 9140 now contains three heads.</para> |
belaran@999 | 9141 <figure id="fig:undo:bad-merge-3" float="0"> |
belaran@999 | 9142 <title>Backing out the merge, favoring the other |
belaran@999 | 9143 parent</title> |
belaran@999 | 9144 <mediaobject> |
belaran@999 | 9145 <imageobject><imagedata fileref="figs/bad-merge-3.png"/></imageobject> |
belaran@999 | 9146 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 9147 </mediaobject> |
belaran@999 | 9148 </figure> |
belaran@999 | 9149 </listitem> |
belaran@999 | 9150 |
belaran@999 | 9151 <listitem> |
belaran@999 | 9152 <para id="x_6c0">Redo the bad merge by merging the two backout heads, |
belaran@999 | 9153 which reduces the number of heads in the repository to |
belaran@999 | 9154 two, as can be seen in <xref linkend="fig:undo:bad-merge-4"/>.</para> |
belaran@999 | 9155 <figure id="fig:undo:bad-merge-4" float="0"> |
belaran@999 | 9156 <title>Merging the backouts</title> |
belaran@999 | 9157 <mediaobject> |
belaran@999 | 9158 <imageobject><imagedata fileref="figs/bad-merge-4.png"/></imageobject> |
belaran@999 | 9159 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 9160 </mediaobject> |
belaran@999 | 9161 </figure> |
belaran@999 | 9162 </listitem> |
belaran@999 | 9163 |
belaran@999 | 9164 <listitem> |
belaran@999 | 9165 <para id="x_6c1">Merge with the commit that was made after the bad |
belaran@999 | 9166 merge, as shown in <xref linkend="fig:undo:bad-merge-5"/>.</para> |
belaran@999 | 9167 <figure id="fig:undo:bad-merge-5" float="0"> |
belaran@999 | 9168 <title>Merging the backouts</title> |
belaran@999 | 9169 <mediaobject> |
belaran@999 | 9170 <imageobject><imagedata fileref="figs/bad-merge-5.png"/></imageobject> |
belaran@999 | 9171 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 9172 </mediaobject> |
belaran@999 | 9173 </figure> |
belaran@999 | 9174 </listitem> |
belaran@999 | 9175 </orderedlist> |
belaran@999 | 9176 </sect2> |
belaran@999 | 9177 |
belaran@999 | 9178 <sect2> |
belaran@999 | 9179 <title>Protect yourself from <quote>escaped</quote> |
belaran@999 | 9180 changes</title> |
belaran@999 | 9181 |
belaran@999 | 9182 <para id="x_123">If you've committed some changes to your local repository |
belaran@999 | 9183 and they've been pushed or pulled somewhere else, this isn't |
belaran@999 | 9184 necessarily a disaster. You can protect yourself ahead of |
belaran@999 | 9185 time against some classes of bad changeset. This is |
belaran@999 | 9186 particularly easy if your team usually pulls changes from a |
belaran@999 | 9187 central repository.</para> |
belaran@999 | 9188 |
belaran@999 | 9189 <para id="x_124">By configuring some hooks on that repository to validate |
belaran@999 | 9190 incoming changesets (see chapter <xref linkend="chap:hook"/>), |
belaran@999 | 9191 you can |
belaran@999 | 9192 automatically prevent some kinds of bad changeset from being |
belaran@999 | 9193 pushed to the central repository at all. With such a |
belaran@999 | 9194 configuration in place, some kinds of bad changeset will |
belaran@999 | 9195 naturally tend to <quote>die out</quote> because they can't |
belaran@999 | 9196 propagate into the central repository. Better yet, this |
belaran@999 | 9197 happens without any need for explicit intervention.</para> |
belaran@999 | 9198 |
belaran@999 | 9199 <para id="x_125">For instance, an incoming change hook that |
belaran@999 | 9200 verifies that a changeset will actually compile can prevent |
belaran@999 | 9201 people from inadvertently <quote>breaking the |
belaran@999 | 9202 build</quote>.</para> |
belaran@999 | 9203 </sect2> |
belaran@999 | 9204 |
belaran@999 | 9205 <sect2> |
belaran@999 | 9206 <title>What to do about sensitive changes that escape</title> |
belaran@999 | 9207 |
belaran@999 | 9208 <para id="x_6c2">Even a carefully run project can suffer an unfortunate |
belaran@999 | 9209 event such as the committing and uncontrolled propagation of a |
belaran@999 | 9210 file that contains important passwords.</para> |
belaran@999 | 9211 |
belaran@999 | 9212 <para id="x_6c3">If something like this happens to you, and the information |
belaran@999 | 9213 that gets accidentally propagated is truly sensitive, your |
belaran@999 | 9214 first step should be to mitigate the effect of the leak |
belaran@999 | 9215 without trying to control the leak itself. If you are not 100% |
belaran@999 | 9216 certain that you know exactly who could have seen the changes, |
belaran@999 | 9217 you should immediately change passwords, cancel credit cards, |
belaran@999 | 9218 or find some other way to make sure that the information that |
belaran@999 | 9219 has leaked is no longer useful. In other words, assume that |
belaran@999 | 9220 the change has propagated far and wide, and that there's |
belaran@999 | 9221 nothing more you can do.</para> |
belaran@999 | 9222 |
belaran@999 | 9223 <para id="x_6c4">You might hope that there would be mechanisms you could |
belaran@999 | 9224 use to either figure out who has seen a change or to erase the |
belaran@999 | 9225 change permanently everywhere, but there are good reasons why |
belaran@999 | 9226 these are not possible.</para> |
belaran@999 | 9227 |
belaran@999 | 9228 <para id="x_6c5">Mercurial does not provide an audit trail of who has |
belaran@999 | 9229 pulled changes from a repository, because it is usually either |
belaran@999 | 9230 impossible to record such information or trivial to spoof it. |
belaran@999 | 9231 In a multi-user or networked environment, you should thus be |
belaran@999 | 9232 extremely skeptical of yourself if you think that you have |
belaran@999 | 9233 identified every place that a sensitive changeset has |
belaran@999 | 9234 propagated to. Don't forget that people can and will send |
belaran@999 | 9235 bundles by email, have their backup software save data |
belaran@999 | 9236 offsite, carry repositories on USB sticks, and find other |
belaran@999 | 9237 completely innocent ways to confound your attempts to track |
belaran@999 | 9238 down every copy of a problematic change.</para> |
belaran@999 | 9239 |
belaran@999 | 9240 <para id="x_6c6">Mercurial also does not provide a way to make a file or |
belaran@999 | 9241 changeset completely disappear from history, because there is |
belaran@999 | 9242 no way to enforce its disappearance; someone could easily |
belaran@999 | 9243 modify their copy of Mercurial to ignore such directives. In |
belaran@999 | 9244 addition, even if Mercurial provided such a capability, |
belaran@999 | 9245 someone who simply hadn't pulled a <quote>make this file |
belaran@999 | 9246 disappear</quote> changeset wouldn't be affected by it, nor |
belaran@999 | 9247 would web crawlers visiting at the wrong time, disk backups, |
belaran@999 | 9248 or other mechanisms. Indeed, no distributed revision control |
belaran@999 | 9249 system can make data reliably vanish. Providing the illusion |
belaran@999 | 9250 of such control could easily give a false sense of security, |
belaran@999 | 9251 and be worse than not providing it at all.</para> |
belaran@999 | 9252 </sect2> |
belaran@999 | 9253 </sect1> |
belaran@999 | 9254 |
belaran@999 | 9255 <sect1 id="sec:undo:bisect"> |
belaran@999 | 9256 <title>Finding the source of a bug</title> |
belaran@999 | 9257 |
belaran@999 | 9258 <para id="x_126">While it's all very well to be able to back out a changeset |
belaran@999 | 9259 that introduced a bug, this requires that you know which |
belaran@999 | 9260 changeset to back out. Mercurial provides an invaluable |
belaran@999 | 9261 command, called <command role="hg-cmd" moreinfo="none">hg bisect</command>, that |
belaran@999 | 9262 helps you to automate this process and accomplish it very |
belaran@999 | 9263 efficiently.</para> |
belaran@999 | 9264 |
belaran@999 | 9265 <para id="x_127">The idea behind the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9266 bisect</command> command is that a changeset has introduced |
belaran@999 | 9267 some change of behavior that you can identify with a simple |
belaran@999 | 9268 pass/fail test. You don't know which piece of code introduced the |
belaran@999 | 9269 change, but you know how to test for the presence of the bug. |
belaran@999 | 9270 The <command role="hg-cmd" moreinfo="none">hg bisect</command> command uses your |
belaran@999 | 9271 test to direct its search for the changeset that introduced the |
belaran@999 | 9272 code that caused the bug.</para> |
belaran@999 | 9273 |
belaran@999 | 9274 <para id="x_128">Here are a few scenarios to help you understand how you |
belaran@999 | 9275 might apply this command.</para> |
belaran@999 | 9276 <itemizedlist> |
belaran@999 | 9277 <listitem><para id="x_129">The most recent version of your software has a |
belaran@999 | 9278 bug that you remember wasn't present a few weeks ago, but |
belaran@999 | 9279 you don't know when it was introduced. Here, your binary |
belaran@999 | 9280 test checks for the presence of that bug.</para> |
belaran@999 | 9281 </listitem> |
belaran@999 | 9282 <listitem><para id="x_12a">You fixed a bug in a rush, and now it's time to |
belaran@999 | 9283 close the entry in your team's bug database. The bug |
belaran@999 | 9284 database requires a changeset ID when you close an entry, |
belaran@999 | 9285 but you don't remember which changeset you fixed the bug in. |
belaran@999 | 9286 Once again, your binary test checks for the presence of the |
belaran@999 | 9287 bug.</para> |
belaran@999 | 9288 </listitem> |
belaran@999 | 9289 <listitem><para id="x_12b">Your software works correctly, but runs 15% |
belaran@999 | 9290 slower than the last time you measured it. You want to know |
belaran@999 | 9291 which changeset introduced the performance regression. In |
belaran@999 | 9292 this case, your binary test measures the performance of your |
belaran@999 | 9293 software, to see whether it's <quote>fast</quote> or |
belaran@999 | 9294 <quote>slow</quote>.</para> |
belaran@999 | 9295 </listitem> |
belaran@999 | 9296 <listitem><para id="x_12c">The sizes of the components of your project that |
belaran@999 | 9297 you ship exploded recently, and you suspect that something |
belaran@999 | 9298 changed in the way you build your project.</para> |
belaran@999 | 9299 </listitem></itemizedlist> |
belaran@999 | 9300 |
belaran@999 | 9301 <para id="x_12d">From these examples, it should be clear that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command is not useful only |
belaran@999 | 9302 for finding the sources of bugs. You can use it to find any |
belaran@999 | 9303 <quote>emergent property</quote> of a repository (anything that |
belaran@999 | 9304 you can't find from a simple text search of the files in the |
belaran@999 | 9305 tree) for which you can write a binary test.</para> |
belaran@999 | 9306 |
belaran@999 | 9307 <para id="x_12e">We'll introduce a little bit of terminology here, just to |
belaran@999 | 9308 make it clear which parts of the search process are your |
belaran@999 | 9309 responsibility, and which are Mercurial's. A |
belaran@999 | 9310 <emphasis>test</emphasis> is something that |
belaran@999 | 9311 <emphasis>you</emphasis> run when <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9312 bisect</command> chooses a changeset. A |
belaran@999 | 9313 <emphasis>probe</emphasis> is what <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9314 bisect</command> runs to tell whether a revision is good. |
belaran@999 | 9315 Finally, we'll use the word <quote>bisect</quote>, as both a |
belaran@999 | 9316 noun and a verb, to stand in for the phrase <quote>search using |
belaran@999 | 9317 the <command role="hg-cmd" moreinfo="none">hg bisect</command> |
belaran@999 | 9318 command</quote>.</para> |
belaran@999 | 9319 |
belaran@999 | 9320 <para id="x_12f">One simple way to automate the searching process would be |
belaran@999 | 9321 simply to probe every changeset. However, this scales poorly. |
belaran@999 | 9322 If it took ten minutes to test a single changeset, and you had |
belaran@999 | 9323 10,000 changesets in your repository, the exhaustive approach |
belaran@999 | 9324 would take on average 35 <emphasis>days</emphasis> to find the |
belaran@999 | 9325 changeset that introduced a bug. Even if you knew that the bug |
belaran@999 | 9326 was introduced by one of the last 500 changesets, and limited |
belaran@999 | 9327 your search to those, you'd still be looking at over 40 hours to |
belaran@999 | 9328 find the changeset that introduced your bug.</para> |
belaran@999 | 9329 |
belaran@999 | 9330 <para id="x_130">What the <command role="hg-cmd" moreinfo="none">hg bisect</command> command |
belaran@999 | 9331 does is use its knowledge of the <quote>shape</quote> of your |
belaran@999 | 9332 project's revision history to perform a search in time |
belaran@999 | 9333 proportional to the <emphasis>logarithm</emphasis> of the number |
belaran@999 | 9334 of changesets to check (the kind of search it performs is called |
belaran@999 | 9335 a dichotomic search). With this approach, searching through |
belaran@999 | 9336 10,000 changesets will take less than three hours, even at ten |
belaran@999 | 9337 minutes per test (the search will require about 14 tests). |
belaran@999 | 9338 Limit your search to the last hundred changesets, and it will |
belaran@999 | 9339 take only about an hour (roughly seven tests).</para> |
belaran@999 | 9340 |
belaran@999 | 9341 <para id="x_131">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command is |
belaran@999 | 9342 aware of the <quote>branchy</quote> nature of a Mercurial |
belaran@999 | 9343 project's revision history, so it has no problems dealing with |
belaran@999 | 9344 branches, merges, or multiple heads in a repository. It can |
belaran@999 | 9345 prune entire branches of history with a single probe, which is |
belaran@999 | 9346 how it operates so efficiently.</para> |
belaran@999 | 9347 |
belaran@999 | 9348 <sect2> |
belaran@999 | 9349 <title>Using the <command role="hg-cmd" moreinfo="none">hg bisect</command> |
belaran@999 | 9350 command</title> |
belaran@999 | 9351 |
belaran@999 | 9352 <para id="x_132">Here's an example of <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9353 bisect</command> in action.</para> |
belaran@999 | 9354 |
belaran@999 | 9355 <note> |
belaran@999 | 9356 <para id="x_133"> In versions 0.9.5 and earlier of Mercurial, <command role="hg-cmd" moreinfo="none">hg bisect</command> was not a core command: |
belaran@999 | 9357 it was distributed with Mercurial as an extension. This |
belaran@999 | 9358 section describes the built-in command, not the old |
belaran@999 | 9359 extension.</para> |
belaran@999 | 9360 </note> |
belaran@999 | 9361 |
belaran@999 | 9362 <para id="x_134">Now let's create a repository, so that we can try out the |
belaran@999 | 9363 <command role="hg-cmd" moreinfo="none">hg bisect</command> command in |
belaran@999 | 9364 isolation.</para> |
belaran@999 | 9365 |
belaran@999 | 9366 <!-- BEGIN bisect.init --> |
belaran@999 | 9367 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mybug</userinput> |
belaran@999 | 9368 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mybug</userinput> |
belaran@999 | 9369 </screen> |
belaran@999 | 9370 <!-- END bisect.init --> |
belaran@999 | 9371 |
belaran@999 | 9372 |
belaran@999 | 9373 <para id="x_135">We'll simulate a project that has a bug in it in a |
belaran@999 | 9374 simple-minded way: create trivial changes in a loop, and |
belaran@999 | 9375 nominate one specific change that will have the |
belaran@999 | 9376 <quote>bug</quote>. This loop creates 35 changesets, each |
belaran@999 | 9377 adding a single file to the repository. We'll represent our |
belaran@999 | 9378 <quote>bug</quote> with a file that contains the text <quote>i |
belaran@999 | 9379 have a gub</quote>.</para> |
belaran@999 | 9380 |
belaran@999 | 9381 <!-- BEGIN bisect.commits --> |
belaran@999 | 9382 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">buggy_change=22</userinput> |
belaran@999 | 9383 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">for (( i = 0; i < 35; i++ )); do</userinput> |
belaran@999 | 9384 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> if [[ $i = $buggy_change ]]; then</userinput> |
belaran@999 | 9385 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo 'i have a gub' > myfile$i</userinput> |
belaran@999 | 9386 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg commit -q -A -m 'buggy changeset'</userinput> |
belaran@999 | 9387 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> else</userinput> |
belaran@999 | 9388 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo 'nothing to see here, move along' > myfile$i</userinput> |
belaran@999 | 9389 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg commit -q -A -m 'normal changeset'</userinput> |
belaran@999 | 9390 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> fi</userinput> |
belaran@999 | 9391 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">done</userinput> |
belaran@999 | 9392 </screen> |
belaran@999 | 9393 <!-- END bisect.commits --> |
belaran@999 | 9394 |
belaran@999 | 9395 |
belaran@999 | 9396 <para id="x_136">The next thing that we'd like to do is figure out how to |
belaran@999 | 9397 use the <command role="hg-cmd" moreinfo="none">hg bisect</command> command. |
belaran@999 | 9398 We can use Mercurial's normal built-in help mechanism for |
belaran@999 | 9399 this.</para> |
belaran@999 | 9400 |
belaran@999 | 9401 <!-- BEGIN bisect.help --> |
belaran@999 | 9402 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help bisect</userinput> |
belaran@999 | 9403 hg bisect [-gbsr] [-c CMD] [REV] |
belaran@999 | 9404 |
belaran@999 | 9405 subdivision search of changesets |
belaran@999 | 9406 |
belaran@999 | 9407 This command helps to find changesets which introduce problems. |
belaran@999 | 9408 To use, mark the earliest changeset you know exhibits the problem |
belaran@999 | 9409 as bad, then mark the latest changeset which is free from the |
belaran@999 | 9410 problem as good. Bisect will update your working directory to a |
belaran@999 | 9411 revision for testing (unless the --noupdate option is specified). |
belaran@999 | 9412 Once you have performed tests, mark the working directory as bad |
belaran@999 | 9413 or good and bisect will either update to another candidate changeset |
belaran@999 | 9414 or announce that it has found the bad revision. |
belaran@999 | 9415 |
belaran@999 | 9416 As a shortcut, you can also use the revision argument to mark a |
belaran@999 | 9417 revision as good or bad without checking it out first. |
belaran@999 | 9418 |
belaran@999 | 9419 If you supply a command it will be used for automatic bisection. Its exit |
belaran@999 | 9420 status will be used as flag to mark revision as bad or good. In case exit |
belaran@999 | 9421 status is 0 the revision is marked as good, 125 - skipped, 127 (command not |
belaran@999 | 9422 found) - bisection will be aborted; any other status bigger than 0 will |
belaran@999 | 9423 mark revision as bad. |
belaran@999 | 9424 |
belaran@999 | 9425 options: |
belaran@999 | 9426 |
belaran@999 | 9427 -r --reset reset bisect state |
belaran@999 | 9428 -g --good mark changeset good |
belaran@999 | 9429 -b --bad mark changeset bad |
belaran@999 | 9430 -s --skip skip testing changeset |
belaran@999 | 9431 -c --command use command to check changeset state |
belaran@999 | 9432 -U --noupdate do not update to target |
belaran@999 | 9433 |
belaran@999 | 9434 use "hg -v help bisect" to show global options |
belaran@999 | 9435 </screen> |
belaran@999 | 9436 <!-- END bisect.help --> |
belaran@999 | 9437 |
belaran@999 | 9438 |
belaran@999 | 9439 <para id="x_137">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command |
belaran@999 | 9440 works in steps. Each step proceeds as follows.</para> |
belaran@999 | 9441 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 9442 <listitem><para id="x_138">You run your binary test.</para> |
belaran@999 | 9443 <itemizedlist> |
belaran@999 | 9444 <listitem><para id="x_139">If the test succeeded, you tell <command role="hg-cmd" moreinfo="none">hg bisect</command> by running the |
belaran@999 | 9445 <command role="hg-cmd" moreinfo="none">hg bisect --good</command> |
belaran@999 | 9446 command.</para> |
belaran@999 | 9447 </listitem> |
belaran@999 | 9448 <listitem><para id="x_13a">If it failed, run the <command role="hg-cmd" moreinfo="none">hg bisect --bad</command> |
belaran@999 | 9449 command.</para></listitem></itemizedlist> |
belaran@999 | 9450 </listitem> |
belaran@999 | 9451 <listitem><para id="x_13b">The command uses your information to decide |
belaran@999 | 9452 which changeset to test next.</para> |
belaran@999 | 9453 </listitem> |
belaran@999 | 9454 <listitem><para id="x_13c">It updates the working directory to that |
belaran@999 | 9455 changeset, and the process begins again.</para> |
belaran@999 | 9456 </listitem></orderedlist> |
belaran@999 | 9457 <para id="x_13d">The process ends when <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9458 bisect</command> identifies a unique changeset that marks |
belaran@999 | 9459 the point where your test transitioned from |
belaran@999 | 9460 <quote>succeeding</quote> to <quote>failing</quote>.</para> |
belaran@999 | 9461 |
belaran@999 | 9462 <para id="x_13e">To start the search, we must run the <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command.</para> |
belaran@999 | 9463 |
belaran@999 | 9464 <!-- BEGIN bisect.search.init --> |
belaran@999 | 9465 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput> |
belaran@999 | 9466 </screen> |
belaran@999 | 9467 <!-- END bisect.search.init --> |
belaran@999 | 9468 |
belaran@999 | 9469 |
belaran@999 | 9470 <para id="x_13f">In our case, the binary test we use is simple: we check to |
belaran@999 | 9471 see if any file in the repository contains the string <quote>i |
belaran@999 | 9472 have a gub</quote>. If it does, this changeset contains the |
belaran@999 | 9473 change that <quote>caused the bug</quote>. By convention, a |
belaran@999 | 9474 changeset that has the property we're searching for is |
belaran@999 | 9475 <quote>bad</quote>, while one that doesn't is |
belaran@999 | 9476 <quote>good</quote>.</para> |
belaran@999 | 9477 |
belaran@999 | 9478 <para id="x_140">Most of the time, the revision to which the working |
belaran@999 | 9479 directory is synced (usually the tip) already exhibits the |
belaran@999 | 9480 problem introduced by the buggy change, so we'll mark it as |
belaran@999 | 9481 <quote>bad</quote>.</para> |
belaran@999 | 9482 |
belaran@999 | 9483 <!-- BEGIN bisect.search.bad-init --> |
belaran@999 | 9484 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --bad</userinput> |
belaran@999 | 9485 </screen> |
belaran@999 | 9486 <!-- END bisect.search.bad-init --> |
belaran@999 | 9487 |
belaran@999 | 9488 |
belaran@999 | 9489 <para id="x_141">Our next task is to nominate a changeset that we know |
belaran@999 | 9490 <emphasis>doesn't</emphasis> have the bug; the <command role="hg-cmd" moreinfo="none">hg bisect</command> command will |
belaran@999 | 9491 <quote>bracket</quote> its search between the first pair of |
belaran@999 | 9492 good and bad changesets. In our case, we know that revision |
belaran@999 | 9493 10 didn't have the bug. (I'll have more words about choosing |
belaran@999 | 9494 the first <quote>good</quote> changeset later.)</para> |
belaran@999 | 9495 |
belaran@999 | 9496 <!-- BEGIN bisect.search.good-init --> |
belaran@999 | 9497 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --good 10</userinput> |
belaran@999 | 9498 Testing changeset 22:69f52b967ab8 (24 changesets remaining, ~4 tests) |
belaran@999 | 9499 0 files updated, 0 files merged, 12 files removed, 0 files unresolved |
belaran@999 | 9500 </screen> |
belaran@999 | 9501 <!-- END bisect.search.good-init --> |
belaran@999 | 9502 |
belaran@999 | 9503 |
belaran@999 | 9504 <para id="x_142">Notice that this command printed some output.</para> |
belaran@999 | 9505 <itemizedlist> |
belaran@999 | 9506 <listitem><para id="x_143">It told us how many changesets it must |
belaran@999 | 9507 consider before it can identify the one that introduced |
belaran@999 | 9508 the bug, and how many tests that will require.</para> |
belaran@999 | 9509 </listitem> |
belaran@999 | 9510 <listitem><para id="x_144">It updated the working directory to the next |
belaran@999 | 9511 changeset to test, and told us which changeset it's |
belaran@999 | 9512 testing.</para> |
belaran@999 | 9513 </listitem></itemizedlist> |
belaran@999 | 9514 |
belaran@999 | 9515 <para id="x_145">We now run our test in the working directory. We use the |
belaran@999 | 9516 <command moreinfo="none">grep</command> command to see if our |
belaran@999 | 9517 <quote>bad</quote> file is present in the working directory. |
belaran@999 | 9518 If it is, this revision is bad; if not, this revision is good. |
belaran@999 | 9519 <!-- BEGIN bisect.search.step1 --> |
belaran@999 | 9520 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">if grep -q 'i have a gub' *</userinput> |
belaran@999 | 9521 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">then</userinput> |
belaran@999 | 9522 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=bad</userinput> |
belaran@999 | 9523 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">else</userinput> |
belaran@999 | 9524 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=good</userinput> |
belaran@999 | 9525 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">fi</userinput> |
belaran@999 | 9526 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo this revision is $result</userinput> |
belaran@999 | 9527 this revision is bad |
belaran@999 | 9528 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --$result</userinput> |
belaran@999 | 9529 Testing changeset 16:f1dd8bc690ae (12 changesets remaining, ~3 tests) |
belaran@999 | 9530 0 files updated, 0 files merged, 6 files removed, 0 files unresolved |
belaran@999 | 9531 </screen> |
belaran@999 | 9532 <!-- END bisect.search.step1 --> |
belaran@999 | 9533 </para> |
belaran@999 | 9534 |
belaran@999 | 9535 <para id="x_146">This test looks like a perfect candidate for automation, |
belaran@999 | 9536 so let's turn it into a shell function.</para> |
belaran@999 | 9537 <!-- BEGIN bisect.search.mytest --> |
belaran@999 | 9538 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest() {</userinput> |
belaran@999 | 9539 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> if grep -q 'i have a gub' *</userinput> |
belaran@999 | 9540 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> then</userinput> |
belaran@999 | 9541 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=bad</userinput> |
belaran@999 | 9542 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> else</userinput> |
belaran@999 | 9543 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> result=good</userinput> |
belaran@999 | 9544 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> fi</userinput> |
belaran@999 | 9545 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> echo this revision is $result</userinput> |
belaran@999 | 9546 <prompt moreinfo="none">></prompt> <userinput moreinfo="none"> hg bisect --$result</userinput> |
belaran@999 | 9547 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">}</userinput> |
belaran@999 | 9548 </screen> |
belaran@999 | 9549 <!-- END bisect.search.mytest --> |
belaran@999 | 9550 |
belaran@999 | 9551 |
belaran@999 | 9552 <para id="x_147">We can now run an entire test step with a single command, |
belaran@999 | 9553 <literal moreinfo="none">mytest</literal>.</para> |
belaran@999 | 9554 |
belaran@999 | 9555 <!-- BEGIN bisect.search.step2 --> |
belaran@999 | 9556 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> |
belaran@999 | 9557 this revision is good |
belaran@999 | 9558 Testing changeset 19:88d99d97058a (6 changesets remaining, ~2 tests) |
belaran@999 | 9559 3 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 9560 </screen> |
belaran@999 | 9561 <!-- END bisect.search.step2 --> |
belaran@999 | 9562 |
belaran@999 | 9563 |
belaran@999 | 9564 <para id="x_148">A few more invocations of our canned test step command, |
belaran@999 | 9565 and we're done.</para> |
belaran@999 | 9566 |
belaran@999 | 9567 <!-- BEGIN bisect.search.rest --> |
belaran@999 | 9568 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> |
belaran@999 | 9569 this revision is good |
belaran@999 | 9570 Testing changeset 20:32a195a31d51 (3 changesets remaining, ~1 tests) |
belaran@999 | 9571 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 9572 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> |
belaran@999 | 9573 this revision is good |
belaran@999 | 9574 Testing changeset 21:a2efe8e4f624 (2 changesets remaining, ~1 tests) |
belaran@999 | 9575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 9576 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">mytest</userinput> |
belaran@999 | 9577 this revision is good |
belaran@999 | 9578 The first bad revision is: |
belaran@999 | 9579 changeset: 22:69f52b967ab8 |
belaran@999 | 9580 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 9581 date: Sun Aug 16 14:04:39 2009 +0000 |
belaran@999 | 9582 summary: buggy changeset |
belaran@999 | 9583 |
belaran@999 | 9584 </screen> |
belaran@999 | 9585 <!-- END bisect.search.rest --> |
belaran@999 | 9586 |
belaran@999 | 9587 |
belaran@999 | 9588 <para id="x_149">Even though we had 40 changesets to search through, the |
belaran@999 | 9589 <command role="hg-cmd" moreinfo="none">hg bisect</command> command let us find |
belaran@999 | 9590 the changeset that introduced our <quote>bug</quote> with only |
belaran@999 | 9591 five tests. Because the number of tests that the <command role="hg-cmd" moreinfo="none">hg bisect</command> command performs grows |
belaran@999 | 9592 logarithmically with the number of changesets to search, the |
belaran@999 | 9593 advantage that it has over the <quote>brute force</quote> |
belaran@999 | 9594 search approach increases with every changeset you add.</para> |
belaran@999 | 9595 |
belaran@999 | 9596 </sect2> |
belaran@999 | 9597 <sect2> |
belaran@999 | 9598 <title>Cleaning up after your search</title> |
belaran@999 | 9599 |
belaran@999 | 9600 <para id="x_14a">When you're finished using the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9601 bisect</command> command in a repository, you can use the |
belaran@999 | 9602 <command role="hg-cmd" moreinfo="none">hg bisect --reset</command> command to |
belaran@999 | 9603 drop the information it was using to drive your search. The |
belaran@999 | 9604 command doesn't use much space, so it doesn't matter if you |
belaran@999 | 9605 forget to run this command. However, <command role="hg-cmd" moreinfo="none">hg bisect</command> won't let you start a new |
belaran@999 | 9606 search in that repository until you do a <command role="hg-cmd" moreinfo="none">hg bisect --reset</command>.</para> |
belaran@999 | 9607 |
belaran@999 | 9608 <!-- BEGIN bisect.search.reset --> |
belaran@999 | 9609 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg bisect --reset</userinput> |
belaran@999 | 9610 </screen> |
belaran@999 | 9611 <!-- END bisect.search.reset --> |
belaran@999 | 9612 |
belaran@999 | 9613 |
belaran@999 | 9614 </sect2> |
belaran@999 | 9615 </sect1> |
belaran@999 | 9616 <sect1> |
belaran@999 | 9617 <title>Tips for finding bugs effectively</title> |
belaran@999 | 9618 |
belaran@999 | 9619 <sect2> |
belaran@999 | 9620 <title>Give consistent input</title> |
belaran@999 | 9621 |
belaran@999 | 9622 <para id="x_14b">The <command role="hg-cmd" moreinfo="none">hg bisect</command> command |
belaran@999 | 9623 requires that you correctly report the result of every test |
belaran@999 | 9624 you perform. If you tell it that a test failed when it really |
belaran@999 | 9625 succeeded, it <emphasis>might</emphasis> be able to detect the |
belaran@999 | 9626 inconsistency. If it can identify an inconsistency in your |
belaran@999 | 9627 reports, it will tell you that a particular changeset is both |
belaran@999 | 9628 good and bad. However, it can't do this perfectly; it's about |
belaran@999 | 9629 as likely to report the wrong changeset as the source of the |
belaran@999 | 9630 bug.</para> |
belaran@999 | 9631 |
belaran@999 | 9632 </sect2> |
belaran@999 | 9633 <sect2> |
belaran@999 | 9634 <title>Automate as much as possible</title> |
belaran@999 | 9635 |
belaran@999 | 9636 <para id="x_14c">When I started using the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9637 bisect</command> command, I tried a few times to run my |
belaran@999 | 9638 tests by hand, on the command line. This is an approach that |
belaran@999 | 9639 I, at least, am not suited to. After a few tries, I found |
belaran@999 | 9640 that I was making enough mistakes that I was having to restart |
belaran@999 | 9641 my searches several times before finally getting correct |
belaran@999 | 9642 results.</para> |
belaran@999 | 9643 |
belaran@999 | 9644 <para id="x_14d">My initial problems with driving the <command role="hg-cmd" moreinfo="none">hg bisect</command> command by hand occurred |
belaran@999 | 9645 even with simple searches on small repositories; if the |
belaran@999 | 9646 problem you're looking for is more subtle, or the number of |
belaran@999 | 9647 tests that <command role="hg-cmd" moreinfo="none">hg bisect</command> must |
belaran@999 | 9648 perform increases, the likelihood of operator error ruining |
belaran@999 | 9649 the search is much higher. Once I started automating my |
belaran@999 | 9650 tests, I had much better results.</para> |
belaran@999 | 9651 |
belaran@999 | 9652 <para id="x_14e">The key to automated testing is twofold:</para> |
belaran@999 | 9653 <itemizedlist> |
belaran@999 | 9654 <listitem><para id="x_14f">always test for the same symptom, and</para> |
belaran@999 | 9655 </listitem> |
belaran@999 | 9656 <listitem><para id="x_150">always feed consistent input to the <command role="hg-cmd" moreinfo="none">hg bisect</command> command.</para> |
belaran@999 | 9657 </listitem></itemizedlist> |
belaran@999 | 9658 <para id="x_151">In my tutorial example above, the <command moreinfo="none">grep</command> |
belaran@999 | 9659 command tests for the symptom, and the <literal moreinfo="none">if</literal> |
belaran@999 | 9660 statement takes the result of this check and ensures that we |
belaran@999 | 9661 always feed the same input to the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9662 bisect</command> command. The <literal moreinfo="none">mytest</literal> |
belaran@999 | 9663 function marries these together in a reproducible way, so that |
belaran@999 | 9664 every test is uniform and consistent.</para> |
belaran@999 | 9665 |
belaran@999 | 9666 </sect2> |
belaran@999 | 9667 <sect2> |
belaran@999 | 9668 <title>Check your results</title> |
belaran@999 | 9669 |
belaran@999 | 9670 <para id="x_152">Because the output of a <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9671 bisect</command> search is only as good as the input you |
belaran@999 | 9672 give it, don't take the changeset it reports as the absolute |
belaran@999 | 9673 truth. A simple way to cross-check its report is to manually |
belaran@999 | 9674 run your test at each of the following changesets:</para> |
belaran@999 | 9675 <itemizedlist> |
belaran@999 | 9676 <listitem><para id="x_153">The changeset that it reports as the first bad |
belaran@999 | 9677 revision. Your test should still report this as |
belaran@999 | 9678 bad.</para> |
belaran@999 | 9679 </listitem> |
belaran@999 | 9680 <listitem><para id="x_154">The parent of that changeset (either parent, |
belaran@999 | 9681 if it's a merge). Your test should report this changeset |
belaran@999 | 9682 as good.</para> |
belaran@999 | 9683 </listitem> |
belaran@999 | 9684 <listitem><para id="x_155">A child of that changeset. Your test should |
belaran@999 | 9685 report this changeset as bad.</para> |
belaran@999 | 9686 </listitem></itemizedlist> |
belaran@999 | 9687 |
belaran@999 | 9688 </sect2> |
belaran@999 | 9689 <sect2> |
belaran@999 | 9690 <title>Beware interference between bugs</title> |
belaran@999 | 9691 |
belaran@999 | 9692 <para id="x_156">It's possible that your search for one bug could be |
belaran@999 | 9693 disrupted by the presence of another. For example, let's say |
belaran@999 | 9694 your software crashes at revision 100, and worked correctly at |
belaran@999 | 9695 revision 50. Unknown to you, someone else introduced a |
belaran@999 | 9696 different crashing bug at revision 60, and fixed it at |
belaran@999 | 9697 revision 80. This could distort your results in one of |
belaran@999 | 9698 several ways.</para> |
belaran@999 | 9699 |
belaran@999 | 9700 <para id="x_157">It is possible that this other bug completely |
belaran@999 | 9701 <quote>masks</quote> yours, which is to say that it occurs |
belaran@999 | 9702 before your bug has a chance to manifest itself. If you can't |
belaran@999 | 9703 avoid that other bug (for example, it prevents your project |
belaran@999 | 9704 from building), and so can't tell whether your bug is present |
belaran@999 | 9705 in a particular changeset, the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9706 bisect</command> command cannot help you directly. Instead, |
belaran@999 | 9707 you can mark a changeset as untested by running <command role="hg-cmd" moreinfo="none">hg bisect --skip</command>.</para> |
belaran@999 | 9708 |
belaran@999 | 9709 <para id="x_158">A different problem could arise if your test for a bug's |
belaran@999 | 9710 presence is not specific enough. If you check for <quote>my |
belaran@999 | 9711 program crashes</quote>, then both your crashing bug and an |
belaran@999 | 9712 unrelated crashing bug that masks it will look like the same |
belaran@999 | 9713 thing, and mislead <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9714 bisect</command>.</para> |
belaran@999 | 9715 |
belaran@999 | 9716 <para id="x_159">Another useful situation in which to use <command role="hg-cmd" moreinfo="none">hg bisect --skip</command> is if you can't |
belaran@999 | 9717 test a revision because your project was in a broken and hence |
belaran@999 | 9718 untestable state at that revision, perhaps because someone |
belaran@999 | 9719 checked in a change that prevented the project from |
belaran@999 | 9720 building.</para> |
belaran@999 | 9721 |
belaran@999 | 9722 </sect2> |
belaran@999 | 9723 <sect2> |
belaran@999 | 9724 <title>Bracket your search lazily</title> |
belaran@999 | 9725 |
belaran@999 | 9726 <para id="x_15a">Choosing the first <quote>good</quote> and |
belaran@999 | 9727 <quote>bad</quote> changesets that will mark the end points of |
belaran@999 | 9728 your search is often easy, but it bears a little discussion |
belaran@999 | 9729 nevertheless. From the perspective of <command role="hg-cmd" moreinfo="none">hg bisect</command>, the <quote>newest</quote> |
belaran@999 | 9730 changeset is conventionally <quote>bad</quote>, and the older |
belaran@999 | 9731 changeset is <quote>good</quote>.</para> |
belaran@999 | 9732 |
belaran@999 | 9733 <para id="x_15b">If you're having trouble remembering when a suitable |
belaran@999 | 9734 <quote>good</quote> change was, so that you can tell <command role="hg-cmd" moreinfo="none">hg bisect</command>, you could do worse than |
belaran@999 | 9735 testing changesets at random. Just remember to eliminate |
belaran@999 | 9736 contenders that can't possibly exhibit the bug (perhaps |
belaran@999 | 9737 because the feature with the bug isn't present yet) and those |
belaran@999 | 9738 where another problem masks the bug (as I discussed |
belaran@999 | 9739 above).</para> |
belaran@999 | 9740 |
belaran@999 | 9741 <para id="x_15c">Even if you end up <quote>early</quote> by thousands of |
belaran@999 | 9742 changesets or months of history, you will only add a handful |
belaran@999 | 9743 of tests to the total number that <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9744 bisect</command> must perform, thanks to its logarithmic |
belaran@999 | 9745 behavior.</para> |
belaran@999 | 9746 |
belaran@999 | 9747 </sect2> |
belaran@999 | 9748 </sect1> |
belaran@999 | 9749 </chapter> |
belaran@999 | 9750 |
belaran@999 | 9751 <!-- |
belaran@999 | 9752 local variables: |
belaran@999 | 9753 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 9754 end: |
belaran@999 | 9755 --> |
belaran@999 | 9756 |
belaran@999 | 9757 <!-- BEGIN ch10 --> |
belaran@999 | 9758 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 9759 |
belaran@999 | 9760 <chapter id="chap:hook"> |
belaran@999 | 9761 <?dbhtml filename="handling-repository-events-with-hooks.html"?> |
belaran@999 | 9762 <title>Handling repository events with hooks</title> |
belaran@999 | 9763 |
belaran@999 | 9764 <para id="x_1e6">Mercurial offers a powerful mechanism to let you perform |
belaran@999 | 9765 automated actions in response to events that occur in a |
belaran@999 | 9766 repository. In some cases, you can even control Mercurial's |
belaran@999 | 9767 response to those events.</para> |
belaran@999 | 9768 |
belaran@999 | 9769 <para id="x_1e7">The name Mercurial uses for one of these actions is a |
belaran@999 | 9770 <emphasis>hook</emphasis>. Hooks are called |
belaran@999 | 9771 <quote>triggers</quote> in some revision control systems, but the |
belaran@999 | 9772 two names refer to the same idea.</para> |
belaran@999 | 9773 |
belaran@999 | 9774 <sect1> |
belaran@999 | 9775 <title>An overview of hooks in Mercurial</title> |
belaran@999 | 9776 |
belaran@999 | 9777 <para id="x_1e8">Here is a brief list of the hooks that Mercurial |
belaran@999 | 9778 supports. We will revisit each of these hooks in more detail |
belaran@999 | 9779 later, in <xref linkend="sec:hook:ref"/>.</para> |
belaran@999 | 9780 |
belaran@999 | 9781 <para id="x_1f6">Each of the hooks whose description begins with the word |
belaran@999 | 9782 <quote>Controlling</quote> has the ability to determine whether |
belaran@999 | 9783 an activity can proceed. If the hook succeeds, the activity may |
belaran@999 | 9784 proceed; if it fails, the activity is either not permitted or |
belaran@999 | 9785 undone, depending on the hook.</para> |
belaran@999 | 9786 |
belaran@999 | 9787 <itemizedlist> |
belaran@999 | 9788 <listitem><para id="x_1e9"><literal role="hook" moreinfo="none">changegroup</literal>: This |
belaran@999 | 9789 is run after a group of changesets has been brought into the |
belaran@999 | 9790 repository from elsewhere.</para> |
belaran@999 | 9791 </listitem> |
belaran@999 | 9792 <listitem><para id="x_1ea"><literal role="hook" moreinfo="none">commit</literal>: This is |
belaran@999 | 9793 run after a new changeset has been created in the local |
belaran@999 | 9794 repository.</para> |
belaran@999 | 9795 </listitem> |
belaran@999 | 9796 <listitem><para id="x_1eb"><literal role="hook" moreinfo="none">incoming</literal>: This is |
belaran@999 | 9797 run once for each new changeset that is brought into the |
belaran@999 | 9798 repository from elsewhere. Notice the difference from |
belaran@999 | 9799 <literal role="hook" moreinfo="none">changegroup</literal>, which is run |
belaran@999 | 9800 once per <emphasis>group</emphasis> of changesets brought |
belaran@999 | 9801 in.</para> |
belaran@999 | 9802 </listitem> |
belaran@999 | 9803 <listitem><para id="x_1ec"><literal role="hook" moreinfo="none">outgoing</literal>: This is |
belaran@999 | 9804 run after a group of changesets has been transmitted from |
belaran@999 | 9805 this repository.</para> |
belaran@999 | 9806 </listitem> |
belaran@999 | 9807 <listitem><para id="x_1ed"><literal role="hook" moreinfo="none">prechangegroup</literal>: |
belaran@999 | 9808 This is run before starting to bring a group of changesets |
belaran@999 | 9809 into the repository. |
belaran@999 | 9810 </para> |
belaran@999 | 9811 </listitem> |
belaran@999 | 9812 <listitem><para id="x_1ee"><literal role="hook" moreinfo="none">precommit</literal>: |
belaran@999 | 9813 Controlling. This is run before starting a commit. |
belaran@999 | 9814 </para> |
belaran@999 | 9815 </listitem> |
belaran@999 | 9816 <listitem><para id="x_1ef"><literal role="hook" moreinfo="none">preoutgoing</literal>: |
belaran@999 | 9817 Controlling. This is run before starting to transmit a group |
belaran@999 | 9818 of changesets from this repository. |
belaran@999 | 9819 </para> |
belaran@999 | 9820 </listitem> |
belaran@999 | 9821 <listitem><para id="x_1f0"><literal role="hook" moreinfo="none">pretag</literal>: |
belaran@999 | 9822 Controlling. This is run before creating a tag. |
belaran@999 | 9823 </para> |
belaran@999 | 9824 </listitem> |
belaran@999 | 9825 <listitem><para id="x_1f1"><literal role="hook" moreinfo="none">pretxnchangegroup</literal>: Controlling. This |
belaran@999 | 9826 is run after a group of changesets has been brought into the |
belaran@999 | 9827 local repository from another, but before the transaction |
belaran@999 | 9828 completes that will make the changes permanent in the |
belaran@999 | 9829 repository. |
belaran@999 | 9830 </para> |
belaran@999 | 9831 </listitem> |
belaran@999 | 9832 <listitem><para id="x_1f2"><literal role="hook" moreinfo="none">pretxncommit</literal>: |
belaran@999 | 9833 Controlling. This is run after a new changeset has been |
belaran@999 | 9834 created in the local repository, but before the transaction |
belaran@999 | 9835 completes that will make it permanent. |
belaran@999 | 9836 </para> |
belaran@999 | 9837 </listitem> |
belaran@999 | 9838 <listitem><para id="x_1f3"><literal role="hook" moreinfo="none">preupdate</literal>: |
belaran@999 | 9839 Controlling. This is run before starting an update or merge |
belaran@999 | 9840 of the working directory. |
belaran@999 | 9841 </para> |
belaran@999 | 9842 </listitem> |
belaran@999 | 9843 <listitem><para id="x_1f4"><literal role="hook" moreinfo="none">tag</literal>: This is run |
belaran@999 | 9844 after a tag is created. |
belaran@999 | 9845 </para> |
belaran@999 | 9846 </listitem> |
belaran@999 | 9847 <listitem><para id="x_1f5"><literal role="hook" moreinfo="none">update</literal>: This is |
belaran@999 | 9848 run after an update or merge of the working directory has |
belaran@999 | 9849 finished. |
belaran@999 | 9850 </para> |
belaran@999 | 9851 </listitem></itemizedlist> |
belaran@999 | 9852 |
belaran@999 | 9853 </sect1> |
belaran@999 | 9854 <sect1> |
belaran@999 | 9855 <title>Hooks and security</title> |
belaran@999 | 9856 |
belaran@999 | 9857 <sect2> |
belaran@999 | 9858 <title>Hooks are run with your privileges</title> |
belaran@999 | 9859 |
belaran@999 | 9860 <para id="x_1f7">When you run a Mercurial command in a repository, and the |
belaran@999 | 9861 command causes a hook to run, that hook runs on |
belaran@999 | 9862 <emphasis>your</emphasis> system, under |
belaran@999 | 9863 <emphasis>your</emphasis> user account, with |
belaran@999 | 9864 <emphasis>your</emphasis> privilege level. Since hooks are |
belaran@999 | 9865 arbitrary pieces of executable code, you should treat them |
belaran@999 | 9866 with an appropriate level of suspicion. Do not install a hook |
belaran@999 | 9867 unless you are confident that you know who created it and what |
belaran@999 | 9868 it does. |
belaran@999 | 9869 </para> |
belaran@999 | 9870 |
belaran@999 | 9871 <para id="x_1f8">In some cases, you may be exposed to hooks that you did |
belaran@999 | 9872 not install yourself. If you work with Mercurial on an |
belaran@999 | 9873 unfamiliar system, Mercurial will run hooks defined in that |
belaran@999 | 9874 system's global <filename role="special" moreinfo="none">~/.hgrc</filename> |
belaran@999 | 9875 file. |
belaran@999 | 9876 </para> |
belaran@999 | 9877 |
belaran@999 | 9878 <para id="x_1f9">If you are working with a repository owned by another |
belaran@999 | 9879 user, Mercurial can run hooks defined in that user's |
belaran@999 | 9880 repository, but it will still run them as <quote>you</quote>. |
belaran@999 | 9881 For example, if you <command role="hg-cmd" moreinfo="none">hg pull</command> |
belaran@999 | 9882 from that repository, and its <filename role="special" moreinfo="none">.hg/hgrc</filename> defines a local <literal role="hook" moreinfo="none">outgoing</literal> hook, that hook will run |
belaran@999 | 9883 under your user account, even though you don't own that |
belaran@999 | 9884 repository. |
belaran@999 | 9885 </para> |
belaran@999 | 9886 |
belaran@999 | 9887 <note> |
belaran@999 | 9888 <para id="x_1fa"> This only applies if you are pulling from a repository |
belaran@999 | 9889 on a local or network filesystem. If you're pulling over |
belaran@999 | 9890 http or ssh, any <literal role="hook" moreinfo="none">outgoing</literal> |
belaran@999 | 9891 hook will run under whatever account is executing the server |
belaran@999 | 9892 process, on the server. |
belaran@999 | 9893 </para> |
belaran@999 | 9894 </note> |
belaran@999 | 9895 |
belaran@999 | 9896 <para id="x_1fb">To see what hooks are defined in a repository, |
belaran@999 | 9897 use the <command role="hg-cmd" moreinfo="none">hg showconfig hooks</command> |
belaran@999 | 9898 command. If you are working in one repository, but talking to |
belaran@999 | 9899 another that you do not own (e.g. using <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9900 incoming</command>), remember that it is the other |
belaran@999 | 9901 repository's hooks you should be checking, not your own. |
belaran@999 | 9902 </para> |
belaran@999 | 9903 </sect2> |
belaran@999 | 9904 |
belaran@999 | 9905 <sect2> |
belaran@999 | 9906 <title>Hooks do not propagate</title> |
belaran@999 | 9907 |
belaran@999 | 9908 <para id="x_1fc">In Mercurial, hooks are not revision controlled, and do |
belaran@999 | 9909 not propagate when you clone, or pull from, a repository. The |
belaran@999 | 9910 reason for this is simple: a hook is a completely arbitrary |
belaran@999 | 9911 piece of executable code. It runs under your user identity, |
belaran@999 | 9912 with your privilege level, on your machine. |
belaran@999 | 9913 </para> |
belaran@999 | 9914 |
belaran@999 | 9915 <para id="x_1fd">It would be extremely reckless for any distributed |
belaran@999 | 9916 revision control system to implement revision-controlled |
belaran@999 | 9917 hooks, as this would offer an easily exploitable way to |
belaran@999 | 9918 subvert the accounts of users of the revision control system. |
belaran@999 | 9919 </para> |
belaran@999 | 9920 |
belaran@999 | 9921 <para id="x_1fe">Since Mercurial does not propagate hooks, if you are |
belaran@999 | 9922 collaborating with other people on a common project, you |
belaran@999 | 9923 should not assume that they are using the same Mercurial hooks |
belaran@999 | 9924 as you are, or that theirs are correctly configured. You |
belaran@999 | 9925 should document the hooks you expect people to use. |
belaran@999 | 9926 </para> |
belaran@999 | 9927 |
belaran@999 | 9928 <para id="x_1ff">In a corporate intranet, this is somewhat easier to |
belaran@999 | 9929 control, as you can for example provide a |
belaran@999 | 9930 <quote>standard</quote> installation of Mercurial on an NFS |
belaran@999 | 9931 filesystem, and use a site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file to define hooks that all users will |
belaran@999 | 9932 see. However, this too has its limits; see below. |
belaran@999 | 9933 </para> |
belaran@999 | 9934 </sect2> |
belaran@999 | 9935 |
belaran@999 | 9936 <sect2> |
belaran@999 | 9937 <title>Hooks can be overridden</title> |
belaran@999 | 9938 |
belaran@999 | 9939 <para id="x_200">Mercurial allows you to override a hook definition by |
belaran@999 | 9940 redefining the hook. You can disable it by setting its value |
belaran@999 | 9941 to the empty string, or change its behavior as you wish. |
belaran@999 | 9942 </para> |
belaran@999 | 9943 |
belaran@999 | 9944 <para id="x_201">If you deploy a system- or site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> file that defines some |
belaran@999 | 9945 hooks, you should thus understand that your users can disable |
belaran@999 | 9946 or override those hooks. |
belaran@999 | 9947 </para> |
belaran@999 | 9948 </sect2> |
belaran@999 | 9949 |
belaran@999 | 9950 <sect2> |
belaran@999 | 9951 <title>Ensuring that critical hooks are run</title> |
belaran@999 | 9952 |
belaran@999 | 9953 <para id="x_202">Sometimes you may want to enforce a policy that you do not |
belaran@999 | 9954 want others to be able to work around. For example, you may |
belaran@999 | 9955 have a requirement that every changeset must pass a rigorous |
belaran@999 | 9956 set of tests. Defining this requirement via a hook in a |
belaran@999 | 9957 site-wide <filename role="special" moreinfo="none">~/.hgrc</filename> won't |
belaran@999 | 9958 work for remote users on laptops, and of course local users |
belaran@999 | 9959 can subvert it at will by overriding the hook. |
belaran@999 | 9960 </para> |
belaran@999 | 9961 |
belaran@999 | 9962 <para id="x_203">Instead, you can set up your policies for use of Mercurial |
belaran@999 | 9963 so that people are expected to propagate changes through a |
belaran@999 | 9964 well-known <quote>canonical</quote> server that you have |
belaran@999 | 9965 locked down and configured appropriately. |
belaran@999 | 9966 </para> |
belaran@999 | 9967 |
belaran@999 | 9968 <para id="x_204">One way to do this is via a combination of social |
belaran@999 | 9969 engineering and technology. Set up a restricted-access |
belaran@999 | 9970 account; users can push changes over the network to |
belaran@999 | 9971 repositories managed by this account, but they cannot log into |
belaran@999 | 9972 the account and run normal shell commands. In this scenario, |
belaran@999 | 9973 a user can commit a changeset that contains any old garbage |
belaran@999 | 9974 they want. |
belaran@999 | 9975 </para> |
belaran@999 | 9976 |
belaran@999 | 9977 <para id="x_205">When someone pushes a changeset to the server that |
belaran@999 | 9978 everyone pulls from, the server will test the changeset before |
belaran@999 | 9979 it accepts it as permanent, and reject it if it fails to pass |
belaran@999 | 9980 the test suite. If people only pull changes from this |
belaran@999 | 9981 filtering server, it will serve to ensure that all changes |
belaran@999 | 9982 that people pull have been automatically vetted. |
belaran@999 | 9983 </para> |
belaran@999 | 9984 |
belaran@999 | 9985 </sect2> |
belaran@999 | 9986 </sect1> |
belaran@999 | 9987 |
belaran@999 | 9988 <sect1 id="sec:hook:simple"> |
belaran@999 | 9989 <title>A short tutorial on using hooks</title> |
belaran@999 | 9990 |
belaran@999 | 9991 <para id="x_212">It is easy to write a Mercurial hook. Let's start with a |
belaran@999 | 9992 hook that runs when you finish a <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 9993 commit</command>, and simply prints the hash of the changeset |
belaran@999 | 9994 you just created. The hook is called <literal role="hook" moreinfo="none">commit</literal>. |
belaran@999 | 9995 </para> |
belaran@999 | 9996 |
belaran@999 | 9997 <para id="x_213">All hooks follow the pattern in this example.</para> |
belaran@999 | 9998 |
belaran@999 | 9999 <!-- BEGIN hook.simple.init --> |
belaran@999 | 10000 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init hook-test</userinput> |
belaran@999 | 10001 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd hook-test</userinput> |
belaran@999 | 10002 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '[hooks]' >> .hg/hgrc</userinput> |
belaran@999 | 10003 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit = echo committed $HG_NODE' >> .hg/hgrc</userinput> |
belaran@999 | 10004 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> |
belaran@999 | 10005 [hooks] |
belaran@999 | 10006 commit = echo committed $HG_NODE |
belaran@999 | 10007 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 10008 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> |
belaran@999 | 10009 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'testing commit hook'</userinput> |
belaran@999 | 10010 committed 13a334d1e5ca83fea465aa779110eec3c5ddd6b1 |
belaran@999 | 10011 </screen> |
belaran@999 | 10012 <!-- END hook.simple.init --> |
belaran@999 | 10013 |
belaran@999 | 10014 |
belaran@999 | 10015 <para id="x_214">You add an entry to the <literal role="rc-hooks" moreinfo="none">hooks</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>. On the left is the name of |
belaran@999 | 10016 the event to trigger on; on the right is the action to take. As |
belaran@999 | 10017 you can see, you can run an arbitrary shell command in a hook. |
belaran@999 | 10018 Mercurial passes extra information to the hook using environment |
belaran@999 | 10019 variables (look for <envar>HG_NODE</envar> in the example). |
belaran@999 | 10020 </para> |
belaran@999 | 10021 |
belaran@999 | 10022 <sect2> |
belaran@999 | 10023 <title>Performing multiple actions per event</title> |
belaran@999 | 10024 |
belaran@999 | 10025 <para id="x_215">Quite often, you will want to define more than one hook |
belaran@999 | 10026 for a particular kind of event, as shown below.</para> |
belaran@999 | 10027 |
belaran@999 | 10028 <!-- BEGIN hook.simple.ext --> |
belaran@999 | 10029 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'commit.when = echo -n "date of commit: "; date' >> .hg/hgrc</userinput> |
belaran@999 | 10030 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a >> a</userinput> |
belaran@999 | 10031 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i have two hooks'</userinput> |
belaran@999 | 10032 committed 3be6e2778fb853cbc7e5138d0b9c29386504670b |
belaran@999 | 10033 date of commit: Sun Aug 16 14:05:05 GMT 2009 |
belaran@999 | 10034 </screen> |
belaran@999 | 10035 <!-- END hook.simple.ext --> |
belaran@999 | 10036 |
belaran@999 | 10037 |
belaran@999 | 10038 <para id="x_216">Mercurial lets you do this by adding an |
belaran@999 | 10039 <emphasis>extension</emphasis> to the end of a hook's name. |
belaran@999 | 10040 You extend a hook's name by giving the name of the hook, |
belaran@999 | 10041 followed by a full stop (the |
belaran@999 | 10042 <quote><literal moreinfo="none">.</literal></quote> character), followed by |
belaran@999 | 10043 some more text of your choosing. For example, Mercurial will |
belaran@999 | 10044 run both <literal moreinfo="none">commit.foo</literal> and |
belaran@999 | 10045 <literal moreinfo="none">commit.bar</literal> when the |
belaran@999 | 10046 <literal moreinfo="none">commit</literal> event occurs. |
belaran@999 | 10047 </para> |
belaran@999 | 10048 |
belaran@999 | 10049 <para id="x_217">To give a well-defined order of execution when there are |
belaran@999 | 10050 multiple hooks defined for an event, Mercurial sorts hooks by |
belaran@999 | 10051 extension, and executes the hook commands in this sorted |
belaran@999 | 10052 order. In the above example, it will execute |
belaran@999 | 10053 <literal moreinfo="none">commit.bar</literal> before |
belaran@999 | 10054 <literal moreinfo="none">commit.foo</literal>, and <literal moreinfo="none">commit</literal> |
belaran@999 | 10055 before both. |
belaran@999 | 10056 </para> |
belaran@999 | 10057 |
belaran@999 | 10058 <para id="x_218">It is a good idea to use a somewhat descriptive |
belaran@999 | 10059 extension when you define a new hook. This will help you to |
belaran@999 | 10060 remember what the hook was for. If the hook fails, you'll get |
belaran@999 | 10061 an error message that contains the hook name and extension, so |
belaran@999 | 10062 using a descriptive extension could give you an immediate hint |
belaran@999 | 10063 as to why the hook failed (see <xref linkend="sec:hook:perm"/> for an example). |
belaran@999 | 10064 </para> |
belaran@999 | 10065 |
belaran@999 | 10066 </sect2> |
belaran@999 | 10067 <sect2 id="sec:hook:perm"> |
belaran@999 | 10068 <title>Controlling whether an activity can proceed</title> |
belaran@999 | 10069 |
belaran@999 | 10070 <para id="x_219">In our earlier examples, we used the <literal role="hook" moreinfo="none">commit</literal> hook, which is run after a |
belaran@999 | 10071 commit has completed. This is one of several Mercurial hooks |
belaran@999 | 10072 that run after an activity finishes. Such hooks have no way |
belaran@999 | 10073 of influencing the activity itself. |
belaran@999 | 10074 </para> |
belaran@999 | 10075 |
belaran@999 | 10076 <para id="x_21a">Mercurial defines a number of events that occur before an |
belaran@999 | 10077 activity starts; or after it starts, but before it finishes. |
belaran@999 | 10078 Hooks that trigger on these events have the added ability to |
belaran@999 | 10079 choose whether the activity can continue, or will abort. |
belaran@999 | 10080 </para> |
belaran@999 | 10081 |
belaran@999 | 10082 <para id="x_21b">The <literal role="hook" moreinfo="none">pretxncommit</literal> hook runs |
belaran@999 | 10083 after a commit has all but completed. In other words, the |
belaran@999 | 10084 metadata representing the changeset has been written out to |
belaran@999 | 10085 disk, but the transaction has not yet been allowed to |
belaran@999 | 10086 complete. The <literal role="hook" moreinfo="none">pretxncommit</literal> |
belaran@999 | 10087 hook has the ability to decide whether the transaction can |
belaran@999 | 10088 complete, or must be rolled back. |
belaran@999 | 10089 </para> |
belaran@999 | 10090 |
belaran@999 | 10091 <para id="x_21c">If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook |
belaran@999 | 10092 exits with a status code of zero, the transaction is allowed |
belaran@999 | 10093 to complete; the commit finishes; and the <literal role="hook" moreinfo="none">commit</literal> hook is run. If the <literal role="hook" moreinfo="none">pretxncommit</literal> hook exits with a |
belaran@999 | 10094 non-zero status code, the transaction is rolled back; the |
belaran@999 | 10095 metadata representing the changeset is erased; and the |
belaran@999 | 10096 <literal role="hook" moreinfo="none">commit</literal> hook is not run. |
belaran@999 | 10097 </para> |
belaran@999 | 10098 |
belaran@999 | 10099 <!-- BEGIN hook.simple.pretxncommit --> |
belaran@999 | 10100 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat check_bug_id</userinput> |
belaran@999 | 10101 #!/bin/sh |
belaran@999 | 10102 # check that a commit comment mentions a numeric bug id |
belaran@999 | 10103 hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]" |
belaran@999 | 10104 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc</userinput> |
belaran@999 | 10105 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a >> a</userinput> |
belaran@999 | 10106 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i am not mentioning a bug id'</userinput> |
belaran@999 | 10107 transaction abort! |
belaran@999 | 10108 rollback completed |
belaran@999 | 10109 abort: pretxncommit.bug_id_required hook exited with status 1 |
belaran@999 | 10110 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m 'i refer you to bug 666'</userinput> |
belaran@999 | 10111 committed 1a52be73a1ca4fa05e269f99003ed00912e8e836 |
belaran@999 | 10112 date of commit: Sun Aug 16 14:05:05 GMT 2009 |
belaran@999 | 10113 </screen> |
belaran@999 | 10114 <!-- END hook.simple.pretxncommit --> |
belaran@999 | 10115 |
belaran@999 | 10116 |
belaran@999 | 10117 <para id="x_21d">The hook in the example above checks that a commit comment |
belaran@999 | 10118 contains a bug ID. If it does, the commit can complete. If |
belaran@999 | 10119 not, the commit is rolled back. |
belaran@999 | 10120 </para> |
belaran@999 | 10121 |
belaran@999 | 10122 </sect2> |
belaran@999 | 10123 </sect1> |
belaran@999 | 10124 <sect1> |
belaran@999 | 10125 <title>Writing your own hooks</title> |
belaran@999 | 10126 |
belaran@999 | 10127 <para id="x_21e">When you are writing a hook, you might find it useful to run |
belaran@999 | 10128 Mercurial either with the <option role="hg-opt-global">-v</option> option, or the <envar role="rc-item-ui">verbose</envar> config item set to |
belaran@999 | 10129 <quote>true</quote>. When you do so, Mercurial will print a |
belaran@999 | 10130 message before it calls each hook. |
belaran@999 | 10131 </para> |
belaran@999 | 10132 |
belaran@999 | 10133 <sect2 id="sec:hook:lang"> |
belaran@999 | 10134 <title>Choosing how your hook should run</title> |
belaran@999 | 10135 |
belaran@999 | 10136 <para id="x_21f">You can write a hook either as a normal |
belaran@999 | 10137 program—typically a shell script—or as a Python |
belaran@999 | 10138 function that is executed within the Mercurial process. |
belaran@999 | 10139 </para> |
belaran@999 | 10140 |
belaran@999 | 10141 <para id="x_220">Writing a hook as an external program has the advantage |
belaran@999 | 10142 that it requires no knowledge of Mercurial's internals. You |
belaran@999 | 10143 can call normal Mercurial commands to get any added |
belaran@999 | 10144 information you need. The trade-off is that external hooks |
belaran@999 | 10145 are slower than in-process hooks. |
belaran@999 | 10146 </para> |
belaran@999 | 10147 |
belaran@999 | 10148 <para id="x_221">An in-process Python hook has complete access to the |
belaran@999 | 10149 Mercurial API, and does not <quote>shell out</quote> to |
belaran@999 | 10150 another process, so it is inherently faster than an external |
belaran@999 | 10151 hook. It is also easier to obtain much of the information |
belaran@999 | 10152 that a hook requires by using the Mercurial API than by |
belaran@999 | 10153 running Mercurial commands. |
belaran@999 | 10154 </para> |
belaran@999 | 10155 |
belaran@999 | 10156 <para id="x_222">If you are comfortable with Python, or require high |
belaran@999 | 10157 performance, writing your hooks in Python may be a good |
belaran@999 | 10158 choice. However, when you have a straightforward hook to |
belaran@999 | 10159 write and you don't need to care about performance (probably |
belaran@999 | 10160 the majority of hooks), a shell script is perfectly fine. |
belaran@999 | 10161 </para> |
belaran@999 | 10162 |
belaran@999 | 10163 </sect2> |
belaran@999 | 10164 <sect2 id="sec:hook:param"> |
belaran@999 | 10165 <title>Hook parameters</title> |
belaran@999 | 10166 |
belaran@999 | 10167 <para id="x_223">Mercurial calls each hook with a set of well-defined |
belaran@999 | 10168 parameters. In Python, a parameter is passed as a keyword |
belaran@999 | 10169 argument to your hook function. For an external program, a |
belaran@999 | 10170 parameter is passed as an environment variable. |
belaran@999 | 10171 </para> |
belaran@999 | 10172 |
belaran@999 | 10173 <para id="x_224">Whether your hook is written in Python or as a shell |
belaran@999 | 10174 script, the hook-specific parameter names and values will be |
belaran@999 | 10175 the same. A boolean parameter will be represented as a |
belaran@999 | 10176 boolean value in Python, but as the number 1 (for |
belaran@999 | 10177 <quote>true</quote>) or 0 (for <quote>false</quote>) as an |
belaran@999 | 10178 environment variable for an external hook. If a hook |
belaran@999 | 10179 parameter is named <literal moreinfo="none">foo</literal>, the keyword |
belaran@999 | 10180 argument for a Python hook will also be named |
belaran@999 | 10181 <literal moreinfo="none">foo</literal>, while the environment variable for an |
belaran@999 | 10182 external hook will be named <literal moreinfo="none">HG_FOO</literal>. |
belaran@999 | 10183 </para> |
belaran@999 | 10184 </sect2> |
belaran@999 | 10185 |
belaran@999 | 10186 <sect2> |
belaran@999 | 10187 <title>Hook return values and activity control</title> |
belaran@999 | 10188 |
belaran@999 | 10189 <para id="x_225">A hook that executes successfully must exit with a status |
belaran@999 | 10190 of zero if external, or return boolean <quote>false</quote> if |
belaran@999 | 10191 in-process. Failure is indicated with a non-zero exit status |
belaran@999 | 10192 from an external hook, or an in-process hook returning boolean |
belaran@999 | 10193 <quote>true</quote>. If an in-process hook raises an |
belaran@999 | 10194 exception, the hook is considered to have failed. |
belaran@999 | 10195 </para> |
belaran@999 | 10196 |
belaran@999 | 10197 <para id="x_226">For a hook that controls whether an activity can proceed, |
belaran@999 | 10198 zero/false means <quote>allow</quote>, while |
belaran@999 | 10199 non-zero/true/exception means <quote>deny</quote>. |
belaran@999 | 10200 </para> |
belaran@999 | 10201 </sect2> |
belaran@999 | 10202 |
belaran@999 | 10203 <sect2> |
belaran@999 | 10204 <title>Writing an external hook</title> |
belaran@999 | 10205 |
belaran@999 | 10206 <para id="x_227">When you define an external hook in your <filename role="special" moreinfo="none">~/.hgrc</filename> and the hook is run, its |
belaran@999 | 10207 value is passed to your shell, which interprets it. This |
belaran@999 | 10208 means that you can use normal shell constructs in the body of |
belaran@999 | 10209 the hook. |
belaran@999 | 10210 </para> |
belaran@999 | 10211 |
belaran@999 | 10212 <para id="x_228">An executable hook is always run with its current |
belaran@999 | 10213 directory set to a repository's root directory. |
belaran@999 | 10214 </para> |
belaran@999 | 10215 |
belaran@999 | 10216 <para id="x_229">Each hook parameter is passed in as an environment |
belaran@999 | 10217 variable; the name is upper-cased, and prefixed with the |
belaran@999 | 10218 string <quote><literal moreinfo="none">HG_</literal></quote>. |
belaran@999 | 10219 </para> |
belaran@999 | 10220 |
belaran@999 | 10221 <para id="x_22a">With the exception of hook parameters, Mercurial does not |
belaran@999 | 10222 set or modify any environment variables when running a hook. |
belaran@999 | 10223 This is useful to remember if you are writing a site-wide hook |
belaran@999 | 10224 that may be run by a number of different users with differing |
belaran@999 | 10225 environment variables set. In multi-user situations, you |
belaran@999 | 10226 should not rely on environment variables being set to the |
belaran@999 | 10227 values you have in your environment when testing the hook. |
belaran@999 | 10228 </para> |
belaran@999 | 10229 </sect2> |
belaran@999 | 10230 |
belaran@999 | 10231 <sect2> |
belaran@999 | 10232 <title>Telling Mercurial to use an in-process hook</title> |
belaran@999 | 10233 |
belaran@999 | 10234 <para id="x_22b">The <filename role="special" moreinfo="none">~/.hgrc</filename> syntax |
belaran@999 | 10235 for defining an in-process hook is slightly different than for |
belaran@999 | 10236 an executable hook. The value of the hook must start with the |
belaran@999 | 10237 text <quote><literal moreinfo="none">python:</literal></quote>, and continue |
belaran@999 | 10238 with the fully-qualified name of a callable object to use as |
belaran@999 | 10239 the hook's value. |
belaran@999 | 10240 </para> |
belaran@999 | 10241 |
belaran@999 | 10242 <para id="x_22c">The module in which a hook lives is automatically imported |
belaran@999 | 10243 when a hook is run. So long as you have the module name and |
belaran@999 | 10244 <envar>PYTHONPATH</envar> right, it should <quote>just |
belaran@999 | 10245 work</quote>. |
belaran@999 | 10246 </para> |
belaran@999 | 10247 |
belaran@999 | 10248 <para id="x_22d">The following <filename role="special" moreinfo="none">~/.hgrc</filename> |
belaran@999 | 10249 example snippet illustrates the syntax and meaning of the |
belaran@999 | 10250 notions we just described. |
belaran@999 | 10251 </para> |
belaran@999 | 10252 <programlisting format="linespecific">[hooks] |
belaran@999 | 10253 commit.example = python:mymodule.submodule.myhook</programlisting> |
belaran@999 | 10254 <para id="x_22e">When Mercurial runs the <literal moreinfo="none">commit.example</literal> |
belaran@999 | 10255 hook, it imports <literal moreinfo="none">mymodule.submodule</literal>, looks |
belaran@999 | 10256 for the callable object named <literal moreinfo="none">myhook</literal>, and |
belaran@999 | 10257 calls it. |
belaran@999 | 10258 </para> |
belaran@999 | 10259 </sect2> |
belaran@999 | 10260 |
belaran@999 | 10261 <sect2> |
belaran@999 | 10262 <title>Writing an in-process hook</title> |
belaran@999 | 10263 |
belaran@999 | 10264 <para id="x_22f">The simplest in-process hook does nothing, but illustrates |
belaran@999 | 10265 the basic shape of the hook API: |
belaran@999 | 10266 </para> |
belaran@999 | 10267 <programlisting format="linespecific">def myhook(ui, repo, **kwargs): |
belaran@999 | 10268 pass</programlisting> |
belaran@999 | 10269 <para id="x_230">The first argument to a Python hook is always a <literal role="py-mod-mercurial.ui" moreinfo="none">ui</literal> object. The second |
belaran@999 | 10270 is a repository object; at the moment, it is always an |
belaran@999 | 10271 instance of <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal>. |
belaran@999 | 10272 Following these two arguments are other keyword arguments. |
belaran@999 | 10273 Which ones are passed in depends on the hook being called, but |
belaran@999 | 10274 a hook can ignore arguments it doesn't care about by dropping |
belaran@999 | 10275 them into a keyword argument dict, as with |
belaran@999 | 10276 <literal moreinfo="none">**kwargs</literal> above. |
belaran@999 | 10277 </para> |
belaran@999 | 10278 |
belaran@999 | 10279 </sect2> |
belaran@999 | 10280 </sect1> |
belaran@999 | 10281 <sect1> |
belaran@999 | 10282 <title>Some hook examples</title> |
belaran@999 | 10283 |
belaran@999 | 10284 <sect2> |
belaran@999 | 10285 <title>Writing meaningful commit messages</title> |
belaran@999 | 10286 |
belaran@999 | 10287 <para id="x_231">It's hard to imagine a useful commit message being very |
belaran@999 | 10288 short. The simple <literal role="hook" moreinfo="none">pretxncommit</literal> |
belaran@999 | 10289 hook of the example below will prevent you from committing a |
belaran@999 | 10290 changeset with a message that is less than ten bytes long. |
belaran@999 | 10291 </para> |
belaran@999 | 10292 |
belaran@999 | 10293 <!-- BEGIN hook.msglen.go --> |
belaran@999 | 10294 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> |
belaran@999 | 10295 [hooks] |
belaran@999 | 10296 pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10 |
belaran@999 | 10297 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 10298 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> |
belaran@999 | 10299 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'too short'</userinput> |
belaran@999 | 10300 transaction abort! |
belaran@999 | 10301 rollback completed |
belaran@999 | 10302 abort: pretxncommit.msglen hook exited with status 1 |
belaran@999 | 10303 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'long enough'</userinput> |
belaran@999 | 10304 </screen> |
belaran@999 | 10305 <!-- END hook.msglen.go --> |
belaran@999 | 10306 |
belaran@999 | 10307 </sect2> |
belaran@999 | 10308 |
belaran@999 | 10309 <sect2> |
belaran@999 | 10310 <title>Checking for trailing whitespace</title> |
belaran@999 | 10311 |
belaran@999 | 10312 <para id="x_232">An interesting use of a commit-related hook is to help you |
belaran@999 | 10313 to write cleaner code. A simple example of <quote>cleaner |
belaran@999 | 10314 code</quote> is the dictum that a change should not add any |
belaran@999 | 10315 new lines of text that contain <quote>trailing |
belaran@999 | 10316 whitespace</quote>. Trailing whitespace is a series of |
belaran@999 | 10317 space and tab characters at the end of a line of text. In |
belaran@999 | 10318 most cases, trailing whitespace is unnecessary, invisible |
belaran@999 | 10319 noise, but it is occasionally problematic, and people often |
belaran@999 | 10320 prefer to get rid of it. |
belaran@999 | 10321 </para> |
belaran@999 | 10322 |
belaran@999 | 10323 <para id="x_233">You can use either the <literal role="hook" moreinfo="none">precommit</literal> or <literal role="hook" moreinfo="none">pretxncommit</literal> hook to tell whether you |
belaran@999 | 10324 have a trailing whitespace problem. If you use the <literal role="hook" moreinfo="none">precommit</literal> hook, the hook will not know |
belaran@999 | 10325 which files you are committing, so it will have to check every |
belaran@999 | 10326 modified file in the repository for trailing white space. If |
belaran@999 | 10327 you want to commit a change to just the file |
belaran@999 | 10328 <filename moreinfo="none">foo</filename>, but the file |
belaran@999 | 10329 <filename moreinfo="none">bar</filename> contains trailing whitespace, doing a |
belaran@999 | 10330 check in the <literal role="hook" moreinfo="none">precommit</literal> hook |
belaran@999 | 10331 will prevent you from committing <filename moreinfo="none">foo</filename> due |
belaran@999 | 10332 to the problem with <filename moreinfo="none">bar</filename>. This doesn't |
belaran@999 | 10333 seem right. |
belaran@999 | 10334 </para> |
belaran@999 | 10335 |
belaran@999 | 10336 <para id="x_234">Should you choose the <literal role="hook" moreinfo="none">pretxncommit</literal> hook, the check won't |
belaran@999 | 10337 occur until just before the transaction for the commit |
belaran@999 | 10338 completes. This will allow you to check for problems only the |
belaran@999 | 10339 exact files that are being committed. However, if you entered |
belaran@999 | 10340 the commit message interactively and the hook fails, the |
belaran@999 | 10341 transaction will roll back; you'll have to re-enter the commit |
belaran@999 | 10342 message after you fix the trailing whitespace and run <command role="hg-cmd" moreinfo="none">hg commit</command> again. |
belaran@999 | 10343 </para> |
belaran@999 | 10344 |
belaran@999 | 10345 <!-- BEGIN ch09/hook.ws.simple --> |
belaran@999 | 10346 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> |
belaran@999 | 10347 [hooks] |
belaran@999 | 10348 pretxncommit.whitespace = hg export tip | (! egrep -q '^\+.*[ \t]$') |
belaran@999 | 10349 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' > a</userinput> |
belaran@999 | 10350 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'test with trailing whitespace'</userinput> |
belaran@999 | 10351 adding a |
belaran@999 | 10352 transaction abort! |
belaran@999 | 10353 rollback completed |
belaran@999 | 10354 abort: pretxncommit.whitespace hook exited with status 1 |
belaran@999 | 10355 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a' > a</userinput> |
belaran@999 | 10356 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'drop trailing whitespace and try again'</userinput> |
belaran@999 | 10357 </screen> |
belaran@999 | 10358 <!-- END ch09/hook.ws.simple --> |
belaran@999 | 10359 |
belaran@999 | 10360 |
belaran@999 | 10361 <para id="x_235">In this example, we introduce a simple <literal role="hook" moreinfo="none">pretxncommit</literal> hook that checks for |
belaran@999 | 10362 trailing whitespace. This hook is short, but not very |
belaran@999 | 10363 helpful. It exits with an error status if a change adds a |
belaran@999 | 10364 line with trailing whitespace to any file, but does not print |
belaran@999 | 10365 any information that might help us to identify the offending |
belaran@999 | 10366 file or line. It also has the nice property of not paying |
belaran@999 | 10367 attention to unmodified lines; only lines that introduce new |
belaran@999 | 10368 trailing whitespace cause problems. |
belaran@999 | 10369 </para> |
belaran@999 | 10370 |
belaran@999 | 10371 <!-- BEGIN ch09/check_whitespace.py.lst --> |
belaran@999 | 10372 <programlisting format="linespecific">#!/usr/bin/env python |
belaran@999 | 10373 # |
belaran@999 | 10374 # save as .hg/check_whitespace.py and make executable |
belaran@999 | 10375 |
belaran@999 | 10376 import re |
belaran@999 | 10377 |
belaran@999 | 10378 def trailing_whitespace(difflines): |
belaran@999 | 10379 # |
belaran@999 | 10380 linenum, header = 0, False |
belaran@999 | 10381 |
belaran@999 | 10382 for line in difflines: |
belaran@999 | 10383 if header: |
belaran@999 | 10384 # remember the name of the file that this diff affects |
belaran@999 | 10385 m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line) |
belaran@999 | 10386 if m and m.group(1) != '/dev/null': |
belaran@999 | 10387 filename = m.group(1).split('/', 1)[-1] |
belaran@999 | 10388 if line.startswith('+++ '): |
belaran@999 | 10389 header = False |
belaran@999 | 10390 continue |
belaran@999 | 10391 if line.startswith('diff '): |
belaran@999 | 10392 header = True |
belaran@999 | 10393 continue |
belaran@999 | 10394 # hunk header - save the line number |
belaran@999 | 10395 m = re.match(r'@@ -\d+,\d+ \+(\d+),', line) |
belaran@999 | 10396 if m: |
belaran@999 | 10397 linenum = int(m.group(1)) |
belaran@999 | 10398 continue |
belaran@999 | 10399 # hunk body - check for an added line with trailing whitespace |
belaran@999 | 10400 m = re.match(r'\+.*\s$', line) |
belaran@999 | 10401 if m: |
belaran@999 | 10402 yield filename, linenum |
belaran@999 | 10403 if line and line[0] in ' +': |
belaran@999 | 10404 linenum += 1 |
belaran@999 | 10405 |
belaran@999 | 10406 if __name__ == '__main__': |
belaran@999 | 10407 import os, sys |
belaran@999 | 10408 |
belaran@999 | 10409 added = 0 |
belaran@999 | 10410 for filename, linenum in trailing_whitespace(os.popen('hg export tip')): |
belaran@999 | 10411 print >> sys.stderr, ('%s, line %d: trailing whitespace added' % |
belaran@999 | 10412 (filename, linenum)) |
belaran@999 | 10413 added += 1 |
belaran@999 | 10414 if added: |
belaran@999 | 10415 # save the commit message so we don't need to retype it |
belaran@999 | 10416 os.system('hg tip --template "{desc}" > .hg/commit.save') |
belaran@999 | 10417 print >> sys.stderr, 'commit message saved to .hg/commit.save' |
belaran@999 | 10418 sys.exit(1)</programlisting> |
belaran@999 | 10419 <!-- END ch09/check_whitespace.py.lst --> |
belaran@999 | 10420 |
belaran@999 | 10421 |
belaran@999 | 10422 <para id="x_236">The above version is much more complex, but also more |
belaran@999 | 10423 useful. It parses a unified diff to see if any lines add |
belaran@999 | 10424 trailing whitespace, and prints the name of the file and the |
belaran@999 | 10425 line number of each such occurrence. Even better, if the |
belaran@999 | 10426 change adds trailing whitespace, this hook saves the commit |
belaran@999 | 10427 comment and prints the name of the save file before exiting |
belaran@999 | 10428 and telling Mercurial to roll the transaction back, so you can |
belaran@999 | 10429 use the <option role="hg-opt-commit">-l filename</option> |
belaran@999 | 10430 option to <command role="hg-cmd" moreinfo="none">hg commit</command> to reuse |
belaran@999 | 10431 the saved commit message once you've corrected the problem. |
belaran@999 | 10432 </para> |
belaran@999 | 10433 |
belaran@999 | 10434 <!-- BEGIN ch09/hook.ws.better --> |
belaran@999 | 10435 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/hgrc</userinput> |
belaran@999 | 10436 [hooks] |
belaran@999 | 10437 pretxncommit.whitespace = .hg/check_whitespace.py |
belaran@999 | 10438 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'a ' >> a</userinput> |
belaran@999 | 10439 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'add new line with trailing whitespace'</userinput> |
belaran@999 | 10440 a, line 2: trailing whitespace added |
belaran@999 | 10441 commit message saved to .hg/commit.save |
belaran@999 | 10442 transaction abort! |
belaran@999 | 10443 rollback completed |
belaran@999 | 10444 abort: pretxncommit.whitespace hook exited with status 1 |
belaran@999 | 10445 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">sed -i 's, *$,,' a</userinput> |
belaran@999 | 10446 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -A -m 'trimmed trailing whitespace'</userinput> |
belaran@999 | 10447 a, line 2: trailing whitespace added |
belaran@999 | 10448 commit message saved to .hg/commit.save |
belaran@999 | 10449 transaction abort! |
belaran@999 | 10450 rollback completed |
belaran@999 | 10451 abort: pretxncommit.whitespace hook exited with status 1 |
belaran@999 | 10452 </screen> |
belaran@999 | 10453 <!-- END ch09/hook.ws.better --> |
belaran@999 | 10454 |
belaran@999 | 10455 |
belaran@999 | 10456 <para id="x_237">As a final aside, note in the example above the |
belaran@999 | 10457 use of <command moreinfo="none">sed</command>'s in-place editing feature to |
belaran@999 | 10458 get rid of trailing whitespace from a file. This is concise |
belaran@999 | 10459 and useful enough that I will reproduce it here (using |
belaran@999 | 10460 <command moreinfo="none">perl</command> for good measure).</para> |
belaran@999 | 10461 <programlisting format="linespecific">perl -pi -e 's,\s+$,,' filename</programlisting> |
belaran@999 | 10462 |
belaran@999 | 10463 </sect2> |
belaran@999 | 10464 </sect1> |
belaran@999 | 10465 <sect1> |
belaran@999 | 10466 <title>Bundled hooks</title> |
belaran@999 | 10467 |
belaran@999 | 10468 <para id="x_238">Mercurial ships with several bundled hooks. You can find |
belaran@999 | 10469 them in the <filename class="directory" moreinfo="none">hgext</filename> |
belaran@999 | 10470 directory of a Mercurial source tree. If you are using a |
belaran@999 | 10471 Mercurial binary package, the hooks will be located in the |
belaran@999 | 10472 <filename class="directory" moreinfo="none">hgext</filename> directory of |
belaran@999 | 10473 wherever your package installer put Mercurial. |
belaran@999 | 10474 </para> |
belaran@999 | 10475 |
belaran@999 | 10476 <sect2> |
belaran@999 | 10477 <title><literal role="hg-ext" moreinfo="none">acl</literal>—access |
belaran@999 | 10478 control for parts of a repository</title> |
belaran@999 | 10479 |
belaran@999 | 10480 <para id="x_239">The <literal role="hg-ext" moreinfo="none">acl</literal> extension lets |
belaran@999 | 10481 you control which remote users are allowed to push changesets |
belaran@999 | 10482 to a networked server. You can protect any portion of a |
belaran@999 | 10483 repository (including the entire repo), so that a specific |
belaran@999 | 10484 remote user can push changes that do not affect the protected |
belaran@999 | 10485 portion. |
belaran@999 | 10486 </para> |
belaran@999 | 10487 |
belaran@999 | 10488 <para id="x_23a">This extension implements access control based on the |
belaran@999 | 10489 identity of the user performing a push, |
belaran@999 | 10490 <emphasis>not</emphasis> on who committed the changesets |
belaran@999 | 10491 they're pushing. It makes sense to use this hook only if you |
belaran@999 | 10492 have a locked-down server environment that authenticates |
belaran@999 | 10493 remote users, and you want to be sure that only specific users |
belaran@999 | 10494 are allowed to push changes to that server. |
belaran@999 | 10495 </para> |
belaran@999 | 10496 |
belaran@999 | 10497 <sect3> |
belaran@999 | 10498 <title>Configuring the <literal role="hook" moreinfo="none">acl</literal> |
belaran@999 | 10499 hook</title> |
belaran@999 | 10500 |
belaran@999 | 10501 <para id="x_23b">In order to manage incoming changesets, the <literal role="hg-ext" moreinfo="none">acl</literal> hook must be used as a |
belaran@999 | 10502 <literal role="hook" moreinfo="none">pretxnchangegroup</literal> hook. This |
belaran@999 | 10503 lets it see which files are modified by each incoming |
belaran@999 | 10504 changeset, and roll back a group of changesets if they |
belaran@999 | 10505 modify <quote>forbidden</quote> files. Example: |
belaran@999 | 10506 </para> |
belaran@999 | 10507 <programlisting format="linespecific">[hooks] |
belaran@999 | 10508 pretxnchangegroup.acl = python:hgext.acl.hook</programlisting> |
belaran@999 | 10509 |
belaran@999 | 10510 <para id="x_23c">The <literal role="hg-ext" moreinfo="none">acl</literal> extension is |
belaran@999 | 10511 configured using three sections. |
belaran@999 | 10512 </para> |
belaran@999 | 10513 |
belaran@999 | 10514 <para id="x_23d">The <literal role="rc-acl" moreinfo="none">acl</literal> section has |
belaran@999 | 10515 only one entry, <envar role="rc-item-acl">sources</envar>, |
belaran@999 | 10516 which lists the sources of incoming changesets that the hook |
belaran@999 | 10517 should pay attention to. You don't normally need to |
belaran@999 | 10518 configure this section. |
belaran@999 | 10519 </para> |
belaran@999 | 10520 <itemizedlist> |
belaran@999 | 10521 <listitem><para id="x_23e"><envar role="rc-item-acl">serve</envar>: |
belaran@999 | 10522 Control incoming changesets that are arriving from a |
belaran@999 | 10523 remote repository over http or ssh. This is the default |
belaran@999 | 10524 value of <envar role="rc-item-acl">sources</envar>, and |
belaran@999 | 10525 usually the only setting you'll need for this |
belaran@999 | 10526 configuration item. |
belaran@999 | 10527 </para> |
belaran@999 | 10528 </listitem> |
belaran@999 | 10529 <listitem><para id="x_23f"><envar role="rc-item-acl">pull</envar>: |
belaran@999 | 10530 Control incoming changesets that are arriving via a pull |
belaran@999 | 10531 from a local repository. |
belaran@999 | 10532 </para> |
belaran@999 | 10533 </listitem> |
belaran@999 | 10534 <listitem><para id="x_240"><envar role="rc-item-acl">push</envar>: |
belaran@999 | 10535 Control incoming changesets that are arriving via a push |
belaran@999 | 10536 from a local repository. |
belaran@999 | 10537 </para> |
belaran@999 | 10538 </listitem> |
belaran@999 | 10539 <listitem><para id="x_241"><envar role="rc-item-acl">bundle</envar>: |
belaran@999 | 10540 Control incoming changesets that are arriving from |
belaran@999 | 10541 another repository via a bundle. |
belaran@999 | 10542 </para> |
belaran@999 | 10543 </listitem></itemizedlist> |
belaran@999 | 10544 |
belaran@999 | 10545 <para id="x_242">The <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal> |
belaran@999 | 10546 section controls the users that are allowed to add |
belaran@999 | 10547 changesets to the repository. If this section is not |
belaran@999 | 10548 present, all users that are not explicitly denied are |
belaran@999 | 10549 allowed. If this section is present, all users that are not |
belaran@999 | 10550 explicitly allowed are denied (so an empty section means |
belaran@999 | 10551 that all users are denied). |
belaran@999 | 10552 </para> |
belaran@999 | 10553 |
belaran@999 | 10554 <para id="x_243">The <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal> |
belaran@999 | 10555 section determines which users are denied from adding |
belaran@999 | 10556 changesets to the repository. If this section is not |
belaran@999 | 10557 present or is empty, no users are denied. |
belaran@999 | 10558 </para> |
belaran@999 | 10559 |
belaran@999 | 10560 <para id="x_244">The syntaxes for the <literal role="rc-acl.allow" moreinfo="none">acl.allow</literal> and <literal role="rc-acl.deny" moreinfo="none">acl.deny</literal> sections are |
belaran@999 | 10561 identical. On the left of each entry is a glob pattern that |
belaran@999 | 10562 matches files or directories, relative to the root of the |
belaran@999 | 10563 repository; on the right, a user name. |
belaran@999 | 10564 </para> |
belaran@999 | 10565 |
belaran@999 | 10566 <para id="x_245">In the following example, the user |
belaran@999 | 10567 <literal moreinfo="none">docwriter</literal> can only push changes to the |
belaran@999 | 10568 <filename class="directory" moreinfo="none">docs</filename> subtree of the |
belaran@999 | 10569 repository, while <literal moreinfo="none">intern</literal> can push changes |
belaran@999 | 10570 to any file or directory except <filename class="directory" moreinfo="none">source/sensitive</filename>. |
belaran@999 | 10571 </para> |
belaran@999 | 10572 <programlisting format="linespecific">[acl.allow] |
belaran@999 | 10573 docs/** = docwriter |
belaran@999 | 10574 [acl.deny] |
belaran@999 | 10575 source/sensitive/** = intern</programlisting> |
belaran@999 | 10576 |
belaran@999 | 10577 </sect3> |
belaran@999 | 10578 <sect3> |
belaran@999 | 10579 <title>Testing and troubleshooting</title> |
belaran@999 | 10580 |
belaran@999 | 10581 <para id="x_246">If you want to test the <literal role="hg-ext" moreinfo="none">acl</literal> hook, run it with Mercurial's |
belaran@999 | 10582 debugging output enabled. Since you'll probably be running |
belaran@999 | 10583 it on a server where it's not convenient (or sometimes |
belaran@999 | 10584 possible) to pass in the <option role="hg-opt-global">--debug</option> option, don't forget |
belaran@999 | 10585 that you can enable debugging output in your <filename role="special" moreinfo="none">~/.hgrc</filename>: |
belaran@999 | 10586 </para> |
belaran@999 | 10587 <programlisting format="linespecific">[ui] |
belaran@999 | 10588 debug = true</programlisting> |
belaran@999 | 10589 <para id="x_247">With this enabled, the <literal role="hg-ext" moreinfo="none">acl</literal> hook will print enough |
belaran@999 | 10590 information to let you figure out why it is allowing or |
belaran@999 | 10591 forbidding pushes from specific users. |
belaran@999 | 10592 </para> |
belaran@999 | 10593 |
belaran@999 | 10594 </sect3> </sect2> |
belaran@999 | 10595 |
belaran@999 | 10596 <sect2> |
belaran@999 | 10597 <title><literal role="hg-ext" moreinfo="none">bugzilla</literal>—integration with |
belaran@999 | 10598 Bugzilla</title> |
belaran@999 | 10599 |
belaran@999 | 10600 <para id="x_248">The <literal role="hg-ext" moreinfo="none">bugzilla</literal> extension |
belaran@999 | 10601 adds a comment to a Bugzilla bug whenever it finds a reference |
belaran@999 | 10602 to that bug ID in a commit comment. You can install this hook |
belaran@999 | 10603 on a shared server, so that any time a remote user pushes |
belaran@999 | 10604 changes to this server, the hook gets run. |
belaran@999 | 10605 </para> |
belaran@999 | 10606 |
belaran@999 | 10607 <para id="x_249">It adds a comment to the bug that looks like this (you can |
belaran@999 | 10608 configure the contents of the comment—see below): |
belaran@999 | 10609 </para> |
belaran@999 | 10610 <programlisting format="linespecific">Changeset aad8b264143a, made by Joe User |
belaran@999 | 10611 <joe.user@domain.com> in the frobnitz repository, refers |
belaran@999 | 10612 to this bug. For complete details, see |
belaran@999 | 10613 http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a |
belaran@999 | 10614 Changeset description: Fix bug 10483 by guarding against some |
belaran@999 | 10615 NULL pointers</programlisting> |
belaran@999 | 10616 <para id="x_24a">The value of this hook is that it automates the process of |
belaran@999 | 10617 updating a bug any time a changeset refers to it. If you |
belaran@999 | 10618 configure the hook properly, it makes it easy for people to |
belaran@999 | 10619 browse straight from a Bugzilla bug to a changeset that refers |
belaran@999 | 10620 to that bug. |
belaran@999 | 10621 </para> |
belaran@999 | 10622 |
belaran@999 | 10623 <para id="x_24b">You can use the code in this hook as a starting point for |
belaran@999 | 10624 some more exotic Bugzilla integration recipes. Here are a few |
belaran@999 | 10625 possibilities: |
belaran@999 | 10626 </para> |
belaran@999 | 10627 <itemizedlist> |
belaran@999 | 10628 <listitem><para id="x_24c">Require that every changeset pushed to the |
belaran@999 | 10629 server have a valid bug ID in its commit comment. In this |
belaran@999 | 10630 case, you'd want to configure the hook as a <literal role="hook" moreinfo="none">pretxncommit</literal> hook. This would |
belaran@999 | 10631 allow the hook to reject changes that didn't contain bug |
belaran@999 | 10632 IDs. |
belaran@999 | 10633 </para> |
belaran@999 | 10634 </listitem> |
belaran@999 | 10635 <listitem><para id="x_24d">Allow incoming changesets to automatically |
belaran@999 | 10636 modify the <emphasis>state</emphasis> of a bug, as well as |
belaran@999 | 10637 simply adding a comment. For example, the hook could |
belaran@999 | 10638 recognise the string <quote>fixed bug 31337</quote> as |
belaran@999 | 10639 indicating that it should update the state of bug 31337 to |
belaran@999 | 10640 <quote>requires testing</quote>. |
belaran@999 | 10641 </para> |
belaran@999 | 10642 </listitem></itemizedlist> |
belaran@999 | 10643 |
belaran@999 | 10644 <sect3 id="sec:hook:bugzilla:config"> |
belaran@999 | 10645 <title>Configuring the <literal role="hook" moreinfo="none">bugzilla</literal> |
belaran@999 | 10646 hook</title> |
belaran@999 | 10647 |
belaran@999 | 10648 <para id="x_24e">You should configure this hook in your server's |
belaran@999 | 10649 <filename role="special" moreinfo="none">~/.hgrc</filename> as an <literal role="hook" moreinfo="none">incoming</literal> hook, for example as |
belaran@999 | 10650 follows: |
belaran@999 | 10651 </para> |
belaran@999 | 10652 <programlisting format="linespecific">[hooks] |
belaran@999 | 10653 incoming.bugzilla = python:hgext.bugzilla.hook</programlisting> |
belaran@999 | 10654 |
belaran@999 | 10655 <para id="x_24f">Because of the specialised nature of this hook, and |
belaran@999 | 10656 because Bugzilla was not written with this kind of |
belaran@999 | 10657 integration in mind, configuring this hook is a somewhat |
belaran@999 | 10658 involved process. |
belaran@999 | 10659 </para> |
belaran@999 | 10660 |
belaran@999 | 10661 <para id="x_250">Before you begin, you must install the MySQL bindings |
belaran@999 | 10662 for Python on the host(s) where you'll be running the hook. |
belaran@999 | 10663 If this is not available as a binary package for your |
belaran@999 | 10664 system, you can download it from |
belaran@999 | 10665 <citation>web:mysql-python</citation>. |
belaran@999 | 10666 </para> |
belaran@999 | 10667 |
belaran@999 | 10668 <para id="x_251">Configuration information for this hook lives in the |
belaran@999 | 10669 <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal> section of |
belaran@999 | 10670 your <filename role="special" moreinfo="none">~/.hgrc</filename>. |
belaran@999 | 10671 </para> |
belaran@999 | 10672 <itemizedlist> |
belaran@999 | 10673 <listitem><para id="x_252"><envar role="rc-item-bugzilla">version</envar>: The version |
belaran@999 | 10674 of Bugzilla installed on the server. The database |
belaran@999 | 10675 schema that Bugzilla uses changes occasionally, so this |
belaran@999 | 10676 hook has to know exactly which schema to use.</para> |
belaran@999 | 10677 </listitem> |
belaran@999 | 10678 <listitem><para id="x_253"><envar role="rc-item-bugzilla">host</envar>: |
belaran@999 | 10679 The hostname of the MySQL server that stores your |
belaran@999 | 10680 Bugzilla data. The database must be configured to allow |
belaran@999 | 10681 connections from whatever host you are running the |
belaran@999 | 10682 <literal role="hook" moreinfo="none">bugzilla</literal> hook on. |
belaran@999 | 10683 </para> |
belaran@999 | 10684 </listitem> |
belaran@999 | 10685 <listitem><para id="x_254"><envar role="rc-item-bugzilla">user</envar>: |
belaran@999 | 10686 The username with which to connect to the MySQL server. |
belaran@999 | 10687 The database must be configured to allow this user to |
belaran@999 | 10688 connect from whatever host you are running the <literal role="hook" moreinfo="none">bugzilla</literal> hook on. This user |
belaran@999 | 10689 must be able to access and modify Bugzilla tables. The |
belaran@999 | 10690 default value of this item is <literal moreinfo="none">bugs</literal>, |
belaran@999 | 10691 which is the standard name of the Bugzilla user in a |
belaran@999 | 10692 MySQL database. |
belaran@999 | 10693 </para> |
belaran@999 | 10694 </listitem> |
belaran@999 | 10695 <listitem><para id="x_255"><envar role="rc-item-bugzilla">password</envar>: The MySQL |
belaran@999 | 10696 password for the user you configured above. This is |
belaran@999 | 10697 stored as plain text, so you should make sure that |
belaran@999 | 10698 unauthorised users cannot read the <filename role="special" moreinfo="none">~/.hgrc</filename> file where you |
belaran@999 | 10699 store this information. |
belaran@999 | 10700 </para> |
belaran@999 | 10701 </listitem> |
belaran@999 | 10702 <listitem><para id="x_256"><envar role="rc-item-bugzilla">db</envar>: |
belaran@999 | 10703 The name of the Bugzilla database on the MySQL server. |
belaran@999 | 10704 The default value of this item is |
belaran@999 | 10705 <literal moreinfo="none">bugs</literal>, which is the standard name of |
belaran@999 | 10706 the MySQL database where Bugzilla stores its data. |
belaran@999 | 10707 </para> |
belaran@999 | 10708 </listitem> |
belaran@999 | 10709 <listitem><para id="x_257"><envar role="rc-item-bugzilla">notify</envar>: If you want |
belaran@999 | 10710 Bugzilla to send out a notification email to subscribers |
belaran@999 | 10711 after this hook has added a comment to a bug, you will |
belaran@999 | 10712 need this hook to run a command whenever it updates the |
belaran@999 | 10713 database. The command to run depends on where you have |
belaran@999 | 10714 installed Bugzilla, but it will typically look something |
belaran@999 | 10715 like this, if you have Bugzilla installed in <filename class="directory" moreinfo="none">/var/www/html/bugzilla</filename>: |
belaran@999 | 10716 </para> |
belaran@999 | 10717 <programlisting format="linespecific">cd /var/www/html/bugzilla && |
belaran@999 | 10718 ./processmail %s nobody@nowhere.com</programlisting> |
belaran@999 | 10719 </listitem> |
belaran@999 | 10720 <listitem><para id="x_258"> The Bugzilla |
belaran@999 | 10721 <literal moreinfo="none">processmail</literal> program expects to be |
belaran@999 | 10722 given a bug ID (the hook replaces |
belaran@999 | 10723 <quote><literal moreinfo="none">%s</literal></quote> with the bug ID) |
belaran@999 | 10724 and an email address. It also expects to be able to |
belaran@999 | 10725 write to some files in the directory that it runs in. |
belaran@999 | 10726 If Bugzilla and this hook are not installed on the same |
belaran@999 | 10727 machine, you will need to find a way to run |
belaran@999 | 10728 <literal moreinfo="none">processmail</literal> on the server where |
belaran@999 | 10729 Bugzilla is installed. |
belaran@999 | 10730 </para> |
belaran@999 | 10731 </listitem></itemizedlist> |
belaran@999 | 10732 |
belaran@999 | 10733 </sect3> |
belaran@999 | 10734 <sect3> |
belaran@999 | 10735 <title>Mapping committer names to Bugzilla user names</title> |
belaran@999 | 10736 |
belaran@999 | 10737 <para id="x_259">By default, the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook tries to use the |
belaran@999 | 10738 email address of a changeset's committer as the Bugzilla |
belaran@999 | 10739 user name with which to update a bug. If this does not suit |
belaran@999 | 10740 your needs, you can map committer email addresses to |
belaran@999 | 10741 Bugzilla user names using a <literal role="rc-usermap" moreinfo="none">usermap</literal> section. |
belaran@999 | 10742 </para> |
belaran@999 | 10743 |
belaran@999 | 10744 <para id="x_25a">Each item in the <literal role="rc-usermap" moreinfo="none">usermap</literal> section contains an |
belaran@999 | 10745 email address on the left, and a Bugzilla user name on the |
belaran@999 | 10746 right. |
belaran@999 | 10747 </para> |
belaran@999 | 10748 <programlisting format="linespecific">[usermap] |
belaran@999 | 10749 jane.user@example.com = jane</programlisting> |
belaran@999 | 10750 <para id="x_25b">You can either keep the <literal role="rc-usermap" moreinfo="none">usermap</literal> data in a normal |
belaran@999 | 10751 <filename role="special" moreinfo="none">~/.hgrc</filename>, or tell the |
belaran@999 | 10752 <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook to read the |
belaran@999 | 10753 information from an external <filename moreinfo="none">usermap</filename> |
belaran@999 | 10754 file. In the latter case, you can store |
belaran@999 | 10755 <filename moreinfo="none">usermap</filename> data by itself in (for example) |
belaran@999 | 10756 a user-modifiable repository. This makes it possible to let |
belaran@999 | 10757 your users maintain their own <envar role="rc-item-bugzilla">usermap</envar> entries. The main |
belaran@999 | 10758 <filename role="special" moreinfo="none">~/.hgrc</filename> file might look |
belaran@999 | 10759 like this: |
belaran@999 | 10760 </para> |
belaran@999 | 10761 <programlisting format="linespecific"># regular hgrc file refers to external usermap file |
belaran@999 | 10762 [bugzilla] |
belaran@999 | 10763 usermap = /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting> |
belaran@999 | 10764 <para id="x_25c">While the <filename moreinfo="none">usermap</filename> file that it |
belaran@999 | 10765 refers to might look like this: |
belaran@999 | 10766 </para> |
belaran@999 | 10767 <programlisting format="linespecific"># bugzilla-usermap.conf - inside a hg repository |
belaran@999 | 10768 [usermap] stephanie@example.com = steph</programlisting> |
belaran@999 | 10769 |
belaran@999 | 10770 </sect3> |
belaran@999 | 10771 <sect3> |
belaran@999 | 10772 <title>Configuring the text that gets added to a bug</title> |
belaran@999 | 10773 |
belaran@999 | 10774 <para id="x_25d">You can configure the text that this hook adds as a |
belaran@999 | 10775 comment; you specify it in the form of a Mercurial template. |
belaran@999 | 10776 Several <filename role="special" moreinfo="none">~/.hgrc</filename> entries |
belaran@999 | 10777 (still in the <literal role="rc-bugzilla" moreinfo="none">bugzilla</literal> |
belaran@999 | 10778 section) control this behavior. |
belaran@999 | 10779 </para> |
belaran@999 | 10780 <itemizedlist> |
belaran@999 | 10781 <listitem><para id="x_25e"><literal moreinfo="none">strip</literal>: The number of |
belaran@999 | 10782 leading path elements to strip from a repository's path |
belaran@999 | 10783 name to construct a partial path for a URL. For example, |
belaran@999 | 10784 if the repositories on your server live under <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and you |
belaran@999 | 10785 have a repository whose path is <filename class="directory" moreinfo="none">/home/hg/repos/app/tests</filename>, |
belaran@999 | 10786 then setting <literal moreinfo="none">strip</literal> to |
belaran@999 | 10787 <literal moreinfo="none">4</literal> will give a partial path of |
belaran@999 | 10788 <filename class="directory" moreinfo="none">app/tests</filename>. The |
belaran@999 | 10789 hook will make this partial path available when |
belaran@999 | 10790 expanding a template, as <literal moreinfo="none">webroot</literal>. |
belaran@999 | 10791 </para> |
belaran@999 | 10792 </listitem> |
belaran@999 | 10793 <listitem><para id="x_25f"><literal moreinfo="none">template</literal>: The text of the |
belaran@999 | 10794 template to use. In addition to the usual |
belaran@999 | 10795 changeset-related variables, this template can use |
belaran@999 | 10796 <literal moreinfo="none">hgweb</literal> (the value of the |
belaran@999 | 10797 <literal moreinfo="none">hgweb</literal> configuration item above) and |
belaran@999 | 10798 <literal moreinfo="none">webroot</literal> (the path constructed using |
belaran@999 | 10799 <literal moreinfo="none">strip</literal> above). |
belaran@999 | 10800 </para> |
belaran@999 | 10801 </listitem></itemizedlist> |
belaran@999 | 10802 |
belaran@999 | 10803 <para id="x_260">In addition, you can add a <envar role="rc-item-web">baseurl</envar> item to the <literal role="rc-web" moreinfo="none">web</literal> section of your <filename role="special" moreinfo="none">~/.hgrc</filename>. The <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook will make this |
belaran@999 | 10804 available when expanding a template, as the base string to |
belaran@999 | 10805 use when constructing a URL that will let users browse from |
belaran@999 | 10806 a Bugzilla comment to view a changeset. Example: |
belaran@999 | 10807 </para> |
belaran@999 | 10808 <programlisting format="linespecific">[web] |
belaran@999 | 10809 baseurl = http://hg.domain.com/</programlisting> |
belaran@999 | 10810 |
belaran@999 | 10811 <para id="x_261">Here is an example set of <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook config information. |
belaran@999 | 10812 </para> |
belaran@999 | 10813 |
belaran@999 | 10814 <!-- BEGIN ch10/bugzilla-config.lst --> |
belaran@999 | 10815 <programlisting format="linespecific">[bugzilla] |
belaran@999 | 10816 host = bugzilla.example.com |
belaran@999 | 10817 password = mypassword version = 2.16 |
belaran@999 | 10818 # server-side repos live in /home/hg/repos, so strip 4 leading |
belaran@999 | 10819 # separators |
belaran@999 | 10820 strip = 4 |
belaran@999 | 10821 hgweb = http://hg.example.com/ |
belaran@999 | 10822 usermap = /home/hg/repos/notify/bugzilla.conf |
belaran@999 | 10823 template = Changeset {node|short}, made by {author} in the {webroot} |
belaran@999 | 10824 repo, refers to this bug.\n |
belaran@999 | 10825 For complete details, see |
belaran@999 | 10826 {hgweb}{webroot}?cmd=changeset;node={node|short}\n |
belaran@999 | 10827 Changeset description:\n |
belaran@999 | 10828 \t{desc|tabindent}</programlisting> |
belaran@999 | 10829 <!-- END ch10/bugzilla-config.lst --> |
belaran@999 | 10830 |
belaran@999 | 10831 |
belaran@999 | 10832 </sect3> |
belaran@999 | 10833 <sect3> |
belaran@999 | 10834 <title>Testing and troubleshooting</title> |
belaran@999 | 10835 |
belaran@999 | 10836 <para id="x_262">The most common problems with configuring the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook relate to running |
belaran@999 | 10837 Bugzilla's <filename moreinfo="none">processmail</filename> script and |
belaran@999 | 10838 mapping committer names to user names. |
belaran@999 | 10839 </para> |
belaran@999 | 10840 |
belaran@999 | 10841 <para id="x_263">Recall from <xref linkend="sec:hook:bugzilla:config"/> above that the user |
belaran@999 | 10842 that runs the Mercurial process on the server is also the |
belaran@999 | 10843 one that will run the <filename moreinfo="none">processmail</filename> |
belaran@999 | 10844 script. The <filename moreinfo="none">processmail</filename> script |
belaran@999 | 10845 sometimes causes Bugzilla to write to files in its |
belaran@999 | 10846 configuration directory, and Bugzilla's configuration files |
belaran@999 | 10847 are usually owned by the user that your web server runs |
belaran@999 | 10848 under. |
belaran@999 | 10849 </para> |
belaran@999 | 10850 |
belaran@999 | 10851 <para id="x_264">You can cause <filename moreinfo="none">processmail</filename> to be run |
belaran@999 | 10852 with the suitable user's identity using the |
belaran@999 | 10853 <command moreinfo="none">sudo</command> command. Here is an example entry |
belaran@999 | 10854 for a <filename moreinfo="none">sudoers</filename> file. |
belaran@999 | 10855 </para> |
belaran@999 | 10856 <programlisting format="linespecific">hg_user = (httpd_user) |
belaran@999 | 10857 NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s</programlisting> |
belaran@999 | 10858 <para id="x_265">This allows the <literal moreinfo="none">hg_user</literal> user to run a |
belaran@999 | 10859 <filename moreinfo="none">processmail-wrapper</filename> program under the |
belaran@999 | 10860 identity of <literal moreinfo="none">httpd_user</literal>. |
belaran@999 | 10861 </para> |
belaran@999 | 10862 |
belaran@999 | 10863 <para id="x_266">This indirection through a wrapper script is necessary, |
belaran@999 | 10864 because <filename moreinfo="none">processmail</filename> expects to be run |
belaran@999 | 10865 with its current directory set to wherever you installed |
belaran@999 | 10866 Bugzilla; you can't specify that kind of constraint in a |
belaran@999 | 10867 <filename moreinfo="none">sudoers</filename> file. The contents of the |
belaran@999 | 10868 wrapper script are simple: |
belaran@999 | 10869 </para> |
belaran@999 | 10870 <programlisting format="linespecific">#!/bin/sh |
belaran@999 | 10871 cd `dirname $0` && ./processmail "$1" nobody@example.com</programlisting> |
belaran@999 | 10872 <para id="x_267">It doesn't seem to matter what email address you pass to |
belaran@999 | 10873 <filename moreinfo="none">processmail</filename>. |
belaran@999 | 10874 </para> |
belaran@999 | 10875 |
belaran@999 | 10876 <para id="x_268">If your <literal role="rc-usermap" moreinfo="none">usermap</literal> is |
belaran@999 | 10877 not set up correctly, users will see an error message from |
belaran@999 | 10878 the <literal role="hg-ext" moreinfo="none">bugzilla</literal> hook when they |
belaran@999 | 10879 push changes to the server. The error message will look |
belaran@999 | 10880 like this: |
belaran@999 | 10881 </para> |
belaran@999 | 10882 <programlisting format="linespecific">cannot find bugzilla user id for john.q.public@example.com</programlisting> |
belaran@999 | 10883 <para id="x_269">What this means is that the committer's address, |
belaran@999 | 10884 <literal moreinfo="none">john.q.public@example.com</literal>, is not a valid |
belaran@999 | 10885 Bugzilla user name, nor does it have an entry in your |
belaran@999 | 10886 <literal role="rc-usermap" moreinfo="none">usermap</literal> that maps it to |
belaran@999 | 10887 a valid Bugzilla user name. |
belaran@999 | 10888 </para> |
belaran@999 | 10889 |
belaran@999 | 10890 </sect3> </sect2> |
belaran@999 | 10891 |
belaran@999 | 10892 <sect2> |
belaran@999 | 10893 <title><literal role="hg-ext" moreinfo="none">notify</literal>—send email |
belaran@999 | 10894 notifications</title> |
belaran@999 | 10895 |
belaran@999 | 10896 <para id="x_26a">Although Mercurial's built-in web server provides RSS |
belaran@999 | 10897 feeds of changes in every repository, many people prefer to |
belaran@999 | 10898 receive change notifications via email. The <literal role="hg-ext" moreinfo="none">notify</literal> hook lets you send out |
belaran@999 | 10899 notifications to a set of email addresses whenever changesets |
belaran@999 | 10900 arrive that those subscribers are interested in. |
belaran@999 | 10901 </para> |
belaran@999 | 10902 |
belaran@999 | 10903 <para id="x_26b">As with the <literal role="hg-ext" moreinfo="none">bugzilla</literal> |
belaran@999 | 10904 hook, the <literal role="hg-ext" moreinfo="none">notify</literal> hook is |
belaran@999 | 10905 template-driven, so you can customise the contents of the |
belaran@999 | 10906 notification messages that it sends. |
belaran@999 | 10907 </para> |
belaran@999 | 10908 |
belaran@999 | 10909 <para id="x_26c">By default, the <literal role="hg-ext" moreinfo="none">notify</literal> |
belaran@999 | 10910 hook includes a diff of every changeset that it sends out; you |
belaran@999 | 10911 can limit the size of the diff, or turn this feature off |
belaran@999 | 10912 entirely. It is useful for letting subscribers review changes |
belaran@999 | 10913 immediately, rather than clicking to follow a URL. |
belaran@999 | 10914 </para> |
belaran@999 | 10915 |
belaran@999 | 10916 <sect3> |
belaran@999 | 10917 <title>Configuring the <literal role="hg-ext" moreinfo="none">notify</literal> |
belaran@999 | 10918 hook</title> |
belaran@999 | 10919 |
belaran@999 | 10920 <para id="x_26d">You can set up the <literal role="hg-ext" moreinfo="none">notify</literal> hook to send one email |
belaran@999 | 10921 message per incoming changeset, or one per incoming group of |
belaran@999 | 10922 changesets (all those that arrived in a single pull or |
belaran@999 | 10923 push). |
belaran@999 | 10924 </para> |
belaran@999 | 10925 <programlisting format="linespecific">[hooks] |
belaran@999 | 10926 # send one email per group of changes |
belaran@999 | 10927 changegroup.notify = python:hgext.notify.hook |
belaran@999 | 10928 # send one email per change |
belaran@999 | 10929 incoming.notify = python:hgext.notify.hook</programlisting> |
belaran@999 | 10930 |
belaran@999 | 10931 <para id="x_26e">Configuration information for this hook lives in the |
belaran@999 | 10932 <literal role="rc-notify" moreinfo="none">notify</literal> section of a |
belaran@999 | 10933 <filename role="special" moreinfo="none">~/.hgrc</filename> file. |
belaran@999 | 10934 </para> |
belaran@999 | 10935 <itemizedlist> |
belaran@999 | 10936 <listitem><para id="x_26f"><envar role="rc-item-notify">test</envar>: |
belaran@999 | 10937 By default, this hook does not send out email at all; |
belaran@999 | 10938 instead, it prints the message that it |
belaran@999 | 10939 <emphasis>would</emphasis> send. Set this item to |
belaran@999 | 10940 <literal moreinfo="none">false</literal> to allow email to be sent. The |
belaran@999 | 10941 reason that sending of email is turned off by default is |
belaran@999 | 10942 that it takes several tries to configure this extension |
belaran@999 | 10943 exactly as you would like, and it would be bad form to |
belaran@999 | 10944 spam subscribers with a number of <quote>broken</quote> |
belaran@999 | 10945 notifications while you debug your configuration. |
belaran@999 | 10946 </para> |
belaran@999 | 10947 </listitem> |
belaran@999 | 10948 <listitem><para id="x_270"><envar role="rc-item-notify">config</envar>: |
belaran@999 | 10949 The path to a configuration file that contains |
belaran@999 | 10950 subscription information. This is kept separate from |
belaran@999 | 10951 the main <filename role="special" moreinfo="none">~/.hgrc</filename> so |
belaran@999 | 10952 that you can maintain it in a repository of its own. |
belaran@999 | 10953 People can then clone that repository, update their |
belaran@999 | 10954 subscriptions, and push the changes back to your server. |
belaran@999 | 10955 </para> |
belaran@999 | 10956 </listitem> |
belaran@999 | 10957 <listitem><para id="x_271"><envar role="rc-item-notify">strip</envar>: |
belaran@999 | 10958 The number of leading path separator characters to strip |
belaran@999 | 10959 from a repository's path, when deciding whether a |
belaran@999 | 10960 repository has subscribers. For example, if the |
belaran@999 | 10961 repositories on your server live in <filename class="directory" moreinfo="none">/home/hg/repos</filename>, and |
belaran@999 | 10962 <literal role="hg-ext" moreinfo="none">notify</literal> is considering a |
belaran@999 | 10963 repository named <filename class="directory" moreinfo="none">/home/hg/repos/shared/test</filename>, |
belaran@999 | 10964 setting <envar role="rc-item-notify">strip</envar> to |
belaran@999 | 10965 <literal moreinfo="none">4</literal> will cause <literal role="hg-ext" moreinfo="none">notify</literal> to trim the path it |
belaran@999 | 10966 considers down to <filename class="directory" moreinfo="none">shared/test</filename>, and it will |
belaran@999 | 10967 match subscribers against that. |
belaran@999 | 10968 </para> |
belaran@999 | 10969 </listitem> |
belaran@999 | 10970 <listitem><para id="x_272"><envar role="rc-item-notify">template</envar>: The template |
belaran@999 | 10971 text to use when sending messages. This specifies both |
belaran@999 | 10972 the contents of the message header and its body. |
belaran@999 | 10973 </para> |
belaran@999 | 10974 </listitem> |
belaran@999 | 10975 <listitem><para id="x_273"><envar role="rc-item-notify">maxdiff</envar>: The maximum |
belaran@999 | 10976 number of lines of diff data to append to the end of a |
belaran@999 | 10977 message. If a diff is longer than this, it is |
belaran@999 | 10978 truncated. By default, this is set to 300. Set this to |
belaran@999 | 10979 <literal moreinfo="none">0</literal> to omit diffs from notification |
belaran@999 | 10980 emails. |
belaran@999 | 10981 </para> |
belaran@999 | 10982 </listitem> |
belaran@999 | 10983 <listitem><para id="x_274"><envar role="rc-item-notify">sources</envar>: A list of |
belaran@999 | 10984 sources of changesets to consider. This lets you limit |
belaran@999 | 10985 <literal role="hg-ext" moreinfo="none">notify</literal> to only sending |
belaran@999 | 10986 out email about changes that remote users pushed into |
belaran@999 | 10987 this repository via a server, for example. See |
belaran@999 | 10988 <xref linkend="sec:hook:sources"/> for the sources you |
belaran@999 | 10989 can specify here. |
belaran@999 | 10990 </para> |
belaran@999 | 10991 </listitem></itemizedlist> |
belaran@999 | 10992 |
belaran@999 | 10993 <para id="x_275">If you set the <envar role="rc-item-web">baseurl</envar> |
belaran@999 | 10994 item in the <literal role="rc-web" moreinfo="none">web</literal> section, |
belaran@999 | 10995 you can use it in a template; it will be available as |
belaran@999 | 10996 <literal moreinfo="none">webroot</literal>. |
belaran@999 | 10997 </para> |
belaran@999 | 10998 |
belaran@999 | 10999 <para id="x_276">Here is an example set of <literal role="hg-ext" moreinfo="none">notify</literal> configuration information. |
belaran@999 | 11000 </para> |
belaran@999 | 11001 |
belaran@999 | 11002 <!-- BEGIN ch10/notify-config.lst --> |
belaran@999 | 11003 <programlisting format="linespecific">[notify] |
belaran@999 | 11004 # really send email |
belaran@999 | 11005 test = false |
belaran@999 | 11006 # subscriber data lives in the notify repo |
belaran@999 | 11007 config = /home/hg/repos/notify/notify.conf |
belaran@999 | 11008 # repos live in /home/hg/repos on server, so strip 4 "/" chars |
belaran@999 | 11009 strip = 4 |
belaran@999 | 11010 template = X-Hg-Repo: {webroot}\n |
belaran@999 | 11011 Subject: {webroot}: {desc|firstline|strip}\n |
belaran@999 | 11012 From: {author} |
belaran@999 | 11013 \n\n |
belaran@999 | 11014 changeset {node|short} in {root} |
belaran@999 | 11015 \n\ndetails: |
belaran@999 | 11016 {baseurl}{webroot}?cmd=changeset;node={node|short} |
belaran@999 | 11017 description: {desc|tabindent|strip} |
belaran@999 | 11018 |
belaran@999 | 11019 [web] |
belaran@999 | 11020 baseurl = |
belaran@999 | 11021 http://hg.example.com/</programlisting> |
belaran@999 | 11022 <!-- END ch10/notify-config.lst --> |
belaran@999 | 11023 |
belaran@999 | 11024 |
belaran@999 | 11025 <para id="x_277">This will produce a message that looks like the |
belaran@999 | 11026 following: |
belaran@999 | 11027 </para> |
belaran@999 | 11028 |
belaran@999 | 11029 <!-- BEGIN ch10/notify-config-mail.lst --> |
belaran@999 | 11030 <programlisting format="linespecific">X-Hg-Repo: tests/slave |
belaran@999 | 11031 Subject: tests/slave: Handle error case when slave has no buffers |
belaran@999 | 11032 Date: Wed, 2 Aug 2006 15:25:46 -0700 (PDT) |
belaran@999 | 11033 |
belaran@999 | 11034 changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave |
belaran@999 | 11035 |
belaran@999 | 11036 details: |
belaran@999 | 11037 http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 |
belaran@999 | 11038 |
belaran@999 | 11039 description: Handle error case when slave has no buffers |
belaran@999 | 11040 |
belaran@999 | 11041 diffs (54 lines): |
belaran@999 | 11042 diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h |
belaran@999 | 11043 --- a/include/tests.h Wed Aug 02 15:19:52 2006 -0700 |
belaran@999 | 11044 +++ b/include/tests.h Wed Aug 02 15:25:26 2006 -0700 |
belaran@999 | 11045 @@ -212,6 +212,15 @@ static __inline__ |
belaran@999 | 11046 void test_headers(void *h) |
belaran@999 | 11047 [...snip...]</programlisting> |
belaran@999 | 11048 <!-- END ch10/notify-config-mail.lst --> |
belaran@999 | 11049 |
belaran@999 | 11050 |
belaran@999 | 11051 </sect3> |
belaran@999 | 11052 <sect3> |
belaran@999 | 11053 <title>Testing and troubleshooting</title> |
belaran@999 | 11054 |
belaran@999 | 11055 <para id="x_278">Do not forget that by default, the <literal role="hg-ext" moreinfo="none">notify</literal> extension <emphasis>will not |
belaran@999 | 11056 send any mail</emphasis> until you explicitly configure it to do so, |
belaran@999 | 11057 by setting <envar role="rc-item-notify">test</envar> to |
belaran@999 | 11058 <literal moreinfo="none">false</literal>. Until you do that, it simply |
belaran@999 | 11059 prints the message it <emphasis>would</emphasis> send. |
belaran@999 | 11060 </para> |
belaran@999 | 11061 |
belaran@999 | 11062 </sect3> |
belaran@999 | 11063 </sect2> |
belaran@999 | 11064 </sect1> |
belaran@999 | 11065 <sect1 id="sec:hook:ref"> |
belaran@999 | 11066 <title>Information for writers of hooks</title> |
belaran@999 | 11067 |
belaran@999 | 11068 <sect2> |
belaran@999 | 11069 <title>In-process hook execution</title> |
belaran@999 | 11070 |
belaran@999 | 11071 <para id="x_279">An in-process hook is called with arguments of the |
belaran@999 | 11072 following form: |
belaran@999 | 11073 </para> |
belaran@999 | 11074 <programlisting format="linespecific">def myhook(ui, repo, **kwargs): pass</programlisting> |
belaran@999 | 11075 <para id="x_27a">The <literal moreinfo="none">ui</literal> parameter is a <literal role="py-mod-mercurial.ui" moreinfo="none">ui</literal> object. The |
belaran@999 | 11076 <literal moreinfo="none">repo</literal> parameter is a <literal role="py-mod-mercurial.localrepo" moreinfo="none">localrepository</literal> |
belaran@999 | 11077 object. The names and values of the |
belaran@999 | 11078 <literal moreinfo="none">**kwargs</literal> parameters depend on the hook |
belaran@999 | 11079 being invoked, with the following common features: |
belaran@999 | 11080 </para> |
belaran@999 | 11081 <itemizedlist> |
belaran@999 | 11082 <listitem><para id="x_27b">If a parameter is named |
belaran@999 | 11083 <literal moreinfo="none">node</literal> or <literal moreinfo="none">parentN</literal>, it |
belaran@999 | 11084 will contain a hexadecimal changeset ID. The empty string |
belaran@999 | 11085 is used to represent <quote>null changeset ID</quote> |
belaran@999 | 11086 instead of a string of zeroes. |
belaran@999 | 11087 </para> |
belaran@999 | 11088 </listitem> |
belaran@999 | 11089 <listitem><para id="x_27c">If a parameter is named |
belaran@999 | 11090 <literal moreinfo="none">url</literal>, it will contain the URL of a |
belaran@999 | 11091 remote repository, if that can be determined. |
belaran@999 | 11092 </para> |
belaran@999 | 11093 </listitem> |
belaran@999 | 11094 <listitem><para id="x_27d">Boolean-valued parameters are represented as |
belaran@999 | 11095 Python <literal moreinfo="none">bool</literal> objects. |
belaran@999 | 11096 </para> |
belaran@999 | 11097 </listitem></itemizedlist> |
belaran@999 | 11098 |
belaran@999 | 11099 <para id="x_27e">An in-process hook is called without a change to the |
belaran@999 | 11100 process's working directory (unlike external hooks, which are |
belaran@999 | 11101 run in the root of the repository). It must not change the |
belaran@999 | 11102 process's working directory, or it will cause any calls it |
belaran@999 | 11103 makes into the Mercurial API to fail. |
belaran@999 | 11104 </para> |
belaran@999 | 11105 |
belaran@999 | 11106 <para id="x_27f">If a hook returns a boolean <quote>false</quote> value, it |
belaran@999 | 11107 is considered to have succeeded. If it returns a boolean |
belaran@999 | 11108 <quote>true</quote> value or raises an exception, it is |
belaran@999 | 11109 considered to have failed. A useful way to think of the |
belaran@999 | 11110 calling convention is <quote>tell me if you fail</quote>. |
belaran@999 | 11111 </para> |
belaran@999 | 11112 |
belaran@999 | 11113 <para id="x_280">Note that changeset IDs are passed into Python hooks as |
belaran@999 | 11114 hexadecimal strings, not the binary hashes that Mercurial's |
belaran@999 | 11115 APIs normally use. To convert a hash from hex to binary, use |
belaran@999 | 11116 the <literal moreinfo="none">bin</literal> function. |
belaran@999 | 11117 </para> |
belaran@999 | 11118 </sect2> |
belaran@999 | 11119 |
belaran@999 | 11120 <sect2> |
belaran@999 | 11121 <title>External hook execution</title> |
belaran@999 | 11122 |
belaran@999 | 11123 <para id="x_281">An external hook is passed to the shell of the user |
belaran@999 | 11124 running Mercurial. Features of that shell, such as variable |
belaran@999 | 11125 substitution and command redirection, are available. The hook |
belaran@999 | 11126 is run in the root directory of the repository (unlike |
belaran@999 | 11127 in-process hooks, which are run in the same directory that |
belaran@999 | 11128 Mercurial was run in). |
belaran@999 | 11129 </para> |
belaran@999 | 11130 |
belaran@999 | 11131 <para id="x_282">Hook parameters are passed to the hook as environment |
belaran@999 | 11132 variables. Each environment variable's name is converted in |
belaran@999 | 11133 upper case and prefixed with the string |
belaran@999 | 11134 <quote><literal moreinfo="none">HG_</literal></quote>. For example, if the |
belaran@999 | 11135 name of a parameter is <quote><literal moreinfo="none">node</literal></quote>, |
belaran@999 | 11136 the name of the environment variable representing that |
belaran@999 | 11137 parameter will be <quote><literal moreinfo="none">HG_NODE</literal></quote>. |
belaran@999 | 11138 </para> |
belaran@999 | 11139 |
belaran@999 | 11140 <para id="x_283">A boolean parameter is represented as the string |
belaran@999 | 11141 <quote><literal moreinfo="none">1</literal></quote> for <quote>true</quote>, |
belaran@999 | 11142 <quote><literal moreinfo="none">0</literal></quote> for <quote>false</quote>. |
belaran@999 | 11143 If an environment variable is named <envar>HG_NODE</envar>, |
belaran@999 | 11144 <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it |
belaran@999 | 11145 contains a changeset ID represented as a hexadecimal string. |
belaran@999 | 11146 The empty string is used to represent <quote>null changeset |
belaran@999 | 11147 ID</quote> instead of a string of zeroes. If an environment |
belaran@999 | 11148 variable is named <envar>HG_URL</envar>, it will contain the |
belaran@999 | 11149 URL of a remote repository, if that can be determined. |
belaran@999 | 11150 </para> |
belaran@999 | 11151 |
belaran@999 | 11152 <para id="x_284">If a hook exits with a status of zero, it is considered to |
belaran@999 | 11153 have succeeded. If it exits with a non-zero status, it is |
belaran@999 | 11154 considered to have failed. |
belaran@999 | 11155 </para> |
belaran@999 | 11156 </sect2> |
belaran@999 | 11157 |
belaran@999 | 11158 <sect2> |
belaran@999 | 11159 <title>Finding out where changesets come from</title> |
belaran@999 | 11160 |
belaran@999 | 11161 <para id="x_285">A hook that involves the transfer of changesets between a |
belaran@999 | 11162 local repository and another may be able to find out |
belaran@999 | 11163 information about the <quote>far side</quote>. Mercurial |
belaran@999 | 11164 knows <emphasis>how</emphasis> changes are being transferred, |
belaran@999 | 11165 and in many cases <emphasis>where</emphasis> they are being |
belaran@999 | 11166 transferred to or from. |
belaran@999 | 11167 </para> |
belaran@999 | 11168 |
belaran@999 | 11169 <sect3 id="sec:hook:sources"> |
belaran@999 | 11170 <title>Sources of changesets</title> |
belaran@999 | 11171 |
belaran@999 | 11172 <para id="x_286">Mercurial will tell a hook what means are, or were, used |
belaran@999 | 11173 to transfer changesets between repositories. This is |
belaran@999 | 11174 provided by Mercurial in a Python parameter named |
belaran@999 | 11175 <literal moreinfo="none">source</literal>, or an environment variable named |
belaran@999 | 11176 <envar>HG_SOURCE</envar>. |
belaran@999 | 11177 </para> |
belaran@999 | 11178 |
belaran@999 | 11179 <itemizedlist> |
belaran@999 | 11180 <listitem><para id="x_287"><literal moreinfo="none">serve</literal>: Changesets are |
belaran@999 | 11181 transferred to or from a remote repository over http or |
belaran@999 | 11182 ssh. |
belaran@999 | 11183 </para> |
belaran@999 | 11184 </listitem> |
belaran@999 | 11185 <listitem><para id="x_288"><literal moreinfo="none">pull</literal>: Changesets are |
belaran@999 | 11186 being transferred via a pull from one repository into |
belaran@999 | 11187 another. |
belaran@999 | 11188 </para> |
belaran@999 | 11189 </listitem> |
belaran@999 | 11190 <listitem><para id="x_289"><literal moreinfo="none">push</literal>: Changesets are |
belaran@999 | 11191 being transferred via a push from one repository into |
belaran@999 | 11192 another. |
belaran@999 | 11193 </para> |
belaran@999 | 11194 </listitem> |
belaran@999 | 11195 <listitem><para id="x_28a"><literal moreinfo="none">bundle</literal>: Changesets are |
belaran@999 | 11196 being transferred to or from a bundle. |
belaran@999 | 11197 </para> |
belaran@999 | 11198 </listitem></itemizedlist> |
belaran@999 | 11199 </sect3> |
belaran@999 | 11200 |
belaran@999 | 11201 <sect3 id="sec:hook:url"> |
belaran@999 | 11202 <title>Where changes are going—remote repository |
belaran@999 | 11203 URLs</title> |
belaran@999 | 11204 |
belaran@999 | 11205 <para id="x_28b">When possible, Mercurial will tell a hook the location |
belaran@999 | 11206 of the <quote>far side</quote> of an activity that transfers |
belaran@999 | 11207 changeset data between repositories. This is provided by |
belaran@999 | 11208 Mercurial in a Python parameter named |
belaran@999 | 11209 <literal moreinfo="none">url</literal>, or an environment variable named |
belaran@999 | 11210 <envar>HG_URL</envar>. |
belaran@999 | 11211 </para> |
belaran@999 | 11212 |
belaran@999 | 11213 <para id="x_28c">This information is not always known. If a hook is |
belaran@999 | 11214 invoked in a repository that is being served via http or |
belaran@999 | 11215 ssh, Mercurial cannot tell where the remote repository is, |
belaran@999 | 11216 but it may know where the client is connecting from. In |
belaran@999 | 11217 such cases, the URL will take one of the following forms: |
belaran@999 | 11218 </para> |
belaran@999 | 11219 <itemizedlist> |
belaran@999 | 11220 <listitem><para id="x_28d"><literal moreinfo="none">remote:ssh:1.2.3.4</literal>—remote |
belaran@999 | 11221 ssh client, at the IP address |
belaran@999 | 11222 <literal moreinfo="none">1.2.3.4</literal>. |
belaran@999 | 11223 </para> |
belaran@999 | 11224 </listitem> |
belaran@999 | 11225 <listitem><para id="x_28e"><literal moreinfo="none">remote:http:1.2.3.4</literal>—remote |
belaran@999 | 11226 http client, at the IP address |
belaran@999 | 11227 <literal moreinfo="none">1.2.3.4</literal>. If the client is using SSL, |
belaran@999 | 11228 this will be of the form |
belaran@999 | 11229 <literal moreinfo="none">remote:https:1.2.3.4</literal>. |
belaran@999 | 11230 </para> |
belaran@999 | 11231 </listitem> |
belaran@999 | 11232 <listitem><para id="x_28f">Empty—no information could be |
belaran@999 | 11233 discovered about the remote client. |
belaran@999 | 11234 </para> |
belaran@999 | 11235 </listitem></itemizedlist> |
belaran@999 | 11236 </sect3> |
belaran@999 | 11237 </sect2> |
belaran@999 | 11238 </sect1> |
belaran@999 | 11239 <sect1> |
belaran@999 | 11240 <title>Hook reference</title> |
belaran@999 | 11241 |
belaran@999 | 11242 <sect2 id="sec:hook:changegroup"> |
belaran@999 | 11243 <title><literal role="hook" moreinfo="none">changegroup</literal>—after |
belaran@999 | 11244 remote changesets added</title> |
belaran@999 | 11245 |
belaran@999 | 11246 <para id="x_290">This hook is run after a group of pre-existing changesets |
belaran@999 | 11247 has been added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg pull</command> or <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 11248 unbundle</command>. This hook is run once per operation |
belaran@999 | 11249 that added one or more changesets. This is in contrast to the |
belaran@999 | 11250 <literal role="hook" moreinfo="none">incoming</literal> hook, which is run |
belaran@999 | 11251 once per changeset, regardless of whether the changesets |
belaran@999 | 11252 arrive in a group. |
belaran@999 | 11253 </para> |
belaran@999 | 11254 |
belaran@999 | 11255 <para id="x_291">Some possible uses for this hook include kicking off an |
belaran@999 | 11256 automated build or test of the added changesets, updating a |
belaran@999 | 11257 bug database, or notifying subscribers that a repository |
belaran@999 | 11258 contains new changes. |
belaran@999 | 11259 </para> |
belaran@999 | 11260 |
belaran@999 | 11261 <para id="x_292">Parameters to this hook: |
belaran@999 | 11262 </para> |
belaran@999 | 11263 <itemizedlist> |
belaran@999 | 11264 <listitem><para id="x_293"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11265 changeset ID of the first changeset in the group that was |
belaran@999 | 11266 added. All changesets between this and |
belaran@999 | 11267 <literal role="tag" moreinfo="none">tip</literal>, inclusive, were added by a single |
belaran@999 | 11268 <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg unbundle</command>. |
belaran@999 | 11269 </para> |
belaran@999 | 11270 </listitem> |
belaran@999 | 11271 <listitem><para id="x_294"><literal moreinfo="none">source</literal>: A |
belaran@999 | 11272 string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details. |
belaran@999 | 11273 </para> |
belaran@999 | 11274 </listitem> |
belaran@999 | 11275 <listitem><para id="x_295"><literal moreinfo="none">url</literal>: A URL. The |
belaran@999 | 11276 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. |
belaran@999 | 11277 </para> |
belaran@999 | 11278 </listitem></itemizedlist> |
belaran@999 | 11279 |
belaran@999 | 11280 <para id="x_296">See also: <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>) |
belaran@999 | 11281 </para> |
belaran@999 | 11282 </sect2> |
belaran@999 | 11283 |
belaran@999 | 11284 <sect2 id="sec:hook:commit"> |
belaran@999 | 11285 <title><literal role="hook" moreinfo="none">commit</literal>—after a new |
belaran@999 | 11286 changeset is created</title> |
belaran@999 | 11287 |
belaran@999 | 11288 <para id="x_297">This hook is run after a new changeset has been created. |
belaran@999 | 11289 </para> |
belaran@999 | 11290 |
belaran@999 | 11291 <para id="x_298">Parameters to this hook: |
belaran@999 | 11292 </para> |
belaran@999 | 11293 <itemizedlist> |
belaran@999 | 11294 <listitem><para id="x_299"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11295 changeset ID of the newly committed changeset. |
belaran@999 | 11296 </para> |
belaran@999 | 11297 </listitem> |
belaran@999 | 11298 <listitem><para id="x_29a"><literal moreinfo="none">parent1</literal>: A changeset ID. |
belaran@999 | 11299 The changeset ID of the first parent of the newly |
belaran@999 | 11300 committed changeset. |
belaran@999 | 11301 </para> |
belaran@999 | 11302 </listitem> |
belaran@999 | 11303 <listitem><para id="x_29b"><literal moreinfo="none">parent2</literal>: A changeset ID. |
belaran@999 | 11304 The changeset ID of the second parent of the newly |
belaran@999 | 11305 committed changeset. |
belaran@999 | 11306 </para> |
belaran@999 | 11307 </listitem></itemizedlist> |
belaran@999 | 11308 |
belaran@999 | 11309 <para id="x_29c">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>) |
belaran@999 | 11310 </para> |
belaran@999 | 11311 </sect2> |
belaran@999 | 11312 |
belaran@999 | 11313 <sect2 id="sec:hook:incoming"> |
belaran@999 | 11314 <title><literal role="hook" moreinfo="none">incoming</literal>—after one |
belaran@999 | 11315 remote changeset is added</title> |
belaran@999 | 11316 |
belaran@999 | 11317 <para id="x_29d">This hook is run after a pre-existing changeset has been |
belaran@999 | 11318 added to the repository, for example via a <command role="hg-cmd" moreinfo="none">hg push</command>. If a group of changesets |
belaran@999 | 11319 was added in a single operation, this hook is called once for |
belaran@999 | 11320 each added changeset. |
belaran@999 | 11321 </para> |
belaran@999 | 11322 |
belaran@999 | 11323 <para id="x_29e">You can use this hook for the same purposes as |
belaran@999 | 11324 the <literal role="hook" moreinfo="none">changegroup</literal> hook (<xref linkend="sec:hook:changegroup"/>); it's simply more |
belaran@999 | 11325 convenient sometimes to run a hook once per group of |
belaran@999 | 11326 changesets, while other times it's handier once per changeset. |
belaran@999 | 11327 </para> |
belaran@999 | 11328 |
belaran@999 | 11329 <para id="x_29f">Parameters to this hook: |
belaran@999 | 11330 </para> |
belaran@999 | 11331 <itemizedlist> |
belaran@999 | 11332 <listitem><para id="x_2a0"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11333 ID of the newly added changeset. |
belaran@999 | 11334 </para> |
belaran@999 | 11335 </listitem> |
belaran@999 | 11336 <listitem><para id="x_2a1"><literal moreinfo="none">source</literal>: A |
belaran@999 | 11337 string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details. |
belaran@999 | 11338 </para> |
belaran@999 | 11339 </listitem> |
belaran@999 | 11340 <listitem><para id="x_2a2"><literal moreinfo="none">url</literal>: A URL. The |
belaran@999 | 11341 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. |
belaran@999 | 11342 </para> |
belaran@999 | 11343 </listitem></itemizedlist> |
belaran@999 | 11344 |
belaran@999 | 11345 <para id="x_2a3">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>) <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>) |
belaran@999 | 11346 </para> |
belaran@999 | 11347 </sect2> |
belaran@999 | 11348 |
belaran@999 | 11349 <sect2 id="sec:hook:outgoing"> |
belaran@999 | 11350 <title><literal role="hook" moreinfo="none">outgoing</literal>—after |
belaran@999 | 11351 changesets are propagated</title> |
belaran@999 | 11352 |
belaran@999 | 11353 <para id="x_2a4">This hook is run after a group of changesets has been |
belaran@999 | 11354 propagated out of this repository, for example by a <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 11355 bundle</command> command. |
belaran@999 | 11356 </para> |
belaran@999 | 11357 |
belaran@999 | 11358 <para id="x_2a5">One possible use for this hook is to notify administrators |
belaran@999 | 11359 that changes have been pulled. |
belaran@999 | 11360 </para> |
belaran@999 | 11361 |
belaran@999 | 11362 <para id="x_2a6">Parameters to this hook: |
belaran@999 | 11363 </para> |
belaran@999 | 11364 <itemizedlist> |
belaran@999 | 11365 <listitem><para id="x_2a7"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11366 changeset ID of the first changeset of the group that was |
belaran@999 | 11367 sent. |
belaran@999 | 11368 </para> |
belaran@999 | 11369 </listitem> |
belaran@999 | 11370 <listitem><para id="x_2a8"><literal moreinfo="none">source</literal>: A string. The |
belaran@999 | 11371 source of the of the operation (see <xref linkend="sec:hook:sources"/>). If a remote |
belaran@999 | 11372 client pulled changes from this repository, |
belaran@999 | 11373 <literal moreinfo="none">source</literal> will be |
belaran@999 | 11374 <literal moreinfo="none">serve</literal>. If the client that obtained |
belaran@999 | 11375 changes from this repository was local, |
belaran@999 | 11376 <literal moreinfo="none">source</literal> will be |
belaran@999 | 11377 <literal moreinfo="none">bundle</literal>, <literal moreinfo="none">pull</literal>, or |
belaran@999 | 11378 <literal moreinfo="none">push</literal>, depending on the operation the |
belaran@999 | 11379 client performed. |
belaran@999 | 11380 </para> |
belaran@999 | 11381 </listitem> |
belaran@999 | 11382 <listitem><para id="x_2a9"><literal moreinfo="none">url</literal>: A URL. The |
belaran@999 | 11383 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. |
belaran@999 | 11384 </para> |
belaran@999 | 11385 </listitem></itemizedlist> |
belaran@999 | 11386 |
belaran@999 | 11387 <para id="x_2aa">See also: <literal role="hook" moreinfo="none">preoutgoing</literal> (<xref linkend="sec:hook:preoutgoing"/>) |
belaran@999 | 11388 </para> |
belaran@999 | 11389 </sect2> |
belaran@999 | 11390 |
belaran@999 | 11391 <sect2 id="sec:hook:prechangegroup"> |
belaran@999 | 11392 <title><literal role="hook" moreinfo="none">prechangegroup</literal>—before starting |
belaran@999 | 11393 to add remote changesets</title> |
belaran@999 | 11394 |
belaran@999 | 11395 <para id="x_2ab">This controlling hook is run before Mercurial begins to |
belaran@999 | 11396 add a group of changesets from another repository. |
belaran@999 | 11397 </para> |
belaran@999 | 11398 |
belaran@999 | 11399 <para id="x_2ac">This hook does not have any information about the |
belaran@999 | 11400 changesets to be added, because it is run before transmission |
belaran@999 | 11401 of those changesets is allowed to begin. If this hook fails, |
belaran@999 | 11402 the changesets will not be transmitted. |
belaran@999 | 11403 </para> |
belaran@999 | 11404 |
belaran@999 | 11405 <para id="x_2ad">One use for this hook is to prevent external changes from |
belaran@999 | 11406 being added to a repository. For example, you could use this |
belaran@999 | 11407 to <quote>freeze</quote> a server-hosted branch temporarily or |
belaran@999 | 11408 permanently so that users cannot push to it, while still |
belaran@999 | 11409 allowing a local administrator to modify the repository. |
belaran@999 | 11410 </para> |
belaran@999 | 11411 |
belaran@999 | 11412 <para id="x_2ae">Parameters to this hook: |
belaran@999 | 11413 </para> |
belaran@999 | 11414 <itemizedlist> |
belaran@999 | 11415 <listitem><para id="x_2af"><literal moreinfo="none">source</literal>: A string. The |
belaran@999 | 11416 source of these changes. See <xref linkend="sec:hook:sources"/> for details. |
belaran@999 | 11417 </para> |
belaran@999 | 11418 </listitem> |
belaran@999 | 11419 <listitem><para id="x_2b0"><literal moreinfo="none">url</literal>: A URL. The |
belaran@999 | 11420 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. |
belaran@999 | 11421 </para> |
belaran@999 | 11422 </listitem></itemizedlist> |
belaran@999 | 11423 |
belaran@999 | 11424 <para id="x_2b1">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>), <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">pretxnchangegroup</literal> (<xref linkend="sec:hook:pretxnchangegroup"/>) |
belaran@999 | 11425 </para> |
belaran@999 | 11426 </sect2> |
belaran@999 | 11427 |
belaran@999 | 11428 <sect2 id="sec:hook:precommit"> |
belaran@999 | 11429 <title><literal role="hook" moreinfo="none">precommit</literal>—before |
belaran@999 | 11430 starting to commit a changeset</title> |
belaran@999 | 11431 |
belaran@999 | 11432 <para id="x_2b2">This hook is run before Mercurial begins to commit a new |
belaran@999 | 11433 changeset. It is run before Mercurial has any of the metadata |
belaran@999 | 11434 for the commit, such as the files to be committed, the commit |
belaran@999 | 11435 message, or the commit date. |
belaran@999 | 11436 </para> |
belaran@999 | 11437 |
belaran@999 | 11438 <para id="x_2b3">One use for this hook is to disable the ability to commit |
belaran@999 | 11439 new changesets, while still allowing incoming changesets. |
belaran@999 | 11440 Another is to run a build or test, and only allow the commit |
belaran@999 | 11441 to begin if the build or test succeeds. |
belaran@999 | 11442 </para> |
belaran@999 | 11443 |
belaran@999 | 11444 <para id="x_2b4">Parameters to this hook: |
belaran@999 | 11445 </para> |
belaran@999 | 11446 <itemizedlist> |
belaran@999 | 11447 <listitem><para id="x_2b5"><literal moreinfo="none">parent1</literal>: A changeset ID. |
belaran@999 | 11448 The changeset ID of the first parent of the working |
belaran@999 | 11449 directory. |
belaran@999 | 11450 </para> |
belaran@999 | 11451 </listitem> |
belaran@999 | 11452 <listitem><para id="x_2b6"><literal moreinfo="none">parent2</literal>: A changeset ID. |
belaran@999 | 11453 The changeset ID of the second parent of the working |
belaran@999 | 11454 directory. |
belaran@999 | 11455 </para> |
belaran@999 | 11456 </listitem></itemizedlist> |
belaran@999 | 11457 <para id="x_2b7">If the commit proceeds, the parents of the working |
belaran@999 | 11458 directory will become the parents of the new changeset. |
belaran@999 | 11459 </para> |
belaran@999 | 11460 |
belaran@999 | 11461 <para id="x_2b8">See also: <literal role="hook" moreinfo="none">commit</literal> |
belaran@999 | 11462 (<xref linkend="sec:hook:commit"/>), <literal role="hook" moreinfo="none">pretxncommit</literal> (<xref linkend="sec:hook:pretxncommit"/>) |
belaran@999 | 11463 </para> |
belaran@999 | 11464 </sect2> |
belaran@999 | 11465 |
belaran@999 | 11466 <sect2 id="sec:hook:preoutgoing"> |
belaran@999 | 11467 <title><literal role="hook" moreinfo="none">preoutgoing</literal>—before |
belaran@999 | 11468 starting to propagate changesets</title> |
belaran@999 | 11469 |
belaran@999 | 11470 <para id="x_2b9">This hook is invoked before Mercurial knows the identities |
belaran@999 | 11471 of the changesets to be transmitted. |
belaran@999 | 11472 </para> |
belaran@999 | 11473 |
belaran@999 | 11474 <para id="x_2ba">One use for this hook is to prevent changes from being |
belaran@999 | 11475 transmitted to another repository. |
belaran@999 | 11476 </para> |
belaran@999 | 11477 |
belaran@999 | 11478 <para id="x_2bb">Parameters to this hook: |
belaran@999 | 11479 </para> |
belaran@999 | 11480 <itemizedlist> |
belaran@999 | 11481 <listitem><para id="x_2bc"><literal moreinfo="none">source</literal>: A |
belaran@999 | 11482 string. The source of the operation that is attempting to |
belaran@999 | 11483 obtain changes from this repository (see <xref linkend="sec:hook:sources"/>). See the documentation |
belaran@999 | 11484 for the <literal moreinfo="none">source</literal> parameter to the |
belaran@999 | 11485 <literal role="hook" moreinfo="none">outgoing</literal> hook, in |
belaran@999 | 11486 <xref linkend="sec:hook:outgoing"/>, for possible values |
belaran@999 | 11487 of this parameter. |
belaran@999 | 11488 </para> |
belaran@999 | 11489 </listitem> |
belaran@999 | 11490 <listitem><para id="x_2bd"><literal moreinfo="none">url</literal>: A URL. The |
belaran@999 | 11491 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. |
belaran@999 | 11492 </para> |
belaran@999 | 11493 </listitem></itemizedlist> |
belaran@999 | 11494 |
belaran@999 | 11495 <para id="x_2be">See also: <literal role="hook" moreinfo="none">outgoing</literal> (<xref linkend="sec:hook:outgoing"/>) |
belaran@999 | 11496 </para> |
belaran@999 | 11497 </sect2> |
belaran@999 | 11498 |
belaran@999 | 11499 <sect2 id="sec:hook:pretag"> |
belaran@999 | 11500 <title><literal role="hook" moreinfo="none">pretag</literal>—before |
belaran@999 | 11501 tagging a changeset</title> |
belaran@999 | 11502 |
belaran@999 | 11503 <para id="x_2bf">This controlling hook is run before a tag is created. If |
belaran@999 | 11504 the hook succeeds, creation of the tag proceeds. If the hook |
belaran@999 | 11505 fails, the tag is not created. |
belaran@999 | 11506 </para> |
belaran@999 | 11507 |
belaran@999 | 11508 <para id="x_2c0">Parameters to this hook: |
belaran@999 | 11509 </para> |
belaran@999 | 11510 <itemizedlist> |
belaran@999 | 11511 <listitem><para id="x_2c1"><literal moreinfo="none">local</literal>: A boolean. Whether |
belaran@999 | 11512 the tag is local to this repository instance (i.e. stored |
belaran@999 | 11513 in <filename role="special" moreinfo="none">.hg/localtags</filename>) or |
belaran@999 | 11514 managed by Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>). |
belaran@999 | 11515 </para> |
belaran@999 | 11516 </listitem> |
belaran@999 | 11517 <listitem><para id="x_2c2"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11518 ID of the changeset to be tagged. |
belaran@999 | 11519 </para> |
belaran@999 | 11520 </listitem> |
belaran@999 | 11521 <listitem><para id="x_2c3"><literal moreinfo="none">tag</literal>: A string. The name of |
belaran@999 | 11522 the tag to be created. |
belaran@999 | 11523 </para> |
belaran@999 | 11524 </listitem></itemizedlist> |
belaran@999 | 11525 |
belaran@999 | 11526 <para id="x_2c4">If the tag to be created is |
belaran@999 | 11527 revision-controlled, the <literal role="hook" moreinfo="none">precommit</literal> and <literal role="hook" moreinfo="none">pretxncommit</literal> hooks (<xref linkend="sec:hook:commit"/> and <xref linkend="sec:hook:pretxncommit"/>) will also be run. |
belaran@999 | 11528 </para> |
belaran@999 | 11529 |
belaran@999 | 11530 <para id="x_2c5">See also: <literal role="hook" moreinfo="none">tag</literal> |
belaran@999 | 11531 (<xref linkend="sec:hook:tag"/>) |
belaran@999 | 11532 </para> |
belaran@999 | 11533 </sect2> |
belaran@999 | 11534 |
belaran@999 | 11535 <sect2 id="sec:hook:pretxnchangegroup"> |
belaran@999 | 11536 <title><literal role="hook" moreinfo="none">pretxnchangegroup</literal>—before |
belaran@999 | 11537 completing addition of remote changesets</title> |
belaran@999 | 11538 |
belaran@999 | 11539 <para id="x_2c6">This controlling hook is run before a |
belaran@999 | 11540 transaction—that manages the addition of a group of new |
belaran@999 | 11541 changesets from outside the repository—completes. If |
belaran@999 | 11542 the hook succeeds, the transaction completes, and all of the |
belaran@999 | 11543 changesets become permanent within this repository. If the |
belaran@999 | 11544 hook fails, the transaction is rolled back, and the data for |
belaran@999 | 11545 the changesets is erased. |
belaran@999 | 11546 </para> |
belaran@999 | 11547 |
belaran@999 | 11548 <para id="x_2c7">This hook can access the metadata associated with the |
belaran@999 | 11549 almost-added changesets, but it should not do anything |
belaran@999 | 11550 permanent with this data. It must also not modify the working |
belaran@999 | 11551 directory. |
belaran@999 | 11552 </para> |
belaran@999 | 11553 |
belaran@999 | 11554 <para id="x_2c8">While this hook is running, if other Mercurial processes |
belaran@999 | 11555 access this repository, they will be able to see the |
belaran@999 | 11556 almost-added changesets as if they are permanent. This may |
belaran@999 | 11557 lead to race conditions if you do not take steps to avoid |
belaran@999 | 11558 them. |
belaran@999 | 11559 </para> |
belaran@999 | 11560 |
belaran@999 | 11561 <para id="x_2c9">This hook can be used to automatically vet a group of |
belaran@999 | 11562 changesets. If the hook fails, all of the changesets are |
belaran@999 | 11563 <quote>rejected</quote> when the transaction rolls back. |
belaran@999 | 11564 </para> |
belaran@999 | 11565 |
belaran@999 | 11566 <para id="x_2ca">Parameters to this hook: |
belaran@999 | 11567 </para> |
belaran@999 | 11568 <itemizedlist> |
belaran@999 | 11569 <listitem><para id="x_2cb"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11570 changeset ID of the first changeset in the group that was |
belaran@999 | 11571 added. All changesets between this and |
belaran@999 | 11572 <literal role="tag" moreinfo="none">tip</literal>, |
belaran@999 | 11573 inclusive, were added by a single <command role="hg-cmd" moreinfo="none">hg pull</command>, <command role="hg-cmd" moreinfo="none">hg push</command> or <command role="hg-cmd" moreinfo="none">hg unbundle</command>. |
belaran@999 | 11574 </para> |
belaran@999 | 11575 </listitem> |
belaran@999 | 11576 <listitem><para id="x_2cc"><literal moreinfo="none">source</literal>: A |
belaran@999 | 11577 string. The source of these changes. See <xref linkend="sec:hook:sources"/> for details. |
belaran@999 | 11578 </para> |
belaran@999 | 11579 </listitem> |
belaran@999 | 11580 <listitem><para id="x_2cd"><literal moreinfo="none">url</literal>: A URL. The |
belaran@999 | 11581 location of the remote repository, if known. See <xref linkend="sec:hook:url"/> for more information. |
belaran@999 | 11582 </para> |
belaran@999 | 11583 </listitem></itemizedlist> |
belaran@999 | 11584 |
belaran@999 | 11585 <para id="x_2ce">See also: <literal role="hook" moreinfo="none">changegroup</literal> (<xref linkend="sec:hook:changegroup"/>), <literal role="hook" moreinfo="none">incoming</literal> (<xref linkend="sec:hook:incoming"/>), <literal role="hook" moreinfo="none">prechangegroup</literal> (<xref linkend="sec:hook:prechangegroup"/>) |
belaran@999 | 11586 </para> |
belaran@999 | 11587 </sect2> |
belaran@999 | 11588 |
belaran@999 | 11589 <sect2 id="sec:hook:pretxncommit"> |
belaran@999 | 11590 <title><literal role="hook" moreinfo="none">pretxncommit</literal>—before |
belaran@999 | 11591 completing commit of new changeset</title> |
belaran@999 | 11592 |
belaran@999 | 11593 <para id="x_2cf">This controlling hook is run before a |
belaran@999 | 11594 transaction—that manages a new commit—completes. |
belaran@999 | 11595 If the hook succeeds, the transaction completes and the |
belaran@999 | 11596 changeset becomes permanent within this repository. If the |
belaran@999 | 11597 hook fails, the transaction is rolled back, and the commit |
belaran@999 | 11598 data is erased. |
belaran@999 | 11599 </para> |
belaran@999 | 11600 |
belaran@999 | 11601 <para id="x_2d0">This hook can access the metadata associated with the |
belaran@999 | 11602 almost-new changeset, but it should not do anything permanent |
belaran@999 | 11603 with this data. It must also not modify the working |
belaran@999 | 11604 directory. |
belaran@999 | 11605 </para> |
belaran@999 | 11606 |
belaran@999 | 11607 <para id="x_2d1">While this hook is running, if other Mercurial processes |
belaran@999 | 11608 access this repository, they will be able to see the |
belaran@999 | 11609 almost-new changeset as if it is permanent. This may lead to |
belaran@999 | 11610 race conditions if you do not take steps to avoid them. |
belaran@999 | 11611 </para> |
belaran@999 | 11612 |
belaran@999 | 11613 <para id="x_2d2">Parameters to this hook:</para> |
belaran@999 | 11614 |
belaran@999 | 11615 <itemizedlist> |
belaran@999 | 11616 <listitem><para id="x_2d3"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11617 changeset ID of the newly committed changeset. |
belaran@999 | 11618 </para> |
belaran@999 | 11619 </listitem> |
belaran@999 | 11620 <listitem><para id="x_2d4"><literal moreinfo="none">parent1</literal>: A changeset ID. |
belaran@999 | 11621 The changeset ID of the first parent of the newly |
belaran@999 | 11622 committed changeset. |
belaran@999 | 11623 </para> |
belaran@999 | 11624 </listitem> |
belaran@999 | 11625 <listitem><para id="x_2d5"><literal moreinfo="none">parent2</literal>: A changeset ID. |
belaran@999 | 11626 The changeset ID of the second parent of the newly |
belaran@999 | 11627 committed changeset. |
belaran@999 | 11628 </para> |
belaran@999 | 11629 </listitem></itemizedlist> |
belaran@999 | 11630 |
belaran@999 | 11631 <para id="x_2d6">See also: <literal role="hook" moreinfo="none">precommit</literal> (<xref linkend="sec:hook:precommit"/>) |
belaran@999 | 11632 </para> |
belaran@999 | 11633 </sect2> |
belaran@999 | 11634 |
belaran@999 | 11635 <sect2 id="sec:hook:preupdate"> |
belaran@999 | 11636 <title><literal role="hook" moreinfo="none">preupdate</literal>—before |
belaran@999 | 11637 updating or merging working directory</title> |
belaran@999 | 11638 |
belaran@999 | 11639 <para id="x_2d7">This controlling hook is run before an update |
belaran@999 | 11640 or merge of the working directory begins. It is run only if |
belaran@999 | 11641 Mercurial's normal pre-update checks determine that the update |
belaran@999 | 11642 or merge can proceed. If the hook succeeds, the update or |
belaran@999 | 11643 merge may proceed; if it fails, the update or merge does not |
belaran@999 | 11644 start. |
belaran@999 | 11645 </para> |
belaran@999 | 11646 |
belaran@999 | 11647 <para id="x_2d8">Parameters to this hook: |
belaran@999 | 11648 </para> |
belaran@999 | 11649 <itemizedlist> |
belaran@999 | 11650 <listitem><para id="x_2d9"><literal moreinfo="none">parent1</literal>: A |
belaran@999 | 11651 changeset ID. The ID of the parent that the working |
belaran@999 | 11652 directory is to be updated to. If the working directory |
belaran@999 | 11653 is being merged, it will not change this parent. |
belaran@999 | 11654 </para> |
belaran@999 | 11655 </listitem> |
belaran@999 | 11656 <listitem><para id="x_2da"><literal moreinfo="none">parent2</literal>: A |
belaran@999 | 11657 changeset ID. Only set if the working directory is being |
belaran@999 | 11658 merged. The ID of the revision that the working directory |
belaran@999 | 11659 is being merged with. |
belaran@999 | 11660 </para> |
belaran@999 | 11661 </listitem></itemizedlist> |
belaran@999 | 11662 |
belaran@999 | 11663 <para id="x_2db">See also: <literal role="hook" moreinfo="none">update</literal> |
belaran@999 | 11664 (<xref linkend="sec:hook:update"/>)</para> |
belaran@999 | 11665 </sect2> |
belaran@999 | 11666 |
belaran@999 | 11667 <sect2 id="sec:hook:tag"> |
belaran@999 | 11668 <title><literal role="hook" moreinfo="none">tag</literal>—after tagging a |
belaran@999 | 11669 changeset</title> |
belaran@999 | 11670 |
belaran@999 | 11671 <para id="x_2dc">This hook is run after a tag has been created. |
belaran@999 | 11672 </para> |
belaran@999 | 11673 |
belaran@999 | 11674 <para id="x_2dd">Parameters to this hook: |
belaran@999 | 11675 </para> |
belaran@999 | 11676 <itemizedlist> |
belaran@999 | 11677 <listitem><para id="x_2de"><literal moreinfo="none">local</literal>: A boolean. Whether |
belaran@999 | 11678 the new tag is local to this repository instance (i.e. |
belaran@999 | 11679 stored in <filename role="special" moreinfo="none">.hg/localtags</filename>) or managed by |
belaran@999 | 11680 Mercurial (stored in <filename role="special" moreinfo="none">.hgtags</filename>). |
belaran@999 | 11681 </para> |
belaran@999 | 11682 </listitem> |
belaran@999 | 11683 <listitem><para id="x_2df"><literal moreinfo="none">node</literal>: A changeset ID. The |
belaran@999 | 11684 ID of the changeset that was tagged. |
belaran@999 | 11685 </para> |
belaran@999 | 11686 </listitem> |
belaran@999 | 11687 <listitem><para id="x_2e0"><literal moreinfo="none">tag</literal>: A string. The name of |
belaran@999 | 11688 the tag that was created. |
belaran@999 | 11689 </para> |
belaran@999 | 11690 </listitem></itemizedlist> |
belaran@999 | 11691 |
belaran@999 | 11692 <para id="x_2e1">If the created tag is revision-controlled, the <literal role="hook" moreinfo="none">commit</literal> hook (section <xref linkend="sec:hook:commit"/>) is run before this hook. |
belaran@999 | 11693 </para> |
belaran@999 | 11694 |
belaran@999 | 11695 <para id="x_2e2">See also: <literal role="hook" moreinfo="none">pretag</literal> |
belaran@999 | 11696 (<xref linkend="sec:hook:pretag"/>) |
belaran@999 | 11697 </para> |
belaran@999 | 11698 </sect2> |
belaran@999 | 11699 |
belaran@999 | 11700 <sect2 id="sec:hook:update"> |
belaran@999 | 11701 <title><literal role="hook" moreinfo="none">update</literal>—after |
belaran@999 | 11702 updating or merging working directory</title> |
belaran@999 | 11703 |
belaran@999 | 11704 <para id="x_2e3">This hook is run after an update or merge of the working |
belaran@999 | 11705 directory completes. Since a merge can fail (if the external |
belaran@999 | 11706 <command moreinfo="none">hgmerge</command> command fails to resolve conflicts |
belaran@999 | 11707 in a file), this hook communicates whether the update or merge |
belaran@999 | 11708 completed cleanly. |
belaran@999 | 11709 </para> |
belaran@999 | 11710 |
belaran@999 | 11711 <itemizedlist> |
belaran@999 | 11712 <listitem><para id="x_2e4"><literal moreinfo="none">error</literal>: A boolean. |
belaran@999 | 11713 Indicates whether the update or merge completed |
belaran@999 | 11714 successfully. |
belaran@999 | 11715 </para> |
belaran@999 | 11716 </listitem> |
belaran@999 | 11717 <listitem><para id="x_2e5"><literal moreinfo="none">parent1</literal>: A changeset ID. |
belaran@999 | 11718 The ID of the parent that the working directory was |
belaran@999 | 11719 updated to. If the working directory was merged, it will |
belaran@999 | 11720 not have changed this parent. |
belaran@999 | 11721 </para> |
belaran@999 | 11722 </listitem> |
belaran@999 | 11723 <listitem><para id="x_2e6"><literal moreinfo="none">parent2</literal>: A changeset ID. |
belaran@999 | 11724 Only set if the working directory was merged. The ID of |
belaran@999 | 11725 the revision that the working directory was merged with. |
belaran@999 | 11726 </para> |
belaran@999 | 11727 </listitem></itemizedlist> |
belaran@999 | 11728 |
belaran@999 | 11729 <para id="x_2e7">See also: <literal role="hook" moreinfo="none">preupdate</literal> |
belaran@999 | 11730 (<xref linkend="sec:hook:preupdate"/>) |
belaran@999 | 11731 </para> |
belaran@999 | 11732 |
belaran@999 | 11733 </sect2> |
belaran@999 | 11734 </sect1> |
belaran@999 | 11735 </chapter> |
belaran@999 | 11736 |
belaran@999 | 11737 <!-- |
belaran@999 | 11738 local variables: |
belaran@999 | 11739 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 11740 end: |
belaran@999 | 11741 --> |
belaran@999 | 11742 |
belaran@999 | 11743 <!-- BEGIN ch11 --> |
belaran@999 | 11744 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 11745 |
belaran@999 | 11746 <chapter id="chap:template"> |
belaran@999 | 11747 <?dbhtml filename="customizing-the-output-of-mercurial.html"?> |
belaran@999 | 11748 <title>Customizing the output of Mercurial</title> |
belaran@999 | 11749 |
belaran@999 | 11750 <para id="x_578">Mercurial provides a powerful mechanism to let you control how |
belaran@999 | 11751 it displays information. The mechanism is based on templates. |
belaran@999 | 11752 You can use templates to generate specific output for a single |
belaran@999 | 11753 command, or to customize the entire appearance of the built-in web |
belaran@999 | 11754 interface.</para> |
belaran@999 | 11755 |
belaran@999 | 11756 <sect1 id="sec:style"> |
belaran@999 | 11757 <title>Using precanned output styles</title> |
belaran@999 | 11758 |
belaran@999 | 11759 <para id="x_579">Packaged with Mercurial are some output styles that you can |
belaran@999 | 11760 use immediately. A style is simply a precanned template that |
belaran@999 | 11761 someone wrote and installed somewhere that Mercurial can |
belaran@999 | 11762 find.</para> |
belaran@999 | 11763 |
belaran@999 | 11764 <para id="x_57a">Before we take a look at Mercurial's bundled styles, let's |
belaran@999 | 11765 review its normal output.</para> |
belaran@999 | 11766 |
belaran@999 | 11767 <!-- BEGIN template.simple.normal --> |
belaran@999 | 11768 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput> |
belaran@999 | 11769 changeset: 1:e3d2468ca47c |
belaran@999 | 11770 tag: mytag |
belaran@999 | 11771 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 11772 date: Sun Aug 16 14:05:17 2009 +0000 |
belaran@999 | 11773 summary: added line to end of <<hello>> file. |
belaran@999 | 11774 |
belaran@999 | 11775 </screen> |
belaran@999 | 11776 <!-- END template.simple.normal --> |
belaran@999 | 11777 |
belaran@999 | 11778 |
belaran@999 | 11779 <para id="x_57b">This is somewhat informative, but it takes up a lot of |
belaran@999 | 11780 space—five lines of output per changeset. The |
belaran@999 | 11781 <literal moreinfo="none">compact</literal> style reduces this to three lines, |
belaran@999 | 11782 presented in a sparse manner.</para> |
belaran@999 | 11783 |
belaran@999 | 11784 <!-- BEGIN template.simple.compact --> |
belaran@999 | 11785 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style compact</userinput> |
belaran@999 | 11786 3[tip] d3cc7424d32c 2009-08-16 14:05 +0000 bos |
belaran@999 | 11787 Added tag v0.1 for changeset a5dd5392119b |
belaran@999 | 11788 |
belaran@999 | 11789 2[v0.1] a5dd5392119b 2009-08-16 14:05 +0000 bos |
belaran@999 | 11790 Added tag mytag for changeset e3d2468ca47c |
belaran@999 | 11791 |
belaran@999 | 11792 1[mytag] e3d2468ca47c 2009-08-16 14:05 +0000 bos |
belaran@999 | 11793 added line to end of <<hello>> file. |
belaran@999 | 11794 |
belaran@999 | 11795 0 1cf727e9fc61 2009-08-16 14:05 +0000 bos |
belaran@999 | 11796 added hello |
belaran@999 | 11797 |
belaran@999 | 11798 </screen> |
belaran@999 | 11799 <!-- END template.simple.compact --> |
belaran@999 | 11800 |
belaran@999 | 11801 |
belaran@999 | 11802 <para id="x_57c">The <literal moreinfo="none">changelog</literal> style hints at the |
belaran@999 | 11803 expressive power of Mercurial's templating engine. This style |
belaran@999 | 11804 attempts to follow the GNU Project's changelog |
belaran@999 | 11805 guidelines<citation>web:changelog</citation>.</para> |
belaran@999 | 11806 |
belaran@999 | 11807 <!-- BEGIN template.simple.changelog --> |
belaran@999 | 11808 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style changelog</userinput> |
belaran@999 | 11809 2009-08-16 Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 11810 |
belaran@999 | 11811 * .hgtags: |
belaran@999 | 11812 Added tag v0.1 for changeset a5dd5392119b |
belaran@999 | 11813 [d3cc7424d32c] [tip] |
belaran@999 | 11814 |
belaran@999 | 11815 * .hgtags: |
belaran@999 | 11816 Added tag mytag for changeset e3d2468ca47c |
belaran@999 | 11817 [a5dd5392119b] [v0.1] |
belaran@999 | 11818 |
belaran@999 | 11819 * goodbye, hello: |
belaran@999 | 11820 added line to end of <<hello>> file. |
belaran@999 | 11821 |
belaran@999 | 11822 in addition, added a file with the helpful name (at least i hope |
belaran@999 | 11823 that some might consider it so) of goodbye. |
belaran@999 | 11824 [e3d2468ca47c] [mytag] |
belaran@999 | 11825 |
belaran@999 | 11826 * hello: |
belaran@999 | 11827 added hello |
belaran@999 | 11828 [1cf727e9fc61] |
belaran@999 | 11829 |
belaran@999 | 11830 </screen> |
belaran@999 | 11831 <!-- END template.simple.changelog --> |
belaran@999 | 11832 |
belaran@999 | 11833 |
belaran@999 | 11834 <para id="x_57d">You will not be shocked to learn that Mercurial's default |
belaran@999 | 11835 output style is named <literal moreinfo="none">default</literal>.</para> |
belaran@999 | 11836 |
belaran@999 | 11837 <sect2> |
belaran@999 | 11838 <title>Setting a default style</title> |
belaran@999 | 11839 |
belaran@999 | 11840 <para id="x_57e">You can modify the output style that Mercurial will use |
belaran@999 | 11841 for every command by editing your <filename role="special" moreinfo="none">~/.hgrc</filename> file, naming the style |
belaran@999 | 11842 you would prefer to use.</para> |
belaran@999 | 11843 |
belaran@999 | 11844 <programlisting format="linespecific">[ui] |
belaran@999 | 11845 style = compact</programlisting> |
belaran@999 | 11846 |
belaran@999 | 11847 <para id="x_57f">If you write a style of your own, you can use it by either |
belaran@999 | 11848 providing the path to your style file, or copying your style |
belaran@999 | 11849 file into a location where Mercurial can find it (typically |
belaran@999 | 11850 the <literal moreinfo="none">templates</literal> subdirectory of your |
belaran@999 | 11851 Mercurial install directory).</para> |
belaran@999 | 11852 </sect2> |
belaran@999 | 11853 </sect1> |
belaran@999 | 11854 |
belaran@999 | 11855 <sect1> |
belaran@999 | 11856 <title>Commands that support styles and templates</title> |
belaran@999 | 11857 |
belaran@999 | 11858 <para id="x_580">All of Mercurial's |
belaran@999 | 11859 <quote><literal moreinfo="none">log</literal>-like</quote> commands let you use |
belaran@999 | 11860 styles and templates: <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 11861 incoming</command>, <command role="hg-cmd" moreinfo="none">hg log</command>, |
belaran@999 | 11862 <command role="hg-cmd" moreinfo="none">hg outgoing</command>, and <command role="hg-cmd" moreinfo="none">hg tip</command>.</para> |
belaran@999 | 11863 |
belaran@999 | 11864 <para id="x_581">As I write this manual, these are so far the only commands |
belaran@999 | 11865 that support styles and templates. Since these are the most |
belaran@999 | 11866 important commands that need customizable output, there has been |
belaran@999 | 11867 little pressure from the Mercurial user community to add style |
belaran@999 | 11868 and template support to other commands.</para> |
belaran@999 | 11869 </sect1> |
belaran@999 | 11870 |
belaran@999 | 11871 <sect1> |
belaran@999 | 11872 <title>The basics of templating</title> |
belaran@999 | 11873 |
belaran@999 | 11874 <para id="x_582">At its simplest, a Mercurial template is a piece of text. |
belaran@999 | 11875 Some of the text never changes, while other parts are |
belaran@999 | 11876 <emphasis>expanded</emphasis>, or replaced with new text, when |
belaran@999 | 11877 necessary.</para> |
belaran@999 | 11878 |
belaran@999 | 11879 <para id="x_583">Before we continue, let's look again at a simple example of |
belaran@999 | 11880 Mercurial's normal output.</para> |
belaran@999 | 11881 |
belaran@999 | 11882 <!-- BEGIN template.simple.normal --> |
belaran@999 | 11883 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1</userinput> |
belaran@999 | 11884 changeset: 1:e3d2468ca47c |
belaran@999 | 11885 tag: mytag |
belaran@999 | 11886 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 11887 date: Sun Aug 16 14:05:17 2009 +0000 |
belaran@999 | 11888 summary: added line to end of <<hello>> file. |
belaran@999 | 11889 |
belaran@999 | 11890 </screen> |
belaran@999 | 11891 <!-- END template.simple.normal --> |
belaran@999 | 11892 |
belaran@999 | 11893 |
belaran@999 | 11894 <para id="x_584">Now, let's run the same command, but using a template to |
belaran@999 | 11895 change its output.</para> |
belaran@999 | 11896 |
belaran@999 | 11897 <!-- BEGIN template.simple.simplest --> |
belaran@999 | 11898 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'i saw a changeset\n'</userinput> |
belaran@999 | 11899 i saw a changeset |
belaran@999 | 11900 </screen> |
belaran@999 | 11901 <!-- END template.simple.simplest --> |
belaran@999 | 11902 |
belaran@999 | 11903 |
belaran@999 | 11904 <para id="x_585">The example above illustrates the simplest possible |
belaran@999 | 11905 template; it's just a piece of static text, printed once for |
belaran@999 | 11906 each changeset. The <option role="hg-opt-log">--template</option> option to the <command role="hg-cmd" moreinfo="none">hg log</command> command tells Mercurial to use |
belaran@999 | 11907 the given text as the template when printing each |
belaran@999 | 11908 changeset.</para> |
belaran@999 | 11909 |
belaran@999 | 11910 <para id="x_586">Notice that the template string above ends with the text |
belaran@999 | 11911 <quote><literal moreinfo="none">\n</literal></quote>. This is an |
belaran@999 | 11912 <emphasis>escape sequence</emphasis>, telling Mercurial to print |
belaran@999 | 11913 a newline at the end of each template item. If you omit this |
belaran@999 | 11914 newline, Mercurial will run each piece of output together. See |
belaran@999 | 11915 <xref linkend="sec:template:escape"/> for more details |
belaran@999 | 11916 of escape sequences.</para> |
belaran@999 | 11917 |
belaran@999 | 11918 <para id="x_587">A template that prints a fixed string of text all the time |
belaran@999 | 11919 isn't very useful; let's try something a bit more |
belaran@999 | 11920 complex.</para> |
belaran@999 | 11921 |
belaran@999 | 11922 <!-- BEGIN template.simple.simplesub --> |
belaran@999 | 11923 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --template 'i saw a changeset: {desc}\n'</userinput> |
belaran@999 | 11924 i saw a changeset: Added tag v0.1 for changeset a5dd5392119b |
belaran@999 | 11925 i saw a changeset: Added tag mytag for changeset e3d2468ca47c |
belaran@999 | 11926 i saw a changeset: added line to end of <<hello>> file. |
belaran@999 | 11927 |
belaran@999 | 11928 in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye. |
belaran@999 | 11929 i saw a changeset: added hello |
belaran@999 | 11930 </screen> |
belaran@999 | 11931 <!-- END template.simple.simplesub --> |
belaran@999 | 11932 |
belaran@999 | 11933 |
belaran@999 | 11934 <para id="x_588">As you can see, the string |
belaran@999 | 11935 <quote><literal moreinfo="none">{desc}</literal></quote> in the template has |
belaran@999 | 11936 been replaced in the output with the description of each |
belaran@999 | 11937 changeset. Every time Mercurial finds text enclosed in curly |
belaran@999 | 11938 braces (<quote><literal moreinfo="none">{</literal></quote> and |
belaran@999 | 11939 <quote><literal moreinfo="none">}</literal></quote>), it will try to replace the |
belaran@999 | 11940 braces and text with the expansion of whatever is inside. To |
belaran@999 | 11941 print a literal curly brace, you must escape it, as described in |
belaran@999 | 11942 <xref linkend="sec:template:escape"/>.</para> |
belaran@999 | 11943 </sect1> |
belaran@999 | 11944 |
belaran@999 | 11945 <sect1 id="sec:template:keyword"> |
belaran@999 | 11946 <title>Common template keywords</title> |
belaran@999 | 11947 |
belaran@999 | 11948 <para id="x_589">You can start writing simple templates immediately using the |
belaran@999 | 11949 keywords below.</para> |
belaran@999 | 11950 |
belaran@999 | 11951 <itemizedlist> |
belaran@999 | 11952 <listitem><para id="x_58a"><literal role="template-keyword" moreinfo="none">author</literal>: String. The |
belaran@999 | 11953 unmodified author of the changeset.</para> |
belaran@999 | 11954 </listitem> |
belaran@999 | 11955 <listitem><para id="x_58b"><literal role="template-keyword" moreinfo="none">branches</literal>: String. The |
belaran@999 | 11956 name of the branch on which the changeset was committed. |
belaran@999 | 11957 Will be empty if the branch name was |
belaran@999 | 11958 <literal moreinfo="none">default</literal>.</para> |
belaran@999 | 11959 </listitem> |
belaran@999 | 11960 <listitem><para id="x_58c"><literal role="template-keyword" moreinfo="none">date</literal>: |
belaran@999 | 11961 Date information. The date when the changeset was |
belaran@999 | 11962 committed. This is <emphasis>not</emphasis> human-readable; |
belaran@999 | 11963 you must pass it through a filter that will render it |
belaran@999 | 11964 appropriately. See <xref linkend="sec:template:filter"/> for more information |
belaran@999 | 11965 on filters. The date is expressed as a pair of numbers. The |
belaran@999 | 11966 first number is a Unix UTC timestamp (seconds since January |
belaran@999 | 11967 1, 1970); the second is the offset of the committer's |
belaran@999 | 11968 timezone from UTC, in seconds.</para> |
belaran@999 | 11969 </listitem> |
belaran@999 | 11970 <listitem><para id="x_58d"><literal role="template-keyword" moreinfo="none">desc</literal>: |
belaran@999 | 11971 String. The text of the changeset description.</para> |
belaran@999 | 11972 </listitem> |
belaran@999 | 11973 <listitem><para id="x_58e"><literal role="template-keyword" moreinfo="none">files</literal>: List of strings. |
belaran@999 | 11974 All files modified, added, or removed by this |
belaran@999 | 11975 changeset.</para> |
belaran@999 | 11976 </listitem> |
belaran@999 | 11977 <listitem><para id="x_58f"><literal role="template-keyword" moreinfo="none">file_adds</literal>: List of |
belaran@999 | 11978 strings. Files added by this changeset.</para> |
belaran@999 | 11979 </listitem> |
belaran@999 | 11980 <listitem><para id="x_590"><literal role="template-keyword" moreinfo="none">file_dels</literal>: List of |
belaran@999 | 11981 strings. Files removed by this changeset.</para> |
belaran@999 | 11982 </listitem> |
belaran@999 | 11983 <listitem><para id="x_591"><literal role="template-keyword" moreinfo="none">node</literal>: |
belaran@999 | 11984 String. The changeset identification hash, as a |
belaran@999 | 11985 40-character hexadecimal string.</para> |
belaran@999 | 11986 </listitem> |
belaran@999 | 11987 <listitem><para id="x_592"><literal role="template-keyword" moreinfo="none">parents</literal>: List of |
belaran@999 | 11988 strings. The parents of the changeset.</para> |
belaran@999 | 11989 </listitem> |
belaran@999 | 11990 <listitem><para id="x_593"><literal role="template-keyword" moreinfo="none">rev</literal>: |
belaran@999 | 11991 Integer. The repository-local changeset revision |
belaran@999 | 11992 number.</para> |
belaran@999 | 11993 </listitem> |
belaran@999 | 11994 <listitem><para id="x_594"><literal role="template-keyword" moreinfo="none">tags</literal>: |
belaran@999 | 11995 List of strings. Any tags associated with the |
belaran@999 | 11996 changeset.</para> |
belaran@999 | 11997 </listitem> |
belaran@999 | 11998 </itemizedlist> |
belaran@999 | 11999 |
belaran@999 | 12000 <para id="x_595">A few simple experiments will show us what to expect when we |
belaran@999 | 12001 use these keywords; you can see the results below.</para> |
belaran@999 | 12002 |
belaran@999 | 12003 <!-- BEGIN template.simple.keywords --> |
belaran@999 | 12004 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'author: {author}\n'</userinput> |
belaran@999 | 12005 author: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 12006 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'desc:\n{desc}\n'</userinput> |
belaran@999 | 12007 desc: |
belaran@999 | 12008 added line to end of <<hello>> file. |
belaran@999 | 12009 |
belaran@999 | 12010 in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye. |
belaran@999 | 12011 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'files: {files}\n'</userinput> |
belaran@999 | 12012 files: goodbye hello |
belaran@999 | 12013 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_adds: {file_adds}\n'</userinput> |
belaran@999 | 12014 file_adds: goodbye |
belaran@999 | 12015 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'file_dels: {file_dels}\n'</userinput> |
belaran@999 | 12016 file_dels: |
belaran@999 | 12017 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'node: {node}\n'</userinput> |
belaran@999 | 12018 node: e3d2468ca47c10bdfbbb41b367a0c84509862197 |
belaran@999 | 12019 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'parents: {parents}\n'</userinput> |
belaran@999 | 12020 parents: |
belaran@999 | 12021 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'rev: {rev}\n'</userinput> |
belaran@999 | 12022 rev: 1 |
belaran@999 | 12023 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'tags: {tags}\n'</userinput> |
belaran@999 | 12024 tags: mytag |
belaran@999 | 12025 </screen> |
belaran@999 | 12026 <!-- END template.simple.keywords --> |
belaran@999 | 12027 |
belaran@999 | 12028 |
belaran@999 | 12029 <para id="x_596">As we noted above, the date keyword does not produce |
belaran@999 | 12030 human-readable output, so we must treat it specially. This |
belaran@999 | 12031 involves using a <emphasis>filter</emphasis>, about which more |
belaran@999 | 12032 in <xref linkend="sec:template:filter"/>.</para> |
belaran@999 | 12033 |
belaran@999 | 12034 <!-- BEGIN template.simple.datekeyword --> |
belaran@999 | 12035 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date}\n'</userinput> |
belaran@999 | 12036 date: 1250431517.00 |
belaran@999 | 12037 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'date: {date|isodate}\n'</userinput> |
belaran@999 | 12038 date: 2009-08-16 14:05 +0000 |
belaran@999 | 12039 </screen> |
belaran@999 | 12040 <!-- END template.simple.datekeyword --> |
belaran@999 | 12041 |
belaran@999 | 12042 </sect1> |
belaran@999 | 12043 |
belaran@999 | 12044 <sect1 id="sec:template:escape"> |
belaran@999 | 12045 <title>Escape sequences</title> |
belaran@999 | 12046 |
belaran@999 | 12047 <para id="x_597">Mercurial's templating engine recognises the most commonly |
belaran@999 | 12048 used escape sequences in strings. When it sees a backslash |
belaran@999 | 12049 (<quote><literal moreinfo="none">\</literal></quote>) character, it looks at the |
belaran@999 | 12050 following character and substitutes the two characters with a |
belaran@999 | 12051 single replacement, as described below.</para> |
belaran@999 | 12052 |
belaran@999 | 12053 <itemizedlist> |
belaran@999 | 12054 <listitem><para id="x_598"><literal moreinfo="none">\</literal>: |
belaran@999 | 12055 Backslash, <quote><literal moreinfo="none">\</literal></quote>, ASCII |
belaran@999 | 12056 134.</para> |
belaran@999 | 12057 </listitem> |
belaran@999 | 12058 <listitem><para id="x_599"><literal moreinfo="none">\n</literal>: Newline, |
belaran@999 | 12059 ASCII 12.</para> |
belaran@999 | 12060 </listitem> |
belaran@999 | 12061 <listitem><para id="x_59a"><literal moreinfo="none">\r</literal>: Carriage |
belaran@999 | 12062 return, ASCII 15.</para> |
belaran@999 | 12063 </listitem> |
belaran@999 | 12064 <listitem><para id="x_59b"><literal moreinfo="none">\t</literal>: Tab, ASCII |
belaran@999 | 12065 11.</para> |
belaran@999 | 12066 </listitem> |
belaran@999 | 12067 <listitem><para id="x_59c"><literal moreinfo="none">\v</literal>: Vertical |
belaran@999 | 12068 tab, ASCII 13.</para> |
belaran@999 | 12069 </listitem> |
belaran@999 | 12070 <listitem><para id="x_59d"><literal moreinfo="none">\{</literal>: Open curly |
belaran@999 | 12071 brace, <quote><literal moreinfo="none">{</literal></quote>, ASCII |
belaran@999 | 12072 173.</para> |
belaran@999 | 12073 </listitem> |
belaran@999 | 12074 <listitem><para id="x_59e"><literal moreinfo="none">\}</literal>: Close curly |
belaran@999 | 12075 brace, <quote><literal moreinfo="none">}</literal></quote>, ASCII |
belaran@999 | 12076 175.</para> |
belaran@999 | 12077 </listitem></itemizedlist> |
belaran@999 | 12078 |
belaran@999 | 12079 <para id="x_59f">As indicated above, if you want the expansion of a template |
belaran@999 | 12080 to contain a literal <quote><literal moreinfo="none">\</literal></quote>, |
belaran@999 | 12081 <quote><literal moreinfo="none">{</literal></quote>, or |
belaran@999 | 12082 <quote><literal moreinfo="none">{</literal></quote> character, you must escape |
belaran@999 | 12083 it.</para> |
belaran@999 | 12084 </sect1> |
belaran@999 | 12085 |
belaran@999 | 12086 <sect1 id="sec:template:filter"> |
belaran@999 | 12087 <title>Filtering keywords to change their results</title> |
belaran@999 | 12088 |
belaran@999 | 12089 <para id="x_5a0">Some of the results of template expansion are not |
belaran@999 | 12090 immediately easy to use. Mercurial lets you specify an optional |
belaran@999 | 12091 chain of <emphasis>filters</emphasis> to modify the result of |
belaran@999 | 12092 expanding a keyword. You have already seen a common filter, |
belaran@999 | 12093 <literal role="template-kw-filt-date" moreinfo="none">isodate</literal>, in |
belaran@999 | 12094 action above, to make a date readable.</para> |
belaran@999 | 12095 |
belaran@999 | 12096 <para id="x_5a1">Below is a list of the most commonly used filters that |
belaran@999 | 12097 Mercurial supports. While some filters can be applied to any |
belaran@999 | 12098 text, others can only be used in specific circumstances. The |
belaran@999 | 12099 name of each filter is followed first by an indication of where |
belaran@999 | 12100 it can be used, then a description of its effect.</para> |
belaran@999 | 12101 |
belaran@999 | 12102 <itemizedlist> |
belaran@999 | 12103 <listitem><para id="x_5a2"><literal role="template-filter" moreinfo="none">addbreaks</literal>: Any text. Add |
belaran@999 | 12104 an XHTML <quote><literal moreinfo="none"><br/></literal></quote> tag |
belaran@999 | 12105 before the end of every line except the last. For example, |
belaran@999 | 12106 <quote><literal moreinfo="none">foo\nbar</literal></quote> becomes |
belaran@999 | 12107 <quote><literal moreinfo="none">foo<br/>\nbar</literal></quote>.</para> |
belaran@999 | 12108 </listitem> |
belaran@999 | 12109 <listitem><para id="x_5a3"><literal role="template-kw-filt-date" moreinfo="none">age</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render |
belaran@999 | 12110 the age of the date, relative to the current time. Yields a |
belaran@999 | 12111 string like <quote><literal moreinfo="none">10 |
belaran@999 | 12112 minutes</literal></quote>.</para> |
belaran@999 | 12113 </listitem> |
belaran@999 | 12114 <listitem><para id="x_5a4"><literal role="template-filter" moreinfo="none">basename</literal>: Any text, but |
belaran@999 | 12115 most useful for the <literal role="template-keyword" moreinfo="none">files</literal> keyword and its |
belaran@999 | 12116 relatives. Treat the text as a path, and return the |
belaran@999 | 12117 basename. For example, |
belaran@999 | 12118 <quote><literal moreinfo="none">foo/bar/baz</literal></quote> becomes |
belaran@999 | 12119 <quote><literal moreinfo="none">baz</literal></quote>.</para> |
belaran@999 | 12120 </listitem> |
belaran@999 | 12121 <listitem><para id="x_5a5"><literal role="template-kw-filt-date" moreinfo="none">date</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render a |
belaran@999 | 12122 date in a similar format to the Unix <literal role="template-keyword" moreinfo="none">date</literal> command, but with |
belaran@999 | 12123 timezone included. Yields a string like <quote><literal moreinfo="none">Mon |
belaran@999 | 12124 Sep 04 15:13:13 2006 -0700</literal></quote>.</para> |
belaran@999 | 12125 </listitem> |
belaran@999 | 12126 <listitem><para id="x_5a6"><literal role="template-kw-filt-author" moreinfo="none">domain</literal>: Any text, |
belaran@999 | 12127 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Finds |
belaran@999 | 12128 the first string that looks like an email address, and |
belaran@999 | 12129 extract just the domain component. For example, |
belaran@999 | 12130 <quote><literal moreinfo="none">Bryan O'Sullivan |
belaran@999 | 12131 <bos@serpentine.com></literal></quote> becomes |
belaran@999 | 12132 <quote><literal moreinfo="none">serpentine.com</literal></quote>.</para> |
belaran@999 | 12133 </listitem> |
belaran@999 | 12134 <listitem><para id="x_5a7"><literal role="template-kw-filt-author" moreinfo="none">email</literal>: Any text, |
belaran@999 | 12135 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Extract |
belaran@999 | 12136 the first string that looks like an email address. For |
belaran@999 | 12137 example, <quote><literal moreinfo="none">Bryan O'Sullivan |
belaran@999 | 12138 <bos@serpentine.com></literal></quote> becomes |
belaran@999 | 12139 <quote><literal moreinfo="none">bos@serpentine.com</literal></quote>.</para> |
belaran@999 | 12140 </listitem> |
belaran@999 | 12141 <listitem><para id="x_5a8"><literal role="template-filter" moreinfo="none">escape</literal>: Any text. |
belaran@999 | 12142 Replace the special XML/XHTML characters |
belaran@999 | 12143 <quote><literal moreinfo="none">&</literal></quote>, |
belaran@999 | 12144 <quote><literal moreinfo="none"><</literal></quote> and |
belaran@999 | 12145 <quote><literal moreinfo="none">></literal></quote> with XML |
belaran@999 | 12146 entities.</para> |
belaran@999 | 12147 </listitem> |
belaran@999 | 12148 <listitem><para id="x_5a9"><literal role="template-filter" moreinfo="none">fill68</literal>: Any text. Wrap |
belaran@999 | 12149 the text to fit in 68 columns. This is useful before you |
belaran@999 | 12150 pass text through the <literal role="template-filter" moreinfo="none">tabindent</literal> filter, and |
belaran@999 | 12151 still want it to fit in an 80-column fixed-font |
belaran@999 | 12152 window.</para> |
belaran@999 | 12153 </listitem> |
belaran@999 | 12154 <listitem><para id="x_5aa"><literal role="template-filter" moreinfo="none">fill76</literal>: Any text. Wrap |
belaran@999 | 12155 the text to fit in 76 columns.</para> |
belaran@999 | 12156 </listitem> |
belaran@999 | 12157 <listitem><para id="x_5ab"><literal role="template-filter" moreinfo="none">firstline</literal>: Any text. |
belaran@999 | 12158 Yield the first line of text, without any trailing |
belaran@999 | 12159 newlines.</para> |
belaran@999 | 12160 </listitem> |
belaran@999 | 12161 <listitem><para id="x_5ac"><literal role="template-kw-filt-date" moreinfo="none">hgdate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render |
belaran@999 | 12162 the date as a pair of readable numbers. Yields a string |
belaran@999 | 12163 like <quote><literal moreinfo="none">1157407993 |
belaran@999 | 12164 25200</literal></quote>.</para> |
belaran@999 | 12165 </listitem> |
belaran@999 | 12166 <listitem><para id="x_5ad"><literal role="template-kw-filt-date" moreinfo="none">isodate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render |
belaran@999 | 12167 the date as a text string in ISO 8601 format. Yields a |
belaran@999 | 12168 string like <quote><literal moreinfo="none">2006-09-04 15:13:13 |
belaran@999 | 12169 -0700</literal></quote>.</para> |
belaran@999 | 12170 </listitem> |
belaran@999 | 12171 <listitem><para id="x_5ae"><literal role="template-filter" moreinfo="none">obfuscate</literal>: Any text, but |
belaran@999 | 12172 most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Yield |
belaran@999 | 12173 the input text rendered as a sequence of XML entities. This |
belaran@999 | 12174 helps to defeat some particularly stupid screen-scraping |
belaran@999 | 12175 email harvesting spambots.</para> |
belaran@999 | 12176 </listitem> |
belaran@999 | 12177 <listitem><para id="x_5af"><literal role="template-kw-filt-author" moreinfo="none">person</literal>: Any text, |
belaran@999 | 12178 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Yield |
belaran@999 | 12179 the text before an email address. For example, |
belaran@999 | 12180 <quote><literal moreinfo="none">Bryan O'Sullivan |
belaran@999 | 12181 <bos@serpentine.com></literal></quote> becomes |
belaran@999 | 12182 <quote><literal moreinfo="none">Bryan O'Sullivan</literal></quote>.</para> |
belaran@999 | 12183 </listitem> |
belaran@999 | 12184 <listitem><para id="x_5b0"><literal role="template-kw-filt-date" moreinfo="none">rfc822date</literal>: |
belaran@999 | 12185 <literal role="template-keyword" moreinfo="none">date</literal> keyword. |
belaran@999 | 12186 Render a date using the same format used in email headers. |
belaran@999 | 12187 Yields a string like <quote><literal moreinfo="none">Mon, 04 Sep 2006 |
belaran@999 | 12188 15:13:13 -0700</literal></quote>.</para> |
belaran@999 | 12189 </listitem> |
belaran@999 | 12190 <listitem><para id="x_5b1"><literal role="template-kw-filt-node" moreinfo="none">short</literal>: Changeset |
belaran@999 | 12191 hash. Yield the short form of a changeset hash, i.e. a |
belaran@999 | 12192 12-character hexadecimal string.</para> |
belaran@999 | 12193 </listitem> |
belaran@999 | 12194 <listitem><para id="x_5b2"><literal role="template-kw-filt-date" moreinfo="none">shortdate</literal>: <literal role="template-keyword" moreinfo="none">date</literal> keyword. Render |
belaran@999 | 12195 the year, month, and day of the date. Yields a string like |
belaran@999 | 12196 <quote><literal moreinfo="none">2006-09-04</literal></quote>.</para> |
belaran@999 | 12197 </listitem> |
belaran@999 | 12198 <listitem><para id="x_5b3"><literal role="template-filter" moreinfo="none">strip</literal>: |
belaran@999 | 12199 Any text. Strip all leading and trailing whitespace from |
belaran@999 | 12200 the string.</para> |
belaran@999 | 12201 </listitem> |
belaran@999 | 12202 <listitem><para id="x_5b4"><literal role="template-filter" moreinfo="none">tabindent</literal>: Any text. |
belaran@999 | 12203 Yield the text, with every line except the first starting |
belaran@999 | 12204 with a tab character.</para> |
belaran@999 | 12205 </listitem> |
belaran@999 | 12206 <listitem><para id="x_5b5"><literal role="template-filter" moreinfo="none">urlescape</literal>: Any text. |
belaran@999 | 12207 Escape all characters that are considered |
belaran@999 | 12208 <quote>special</quote> by URL parsers. For example, |
belaran@999 | 12209 <literal moreinfo="none">foo bar</literal> becomes |
belaran@999 | 12210 <literal moreinfo="none">foo%20bar</literal>.</para> |
belaran@999 | 12211 </listitem> |
belaran@999 | 12212 <listitem><para id="x_5b6"><literal role="template-kw-filt-author" moreinfo="none">user</literal>: Any text, |
belaran@999 | 12213 but most useful for the <literal role="template-keyword" moreinfo="none">author</literal> keyword. Return |
belaran@999 | 12214 the <quote>user</quote> portion of an email address. For |
belaran@999 | 12215 example, <quote><literal moreinfo="none">Bryan O'Sullivan |
belaran@999 | 12216 <bos@serpentine.com></literal></quote> becomes |
belaran@999 | 12217 <quote><literal moreinfo="none">bos</literal></quote>.</para> |
belaran@999 | 12218 </listitem> |
belaran@999 | 12219 </itemizedlist> |
belaran@999 | 12220 |
belaran@999 | 12221 <!-- BEGIN template.simple.manyfilters --> |
belaran@999 | 12222 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author}\n'</userinput> |
belaran@999 | 12223 Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 12224 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|domain}\n'</userinput> |
belaran@999 | 12225 serpentine.com |
belaran@999 | 12226 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|email}\n'</userinput> |
belaran@999 | 12227 bos@serpentine.com |
belaran@999 | 12228 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|obfuscate}\n' | cut -c-76</userinput> |
belaran@999 | 12229 &#66;&#114;&#121;&#97;&#110;&#32;&#79;&#39;&#83;&#117;&#108;&#108;&#105;&#11 |
belaran@999 | 12230 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|person}\n'</userinput> |
belaran@999 | 12231 Bryan O'Sullivan |
belaran@999 | 12232 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{author|user}\n'</userinput> |
belaran@999 | 12233 bos |
belaran@999 | 12234 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'</userinput> |
belaran@999 | 12235 looks almost right, but actually garbage: 1250431517.00 |
belaran@999 | 12236 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|age}\n'</userinput> |
belaran@999 | 12237 3 seconds |
belaran@999 | 12238 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|date}\n'</userinput> |
belaran@999 | 12239 Sun Aug 16 14:05:17 2009 +0000 |
belaran@999 | 12240 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|hgdate}\n'</userinput> |
belaran@999 | 12241 1250431517 0 |
belaran@999 | 12242 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|isodate}\n'</userinput> |
belaran@999 | 12243 2009-08-16 14:05 +0000 |
belaran@999 | 12244 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|rfc822date}\n'</userinput> |
belaran@999 | 12245 Sun, 16 Aug 2009 14:05:17 +0000 |
belaran@999 | 12246 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{date|shortdate}\n'</userinput> |
belaran@999 | 12247 2009-08-16 |
belaran@999 | 12248 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc}\n' | cut -c-76</userinput> |
belaran@999 | 12249 added line to end of <<hello>> file. |
belaran@999 | 12250 |
belaran@999 | 12251 in addition, added a file with the helpful name (at least i hope that some m |
belaran@999 | 12252 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76</userinput> |
belaran@999 | 12253 added line to end of <<hello>> file.<br/> |
belaran@999 | 12254 <br/> |
belaran@999 | 12255 in addition, added a file with the helpful name (at least i hope that some m |
belaran@999 | 12256 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|escape}\n' | cut -c-76</userinput> |
belaran@999 | 12257 added line to end of &lt;&lt;hello&gt;&gt; file. |
belaran@999 | 12258 |
belaran@999 | 12259 in addition, added a file with the helpful name (at least i hope that some m |
belaran@999 | 12260 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill68}\n'</userinput> |
belaran@999 | 12261 added line to end of <<hello>> file. |
belaran@999 | 12262 |
belaran@999 | 12263 in addition, added a file with the helpful name (at least i hope |
belaran@999 | 12264 that some might consider it so) of goodbye. |
belaran@999 | 12265 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|fill76}\n'</userinput> |
belaran@999 | 12266 added line to end of <<hello>> file. |
belaran@999 | 12267 |
belaran@999 | 12268 in addition, added a file with the helpful name (at least i hope that some |
belaran@999 | 12269 might consider it so) of goodbye. |
belaran@999 | 12270 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|firstline}\n'</userinput> |
belaran@999 | 12271 added line to end of <<hello>> file. |
belaran@999 | 12272 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|strip}\n' | cut -c-76</userinput> |
belaran@999 | 12273 added line to end of <<hello>> file. |
belaran@999 | 12274 |
belaran@999 | 12275 in addition, added a file with the helpful name (at least i hope that some m |
belaran@999 | 12276 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76</userinput> |
belaran@999 | 12277 added line to end of <<hello>> file. |
belaran@999 | 12278 |
belaran@999 | 12279 in addition, added a file with the helpful name (at least i hope tha |
belaran@999 | 12280 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node}\n'</userinput> |
belaran@999 | 12281 e3d2468ca47c10bdfbbb41b367a0c84509862197 |
belaran@999 | 12282 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template '{node|short}\n'</userinput> |
belaran@999 | 12283 e3d2468ca47c |
belaran@999 | 12284 </screen> |
belaran@999 | 12285 <!-- END template.simple.manyfilters --> |
belaran@999 | 12286 |
belaran@999 | 12287 |
belaran@999 | 12288 <note> |
belaran@999 | 12289 <para id="x_5b7"> If you try to apply a filter to a piece of data that it |
belaran@999 | 12290 cannot process, Mercurial will fail and print a Python |
belaran@999 | 12291 exception. For example, trying to run the output of the |
belaran@999 | 12292 <literal role="template-keyword" moreinfo="none">desc</literal> keyword into |
belaran@999 | 12293 the <literal role="template-kw-filt-date" moreinfo="none">isodate</literal> |
belaran@999 | 12294 filter is not a good idea.</para> |
belaran@999 | 12295 </note> |
belaran@999 | 12296 |
belaran@999 | 12297 <sect2> |
belaran@999 | 12298 <title>Combining filters</title> |
belaran@999 | 12299 |
belaran@999 | 12300 <para id="x_5b8">It is easy to combine filters to yield output in the form |
belaran@999 | 12301 you would like. The following chain of filters tidies up a |
belaran@999 | 12302 description, then makes sure that it fits cleanly into 68 |
belaran@999 | 12303 columns, then indents it by a further 8 characters (at least |
belaran@999 | 12304 on Unix-like systems, where a tab is conventionally 8 |
belaran@999 | 12305 characters wide).</para> |
belaran@999 | 12306 |
belaran@999 | 12307 <!-- BEGIN template.simple.combine --> |
belaran@999 | 12308 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'</userinput> |
belaran@999 | 12309 description: |
belaran@999 | 12310 added line to end of <<hello>> file. |
belaran@999 | 12311 |
belaran@999 | 12312 in addition, added a file with the helpful name (at least i hope |
belaran@999 | 12313 that some might consider it so) of goodbye. |
belaran@999 | 12314 </screen> |
belaran@999 | 12315 <!-- END template.simple.combine --> |
belaran@999 | 12316 |
belaran@999 | 12317 |
belaran@999 | 12318 <para id="x_5b9">Note the use of <quote><literal moreinfo="none">\t</literal></quote> (a |
belaran@999 | 12319 tab character) in the template to force the first line to be |
belaran@999 | 12320 indented; this is necessary since <literal role="template-keyword" moreinfo="none">tabindent</literal> indents all |
belaran@999 | 12321 lines <emphasis>except</emphasis> the first.</para> |
belaran@999 | 12322 |
belaran@999 | 12323 <para id="x_5ba">Keep in mind that the order of filters in a chain is |
belaran@999 | 12324 significant. The first filter is applied to the result of the |
belaran@999 | 12325 keyword; the second to the result of the first filter; and so |
belaran@999 | 12326 on. For example, using <literal moreinfo="none">fill68|tabindent</literal> |
belaran@999 | 12327 gives very different results from |
belaran@999 | 12328 <literal moreinfo="none">tabindent|fill68</literal>.</para> |
belaran@999 | 12329 </sect2> |
belaran@999 | 12330 </sect1> |
belaran@999 | 12331 |
belaran@999 | 12332 <sect1> |
belaran@999 | 12333 <title>From templates to styles</title> |
belaran@999 | 12334 |
belaran@999 | 12335 <para id="x_5bb">A command line template provides a quick and simple way to |
belaran@999 | 12336 format some output. Templates can become verbose, though, and |
belaran@999 | 12337 it's useful to be able to give a template a name. A style file |
belaran@999 | 12338 is a template with a name, stored in a file.</para> |
belaran@999 | 12339 |
belaran@999 | 12340 <para id="x_5bc">More than that, using a style file unlocks the power of |
belaran@999 | 12341 Mercurial's templating engine in ways that are not possible |
belaran@999 | 12342 using the command line <option role="hg-opt-log">--template</option> option.</para> |
belaran@999 | 12343 |
belaran@999 | 12344 <sect2> |
belaran@999 | 12345 <title>The simplest of style files</title> |
belaran@999 | 12346 |
belaran@999 | 12347 <para id="x_5bd">Our simple style file contains just one line:</para> |
belaran@999 | 12348 |
belaran@999 | 12349 <!-- BEGIN template.simple.rev --> |
belaran@999 | 12350 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'changeset = "rev: {rev}\n"' > rev</userinput> |
belaran@999 | 12351 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -l1 --style ./rev</userinput> |
belaran@999 | 12352 rev: 3 |
belaran@999 | 12353 </screen> |
belaran@999 | 12354 <!-- END template.simple.rev --> |
belaran@999 | 12355 |
belaran@999 | 12356 |
belaran@999 | 12357 <para id="x_5be">This tells Mercurial, <quote>if you're printing a |
belaran@999 | 12358 changeset, use the text on the right as the |
belaran@999 | 12359 template</quote>.</para> |
belaran@999 | 12360 </sect2> |
belaran@999 | 12361 |
belaran@999 | 12362 <sect2> |
belaran@999 | 12363 <title>Style file syntax</title> |
belaran@999 | 12364 |
belaran@999 | 12365 <para id="x_5bf">The syntax rules for a style file are simple.</para> |
belaran@999 | 12366 |
belaran@999 | 12367 <itemizedlist> |
belaran@999 | 12368 <listitem><para id="x_5c0">The file is processed one line at a |
belaran@999 | 12369 time.</para> |
belaran@999 | 12370 </listitem> |
belaran@999 | 12371 <listitem><para id="x_5c1">Leading and trailing white space are |
belaran@999 | 12372 ignored.</para> |
belaran@999 | 12373 </listitem> |
belaran@999 | 12374 <listitem><para id="x_5c2">Empty lines are skipped.</para> |
belaran@999 | 12375 </listitem> |
belaran@999 | 12376 <listitem><para id="x_5c3">If a line starts with either of the characters |
belaran@999 | 12377 <quote><literal moreinfo="none">#</literal></quote> or |
belaran@999 | 12378 <quote><literal moreinfo="none">;</literal></quote>, the entire line is |
belaran@999 | 12379 treated as a comment, and skipped as if empty.</para> |
belaran@999 | 12380 </listitem> |
belaran@999 | 12381 <listitem><para id="x_5c4">A line starts with a keyword. This must start |
belaran@999 | 12382 with an alphabetic character or underscore, and can |
belaran@999 | 12383 subsequently contain any alphanumeric character or |
belaran@999 | 12384 underscore. (In regexp notation, a keyword must match |
belaran@999 | 12385 <literal moreinfo="none">[A-Za-z_][A-Za-z0-9_]*</literal>.)</para> |
belaran@999 | 12386 </listitem> |
belaran@999 | 12387 <listitem><para id="x_5c5">The next element must be an |
belaran@999 | 12388 <quote><literal moreinfo="none">=</literal></quote> character, which can |
belaran@999 | 12389 be preceded or followed by an arbitrary amount of white |
belaran@999 | 12390 space.</para> |
belaran@999 | 12391 </listitem> |
belaran@999 | 12392 <listitem><para id="x_5c6">If the rest of the line starts and ends with |
belaran@999 | 12393 matching quote characters (either single or double quote), |
belaran@999 | 12394 it is treated as a template body.</para> |
belaran@999 | 12395 </listitem> |
belaran@999 | 12396 <listitem><para id="x_5c7">If the rest of the line <emphasis>does |
belaran@999 | 12397 not</emphasis> start with a quote character, it is |
belaran@999 | 12398 treated as the name of a file; the contents of this file |
belaran@999 | 12399 will be read and used as a template body.</para> |
belaran@999 | 12400 </listitem></itemizedlist> |
belaran@999 | 12401 </sect2> |
belaran@999 | 12402 </sect1> |
belaran@999 | 12403 |
belaran@999 | 12404 <sect1> |
belaran@999 | 12405 <title>Style files by example</title> |
belaran@999 | 12406 |
belaran@999 | 12407 <para id="x_5c8">To illustrate how to write a style file, we will construct a |
belaran@999 | 12408 few by example. Rather than provide a complete style file and |
belaran@999 | 12409 walk through it, we'll mirror the usual process of developing a |
belaran@999 | 12410 style file by starting with something very simple, and walking |
belaran@999 | 12411 through a series of successively more complete examples.</para> |
belaran@999 | 12412 |
belaran@999 | 12413 <sect2> |
belaran@999 | 12414 <title>Identifying mistakes in style files</title> |
belaran@999 | 12415 |
belaran@999 | 12416 <para id="x_5c9">If Mercurial encounters a problem in a style file you are |
belaran@999 | 12417 working on, it prints a terse error message that, once you |
belaran@999 | 12418 figure out what it means, is actually quite useful.</para> |
belaran@999 | 12419 |
belaran@999 | 12420 <!-- BEGIN template.svnstyle.syntax.input --> |
belaran@999 | 12421 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat broken.style</userinput> |
belaran@999 | 12422 changeset = |
belaran@999 | 12423 </screen> |
belaran@999 | 12424 <!-- END template.svnstyle.syntax.input --> |
belaran@999 | 12425 |
belaran@999 | 12426 |
belaran@999 | 12427 <para id="x_5ca">Notice that <filename moreinfo="none">broken.style</filename> attempts to |
belaran@999 | 12428 define a <literal moreinfo="none">changeset</literal> keyword, but forgets to |
belaran@999 | 12429 give any content for it. When instructed to use this style |
belaran@999 | 12430 file, Mercurial promptly complains.</para> |
belaran@999 | 12431 |
belaran@999 | 12432 <!-- BEGIN template.svnstyle.syntax.error --> |
belaran@999 | 12433 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r1 --style broken.style</userinput> |
belaran@999 | 12434 abort: broken.style:1: parse error |
belaran@999 | 12435 </screen> |
belaran@999 | 12436 <!-- END template.svnstyle.syntax.error --> |
belaran@999 | 12437 |
belaran@999 | 12438 |
belaran@999 | 12439 <para id="x_5cb">This error message looks intimidating, but it is not too |
belaran@999 | 12440 hard to follow.</para> |
belaran@999 | 12441 |
belaran@999 | 12442 <itemizedlist> |
belaran@999 | 12443 <listitem><para id="x_5cc">The first component is simply Mercurial's way |
belaran@999 | 12444 of saying <quote>I am giving up</quote>.</para> |
belaran@999 | 12445 <programlisting format="linespecific">___abort___: broken.style:1: parse error</programlisting> |
belaran@999 | 12446 </listitem> |
belaran@999 | 12447 <listitem><para id="x_5cd">Next comes the name of the style file that |
belaran@999 | 12448 contains the error.</para> |
belaran@999 | 12449 <programlisting format="linespecific">abort: ___broken.style___:1: parse error</programlisting> |
belaran@999 | 12450 </listitem> |
belaran@999 | 12451 <listitem><para id="x_5ce">Following the file name is the line number |
belaran@999 | 12452 where the error was encountered.</para> |
belaran@999 | 12453 <programlisting format="linespecific">abort: broken.style:___1___: parse error</programlisting> |
belaran@999 | 12454 </listitem> |
belaran@999 | 12455 <listitem><para id="x_5cf">Finally, a description of what went |
belaran@999 | 12456 wrong.</para> |
belaran@999 | 12457 <programlisting format="linespecific">abort: broken.style:1: ___parse error___</programlisting> |
belaran@999 | 12458 </listitem> |
belaran@999 | 12459 <listitem><para id="x_5d0">The description of the problem is not always |
belaran@999 | 12460 clear (as in this case), but even when it is cryptic, it |
belaran@999 | 12461 is almost always trivial to visually inspect the offending |
belaran@999 | 12462 line in the style file and see what is wrong.</para> |
belaran@999 | 12463 </listitem> |
belaran@999 | 12464 </itemizedlist> |
belaran@999 | 12465 </sect2> |
belaran@999 | 12466 |
belaran@999 | 12467 <sect2> |
belaran@999 | 12468 <title>Uniquely identifying a repository</title> |
belaran@999 | 12469 |
belaran@999 | 12470 <para id="x_5d1">If you would like to be able to identify a Mercurial |
belaran@999 | 12471 repository <quote>fairly uniquely</quote> using a short string |
belaran@999 | 12472 as an identifier, you can use the first revision in the |
belaran@999 | 12473 repository.</para> |
belaran@999 | 12474 |
belaran@999 | 12475 <!-- BEGIN template.svnstyle.id --> |
belaran@999 | 12476 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r0 --template '{node}'</userinput> |
belaran@999 | 12477 02b4f9d8a52a6da645e20fa7df0accc8aa33b650</screen> |
belaran@999 | 12478 <!-- END template.svnstyle.id --> |
belaran@999 | 12479 |
belaran@999 | 12480 |
belaran@999 | 12481 <para id="x_5d2">This is likely to be unique, and so it is |
belaran@999 | 12482 useful in many cases. There are a few caveats.</para> |
belaran@999 | 12483 <itemizedlist> |
belaran@999 | 12484 <listitem><para id="x_5d3">It will not work in a completely empty |
belaran@999 | 12485 repository, because such a repository does not have a |
belaran@999 | 12486 revision zero.</para> |
belaran@999 | 12487 </listitem> |
belaran@999 | 12488 <listitem><para id="x_5d4">Neither will it work in the (extremely rare) |
belaran@999 | 12489 case where a repository is a merge of two or more formerly |
belaran@999 | 12490 independent repositories, and you still have those |
belaran@999 | 12491 repositories around.</para> |
belaran@999 | 12492 </listitem></itemizedlist> |
belaran@999 | 12493 <para id="x_5d5">Here are some uses to which you could put this |
belaran@999 | 12494 identifier:</para> |
belaran@999 | 12495 <itemizedlist> |
belaran@999 | 12496 <listitem><para id="x_5d6">As a key into a table for a database that |
belaran@999 | 12497 manages repositories on a server.</para> |
belaran@999 | 12498 </listitem> |
belaran@999 | 12499 <listitem><para id="x_5d7">As half of a {<emphasis>repository |
belaran@999 | 12500 ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. |
belaran@999 | 12501 Save this information away when you run an automated build |
belaran@999 | 12502 or other activity, so that you can <quote>replay</quote> |
belaran@999 | 12503 the build later if necessary.</para> |
belaran@999 | 12504 </listitem> |
belaran@999 | 12505 </itemizedlist> |
belaran@999 | 12506 </sect2> |
belaran@999 | 12507 |
belaran@999 | 12508 <sect2> |
belaran@999 | 12509 <title>Listing files on multiple lines</title> |
belaran@999 | 12510 |
belaran@999 | 12511 <para id="x_714">Suppose we want to list the files changed by a changeset, |
belaran@999 | 12512 one per line, with a little indentation before each file |
belaran@999 | 12513 name.</para> |
belaran@999 | 12514 |
belaran@999 | 12515 <!-- BEGIN ch10/multiline.go --> |
belaran@999 | 12516 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat > multiline << EOF</userinput> |
belaran@999 | 12517 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">changeset = "Changed in {node|short}:\n{files}"</userinput> |
belaran@999 | 12518 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">file = " {file}\n"</userinput> |
belaran@999 | 12519 <prompt moreinfo="none">></prompt> <userinput moreinfo="none">EOF</userinput> |
belaran@999 | 12520 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style multiline</userinput> |
belaran@999 | 12521 Changed in badb58085712: |
belaran@999 | 12522 .bashrc |
belaran@999 | 12523 .hgrc |
belaran@999 | 12524 test.c |
belaran@999 | 12525 </screen> |
belaran@999 | 12526 <!-- END ch10/multiline.go --> |
belaran@999 | 12527 |
belaran@999 | 12528 </sect2> |
belaran@999 | 12529 |
belaran@999 | 12530 <sect2> |
belaran@999 | 12531 <title>Mimicking Subversion's output</title> |
belaran@999 | 12532 |
belaran@999 | 12533 <para id="x_5d8">Let's try to emulate the default output format used by |
belaran@999 | 12534 another revision control tool, Subversion.</para> |
belaran@999 | 12535 |
belaran@999 | 12536 <!-- BEGIN template.svnstyle.short --> |
belaran@999 | 12537 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svn log -r9653</userinput> |
belaran@999 | 12538 ------------------------------------------------------------------------ |
belaran@999 | 12539 r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines |
belaran@999 | 12540 |
belaran@999 | 12541 On reporting a route error, also include the status for the error, |
belaran@999 | 12542 rather than indicating a status of 0 when an error has occurred. |
belaran@999 | 12543 |
belaran@999 | 12544 Signed-off-by: Sean Hefty <sean.hefty@intel.com> |
belaran@999 | 12545 |
belaran@999 | 12546 ------------------------------------------------------------------------ |
belaran@999 | 12547 </screen> |
belaran@999 | 12548 <!-- END template.svnstyle.short --> |
belaran@999 | 12549 |
belaran@999 | 12550 |
belaran@999 | 12551 <para id="x_5d9">Since Subversion's output style is fairly simple, it is |
belaran@999 | 12552 easy to copy-and-paste a hunk of its output into a file, and |
belaran@999 | 12553 replace the text produced above by Subversion with the |
belaran@999 | 12554 template values we'd like to see expanded.</para> |
belaran@999 | 12555 |
belaran@999 | 12556 <!-- BEGIN template.svnstyle.template --> |
belaran@999 | 12557 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.template</userinput> |
belaran@999 | 12558 r{rev} | {author|user} | {date|isodate} ({date|rfc822date}) |
belaran@999 | 12559 |
belaran@999 | 12560 {desc|strip|fill76} |
belaran@999 | 12561 |
belaran@999 | 12562 ------------------------------------------------------------------------ |
belaran@999 | 12563 </screen> |
belaran@999 | 12564 <!-- END template.svnstyle.template --> |
belaran@999 | 12565 |
belaran@999 | 12566 |
belaran@999 | 12567 <para id="x_5da">There are a few small ways in which this template deviates |
belaran@999 | 12568 from the output produced by Subversion.</para> |
belaran@999 | 12569 <itemizedlist> |
belaran@999 | 12570 <listitem><para id="x_5db">Subversion prints a <quote>readable</quote> |
belaran@999 | 12571 date (the <quote><literal moreinfo="none">Wed, 27 Sep 2006</literal></quote> in the |
belaran@999 | 12572 example output above) in parentheses. Mercurial's |
belaran@999 | 12573 templating engine does not provide a way to display a date |
belaran@999 | 12574 in this format without also printing the time and time |
belaran@999 | 12575 zone.</para> |
belaran@999 | 12576 </listitem> |
belaran@999 | 12577 <listitem><para id="x_5dc">We emulate Subversion's printing of |
belaran@999 | 12578 <quote>separator</quote> lines full of |
belaran@999 | 12579 <quote><literal moreinfo="none">-</literal></quote> characters by ending |
belaran@999 | 12580 the template with such a line. We use the templating |
belaran@999 | 12581 engine's <literal role="template-keyword" moreinfo="none">header</literal> |
belaran@999 | 12582 keyword to print a separator line as the first line of |
belaran@999 | 12583 output (see below), thus achieving similar output to |
belaran@999 | 12584 Subversion.</para> |
belaran@999 | 12585 </listitem> |
belaran@999 | 12586 <listitem><para id="x_5dd">Subversion's output includes a count in the |
belaran@999 | 12587 header of the number of lines in the commit message. We |
belaran@999 | 12588 cannot replicate this in Mercurial; the templating engine |
belaran@999 | 12589 does not currently provide a filter that counts the number |
belaran@999 | 12590 of lines the template generates.</para> |
belaran@999 | 12591 </listitem></itemizedlist> |
belaran@999 | 12592 <para id="x_5de">It took me no more than a minute or two of work to replace |
belaran@999 | 12593 literal text from an example of Subversion's output with some |
belaran@999 | 12594 keywords and filters to give the template above. The style |
belaran@999 | 12595 file simply refers to the template.</para> |
belaran@999 | 12596 |
belaran@999 | 12597 <!-- BEGIN template.svnstyle.style --> |
belaran@999 | 12598 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat svn.style</userinput> |
belaran@999 | 12599 header = '------------------------------------------------------------------------\n\n' |
belaran@999 | 12600 changeset = svn.template |
belaran@999 | 12601 </screen> |
belaran@999 | 12602 <!-- END template.svnstyle.style --> |
belaran@999 | 12603 |
belaran@999 | 12604 |
belaran@999 | 12605 <para id="x_5df">We could have included the text of the template file |
belaran@999 | 12606 directly in the style file by enclosing it in quotes and |
belaran@999 | 12607 replacing the newlines with |
belaran@999 | 12608 <quote><literal moreinfo="none">\n</literal></quote> sequences, but it would |
belaran@999 | 12609 have made the style file too difficult to read. Readability |
belaran@999 | 12610 is a good guide when you're trying to decide whether some text |
belaran@999 | 12611 belongs in a style file, or in a template file that the style |
belaran@999 | 12612 file points to. If the style file will look too big or |
belaran@999 | 12613 cluttered if you insert a literal piece of text, drop it into |
belaran@999 | 12614 a template instead.</para> |
belaran@999 | 12615 </sect2> |
belaran@999 | 12616 </sect1> |
belaran@999 | 12617 </chapter> |
belaran@999 | 12618 |
belaran@999 | 12619 <!-- |
belaran@999 | 12620 local variables: |
belaran@999 | 12621 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 12622 end: |
belaran@999 | 12623 --> |
belaran@999 | 12624 |
belaran@999 | 12625 <!-- BEGIN ch12 --> |
belaran@999 | 12626 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 12627 |
belaran@999 | 12628 <chapter id="chap:mq"> |
belaran@999 | 12629 <?dbhtml filename="managing-change-with-mercurial-queues.html"?> |
belaran@999 | 12630 <title>Managing change with Mercurial Queues</title> |
belaran@999 | 12631 |
belaran@999 | 12632 <sect1 id="sec:mq:patch-mgmt"> |
belaran@999 | 12633 <title>The patch management problem</title> |
belaran@999 | 12634 |
belaran@999 | 12635 <para id="x_3ac">Here is a common scenario: you need to install a software |
belaran@999 | 12636 package from source, but you find a bug that you must fix in the |
belaran@999 | 12637 source before you can start using the package. You make your |
belaran@999 | 12638 changes, forget about the package for a while, and a few months |
belaran@999 | 12639 later you need to upgrade to a newer version of the package. If |
belaran@999 | 12640 the newer version of the package still has the bug, you must |
belaran@999 | 12641 extract your fix from the older source tree and apply it against |
belaran@999 | 12642 the newer version. This is a tedious task, and it's easy to |
belaran@999 | 12643 make mistakes.</para> |
belaran@999 | 12644 |
belaran@999 | 12645 <para id="x_3ad">This is a simple case of the <quote>patch management</quote> |
belaran@999 | 12646 problem. You have an <quote>upstream</quote> source tree that |
belaran@999 | 12647 you can't change; you need to make some local changes on top of |
belaran@999 | 12648 the upstream tree; and you'd like to be able to keep those |
belaran@999 | 12649 changes separate, so that you can apply them to newer versions |
belaran@999 | 12650 of the upstream source.</para> |
belaran@999 | 12651 |
belaran@999 | 12652 <para id="x_3ae">The patch management problem arises in many situations. |
belaran@999 | 12653 Probably the most visible is that a user of an open source |
belaran@999 | 12654 software project will contribute a bug fix or new feature to the |
belaran@999 | 12655 project's maintainers in the form of a patch.</para> |
belaran@999 | 12656 |
belaran@999 | 12657 <para id="x_3af">Distributors of operating systems that include open source |
belaran@999 | 12658 software often need to make changes to the packages they |
belaran@999 | 12659 distribute so that they will build properly in their |
belaran@999 | 12660 environments.</para> |
belaran@999 | 12661 |
belaran@999 | 12662 <para id="x_3b0">When you have few changes to maintain, it is easy to manage |
belaran@999 | 12663 a single patch using the standard <command moreinfo="none">diff</command> and |
belaran@999 | 12664 <command moreinfo="none">patch</command> programs (see <xref linkend="sec:mq:patch"/> for a discussion of these |
belaran@999 | 12665 tools). Once the number of changes grows, it starts to make |
belaran@999 | 12666 sense to maintain patches as discrete <quote>chunks of |
belaran@999 | 12667 work,</quote> so that for example a single patch will contain |
belaran@999 | 12668 only one bug fix (the patch might modify several files, but it's |
belaran@999 | 12669 doing <quote>only one thing</quote>), and you may have a number |
belaran@999 | 12670 of such patches for different bugs you need fixed and local |
belaran@999 | 12671 changes you require. In this situation, if you submit a bug fix |
belaran@999 | 12672 patch to the upstream maintainers of a package and they include |
belaran@999 | 12673 your fix in a subsequent release, you can simply drop that |
belaran@999 | 12674 single patch when you're updating to the newer release.</para> |
belaran@999 | 12675 |
belaran@999 | 12676 <para id="x_3b1">Maintaining a single patch against an upstream tree is a |
belaran@999 | 12677 little tedious and error-prone, but not difficult. However, the |
belaran@999 | 12678 complexity of the problem grows rapidly as the number of patches |
belaran@999 | 12679 you have to maintain increases. With more than a tiny number of |
belaran@999 | 12680 patches in hand, understanding which ones you have applied and |
belaran@999 | 12681 maintaining them moves from messy to overwhelming.</para> |
belaran@999 | 12682 |
belaran@999 | 12683 <para id="x_3b2">Fortunately, Mercurial includes a powerful extension, |
belaran@999 | 12684 Mercurial Queues (or simply <quote>MQ</quote>), that massively |
belaran@999 | 12685 simplifies the patch management problem.</para> |
belaran@999 | 12686 |
belaran@999 | 12687 </sect1> |
belaran@999 | 12688 <sect1 id="sec:mq:history"> |
belaran@999 | 12689 <title>The prehistory of Mercurial Queues</title> |
belaran@999 | 12690 |
belaran@999 | 12691 <para id="x_3b3">During the late 1990s, several Linux kernel developers |
belaran@999 | 12692 started to maintain <quote>patch series</quote> that modified |
belaran@999 | 12693 the behavior of the Linux kernel. Some of these series were |
belaran@999 | 12694 focused on stability, some on feature coverage, and others were |
belaran@999 | 12695 more speculative.</para> |
belaran@999 | 12696 |
belaran@999 | 12697 <para id="x_3b4">The sizes of these patch series grew rapidly. In 2002, |
belaran@999 | 12698 Andrew Morton published some shell scripts he had been using to |
belaran@999 | 12699 automate the task of managing his patch queues. Andrew was |
belaran@999 | 12700 successfully using these scripts to manage hundreds (sometimes |
belaran@999 | 12701 thousands) of patches on top of the Linux kernel.</para> |
belaran@999 | 12702 |
belaran@999 | 12703 <sect2 id="sec:mq:quilt"> |
belaran@999 | 12704 <title>A patchwork quilt</title> |
belaran@999 | 12705 |
belaran@999 | 12706 <para id="x_3b5">In early 2003, Andreas Gruenbacher and Martin Quinson |
belaran@999 | 12707 borrowed the approach of Andrew's scripts and published a tool |
belaran@999 | 12708 called <quote>patchwork quilt</quote> |
belaran@999 | 12709 <citation>web:quilt</citation>, or simply <quote>quilt</quote> |
belaran@999 | 12710 (see <citation>gruenbacher:2005</citation> for a paper |
belaran@999 | 12711 describing it). Because quilt substantially automated patch |
belaran@999 | 12712 management, it rapidly gained a large following among open |
belaran@999 | 12713 source software developers.</para> |
belaran@999 | 12714 |
belaran@999 | 12715 <para id="x_3b6">Quilt manages a <emphasis>stack of patches</emphasis> on |
belaran@999 | 12716 top of a directory tree. To begin, you tell quilt to manage a |
belaran@999 | 12717 directory tree, and tell it which files you want to manage; it |
belaran@999 | 12718 stores away the names and contents of those files. To fix a |
belaran@999 | 12719 bug, you create a new patch (using a single command), edit the |
belaran@999 | 12720 files you need to fix, then <quote>refresh</quote> the |
belaran@999 | 12721 patch.</para> |
belaran@999 | 12722 |
belaran@999 | 12723 <para id="x_3b7">The refresh step causes quilt to scan the directory tree; |
belaran@999 | 12724 it updates the patch with all of the changes you have made. |
belaran@999 | 12725 You can create another patch on top of the first, which will |
belaran@999 | 12726 track the changes required to modify the tree from <quote>tree |
belaran@999 | 12727 with one patch applied</quote> to <quote>tree with two |
belaran@999 | 12728 patches applied</quote>.</para> |
belaran@999 | 12729 |
belaran@999 | 12730 <para id="x_3b8">You can <emphasis>change</emphasis> which patches are |
belaran@999 | 12731 applied to the tree. If you <quote>pop</quote> a patch, the |
belaran@999 | 12732 changes made by that patch will vanish from the directory |
belaran@999 | 12733 tree. Quilt remembers which patches you have popped, though, |
belaran@999 | 12734 so you can <quote>push</quote> a popped patch again, and the |
belaran@999 | 12735 directory tree will be restored to contain the modifications |
belaran@999 | 12736 in the patch. Most importantly, you can run the |
belaran@999 | 12737 <quote>refresh</quote> command at any time, and the topmost |
belaran@999 | 12738 applied patch will be updated. This means that you can, at |
belaran@999 | 12739 any time, change both which patches are applied and what |
belaran@999 | 12740 modifications those patches make.</para> |
belaran@999 | 12741 |
belaran@999 | 12742 <para id="x_3b9">Quilt knows nothing about revision control tools, so it |
belaran@999 | 12743 works equally well on top of an unpacked tarball or a |
belaran@999 | 12744 Subversion working copy.</para> |
belaran@999 | 12745 </sect2> |
belaran@999 | 12746 |
belaran@999 | 12747 <sect2 id="sec:mq:quilt-mq"> |
belaran@999 | 12748 <title>From patchwork quilt to Mercurial Queues</title> |
belaran@999 | 12749 |
belaran@999 | 12750 <para id="x_3ba">In mid-2005, Chris Mason took the features of quilt and |
belaran@999 | 12751 wrote an extension that he called Mercurial Queues, which |
belaran@999 | 12752 added quilt-like behavior to Mercurial.</para> |
belaran@999 | 12753 |
belaran@999 | 12754 <para id="x_3bb">The key difference between quilt and MQ is that quilt |
belaran@999 | 12755 knows nothing about revision control systems, while MQ is |
belaran@999 | 12756 <emphasis>integrated</emphasis> into Mercurial. Each patch |
belaran@999 | 12757 that you push is represented as a Mercurial changeset. Pop a |
belaran@999 | 12758 patch, and the changeset goes away.</para> |
belaran@999 | 12759 |
belaran@999 | 12760 <para id="x_3bc">Because quilt does not care about revision control tools, |
belaran@999 | 12761 it is still a tremendously useful piece of software to know |
belaran@999 | 12762 about for situations where you cannot use Mercurial and |
belaran@999 | 12763 MQ.</para> |
belaran@999 | 12764 |
belaran@999 | 12765 </sect2> |
belaran@999 | 12766 </sect1> |
belaran@999 | 12767 <sect1> |
belaran@999 | 12768 <title>The huge advantage of MQ</title> |
belaran@999 | 12769 |
belaran@999 | 12770 <para id="x_3bd">I cannot overstate the value that MQ offers through the |
belaran@999 | 12771 unification of patches and revision control.</para> |
belaran@999 | 12772 |
belaran@999 | 12773 <para id="x_3be">A major reason that patches have persisted in the free |
belaran@999 | 12774 software and open source world—in spite of the |
belaran@999 | 12775 availability of increasingly capable revision control tools over |
belaran@999 | 12776 the years—is the <emphasis>agility</emphasis> they |
belaran@999 | 12777 offer.</para> |
belaran@999 | 12778 |
belaran@999 | 12779 <para id="x_3bf">Traditional revision control tools make a permanent, |
belaran@999 | 12780 irreversible record of everything that you do. While this has |
belaran@999 | 12781 great value, it's also somewhat stifling. If you want to |
belaran@999 | 12782 perform a wild-eyed experiment, you have to be careful in how |
belaran@999 | 12783 you go about it, or you risk leaving unneeded—or worse, |
belaran@999 | 12784 misleading or destabilising—traces of your missteps and |
belaran@999 | 12785 errors in the permanent revision record.</para> |
belaran@999 | 12786 |
belaran@999 | 12787 <para id="x_3c0">By contrast, MQ's marriage of distributed revision control |
belaran@999 | 12788 with patches makes it much easier to isolate your work. Your |
belaran@999 | 12789 patches live on top of normal revision history, and you can make |
belaran@999 | 12790 them disappear or reappear at will. If you don't like a patch, |
belaran@999 | 12791 you can drop it. If a patch isn't quite as you want it to be, |
belaran@999 | 12792 simply fix it—as many times as you need to, until you |
belaran@999 | 12793 have refined it into the form you desire.</para> |
belaran@999 | 12794 |
belaran@999 | 12795 <para id="x_3c1">As an example, the integration of patches with revision |
belaran@999 | 12796 control makes understanding patches and debugging their |
belaran@999 | 12797 effects—and their interplay with the code they're based |
belaran@999 | 12798 on—<emphasis>enormously</emphasis> easier. Since every |
belaran@999 | 12799 applied patch has an associated changeset, you can give <command role="hg-cmd" moreinfo="none">hg log</command> a file name to see which |
belaran@999 | 12800 changesets and patches affected the file. You can use the |
belaran@999 | 12801 <command role="hg-cmd" moreinfo="none">hg bisect</command> command to |
belaran@999 | 12802 binary-search through all changesets and applied patches to see |
belaran@999 | 12803 where a bug got introduced or fixed. You can use the <command role="hg-cmd" moreinfo="none">hg annotate</command> command to see which |
belaran@999 | 12804 changeset or patch modified a particular line of a source file. |
belaran@999 | 12805 And so on.</para> |
belaran@999 | 12806 </sect1> |
belaran@999 | 12807 |
belaran@999 | 12808 <sect1 id="sec:mq:patch"> |
belaran@999 | 12809 <title>Understanding patches</title> |
belaran@999 | 12810 |
belaran@999 | 12811 <para id="x_3c2">Because MQ doesn't hide its patch-oriented nature, it is |
belaran@999 | 12812 helpful to understand what patches are, and a little about the |
belaran@999 | 12813 tools that work with them.</para> |
belaran@999 | 12814 |
belaran@999 | 12815 <para id="x_3c3">The traditional Unix <command moreinfo="none">diff</command> command |
belaran@999 | 12816 compares two files, and prints a list of differences between |
belaran@999 | 12817 them. The <command moreinfo="none">patch</command> command understands these |
belaran@999 | 12818 differences as <emphasis>modifications</emphasis> to make to a |
belaran@999 | 12819 file. Take a look below for a simple example of these commands |
belaran@999 | 12820 in action.</para> |
belaran@999 | 12821 |
belaran@999 | 12822 <!-- BEGIN mq.dodiff.diff --> |
belaran@999 | 12823 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'this is my original thought' > oldfile</userinput> |
belaran@999 | 12824 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'i have changed my mind' > newfile</userinput> |
belaran@999 | 12825 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diff -u oldfile newfile > tiny.patch</userinput> |
belaran@999 | 12826 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat tiny.patch</userinput> |
belaran@999 | 12827 --- oldfile 2009-08-16 14:05:06.000000000 +0000 |
belaran@999 | 12828 +++ newfile 2009-08-16 14:05:06.000000000 +0000 |
belaran@999 | 12829 @@ -1 +1 @@ |
belaran@999 | 12830 -this is my original thought |
belaran@999 | 12831 +i have changed my mind |
belaran@999 | 12832 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">patch < tiny.patch</userinput> |
belaran@999 | 12833 patching file oldfile |
belaran@999 | 12834 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat oldfile</userinput> |
belaran@999 | 12835 i have changed my mind |
belaran@999 | 12836 </screen> |
belaran@999 | 12837 <!-- END mq.dodiff.diff --> |
belaran@999 | 12838 |
belaran@999 | 12839 |
belaran@999 | 12840 <para id="x_3c4">The type of file that <command moreinfo="none">diff</command> generates (and |
belaran@999 | 12841 <command moreinfo="none">patch</command> takes as input) is called a |
belaran@999 | 12842 <quote>patch</quote> or a <quote>diff</quote>; there is no |
belaran@999 | 12843 difference between a patch and a diff. (We'll use the term |
belaran@999 | 12844 <quote>patch</quote>, since it's more commonly used.)</para> |
belaran@999 | 12845 |
belaran@999 | 12846 <para id="x_3c5">A patch file can start with arbitrary text; the |
belaran@999 | 12847 <command moreinfo="none">patch</command> command ignores this text, but MQ uses |
belaran@999 | 12848 it as the commit message when creating changesets. To find the |
belaran@999 | 12849 beginning of the patch content, <command moreinfo="none">patch</command> |
belaran@999 | 12850 searches for the first line that starts with the string |
belaran@999 | 12851 <quote><literal moreinfo="none">diff -</literal></quote>.</para> |
belaran@999 | 12852 |
belaran@999 | 12853 <para id="x_3c6">MQ works with <emphasis>unified</emphasis> diffs |
belaran@999 | 12854 (<command moreinfo="none">patch</command> can accept several other diff formats, |
belaran@999 | 12855 but MQ doesn't). A unified diff contains two kinds of header. |
belaran@999 | 12856 The <emphasis>file header</emphasis> describes the file being |
belaran@999 | 12857 modified; it contains the name of the file to modify. When |
belaran@999 | 12858 <command moreinfo="none">patch</command> sees a new file header, it looks for a |
belaran@999 | 12859 file with that name to start modifying.</para> |
belaran@999 | 12860 |
belaran@999 | 12861 <para id="x_3c7">After the file header comes a series of |
belaran@999 | 12862 <emphasis>hunks</emphasis>. Each hunk starts with a header; |
belaran@999 | 12863 this identifies the range of line numbers within the file that |
belaran@999 | 12864 the hunk should modify. Following the header, a hunk starts and |
belaran@999 | 12865 ends with a few (usually three) lines of text from the |
belaran@999 | 12866 unmodified file; these are called the |
belaran@999 | 12867 <emphasis>context</emphasis> for the hunk. If there's only a |
belaran@999 | 12868 small amount of context between successive hunks, |
belaran@999 | 12869 <command moreinfo="none">diff</command> doesn't print a new hunk header; it just |
belaran@999 | 12870 runs the hunks together, with a few lines of context between |
belaran@999 | 12871 modifications.</para> |
belaran@999 | 12872 |
belaran@999 | 12873 <para id="x_3c8">Each line of context begins with a space character. Within |
belaran@999 | 12874 the hunk, a line that begins with |
belaran@999 | 12875 <quote><literal moreinfo="none">-</literal></quote> means <quote>remove this |
belaran@999 | 12876 line,</quote> while a line that begins with |
belaran@999 | 12877 <quote><literal moreinfo="none">+</literal></quote> means <quote>insert this |
belaran@999 | 12878 line.</quote> For example, a line that is modified is |
belaran@999 | 12879 represented by one deletion and one insertion.</para> |
belaran@999 | 12880 |
belaran@999 | 12881 <para id="x_3c9">We will return to some of the more subtle aspects of patches |
belaran@999 | 12882 later (in <xref linkend="sec:mq:adv-patch"/>), but you |
belaran@999 | 12883 should have |
belaran@999 | 12884 enough information now to use MQ.</para> |
belaran@999 | 12885 </sect1> |
belaran@999 | 12886 |
belaran@999 | 12887 <sect1 id="sec:mq:start"> |
belaran@999 | 12888 <title>Getting started with Mercurial Queues</title> |
belaran@999 | 12889 |
belaran@999 | 12890 <para id="x_3ca">Because MQ is implemented as an extension, you must |
belaran@999 | 12891 explicitly enable before you can use it. (You don't need to |
belaran@999 | 12892 download anything; MQ ships with the standard Mercurial |
belaran@999 | 12893 distribution.) To enable MQ, edit your <filename role="home" moreinfo="none">~/.hgrc</filename> file, and add the lines |
belaran@999 | 12894 below.</para> |
belaran@999 | 12895 |
belaran@999 | 12896 <programlisting format="linespecific">[extensions] |
belaran@999 | 12897 hgext.mq =</programlisting> |
belaran@999 | 12898 |
belaran@999 | 12899 <para id="x_3cb">Once the extension is enabled, it will make a number of new |
belaran@999 | 12900 commands available. To verify that the extension is working, |
belaran@999 | 12901 you can use <command role="hg-cmd" moreinfo="none">hg help</command> to see if |
belaran@999 | 12902 the <command role="hg-ext-mq" moreinfo="none">qinit</command> command is now |
belaran@999 | 12903 available.</para> |
belaran@999 | 12904 |
belaran@999 | 12905 <!-- BEGIN mq.qinit-help.help --> |
belaran@999 | 12906 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg help qinit</userinput> |
belaran@999 | 12907 hg qinit [-c] |
belaran@999 | 12908 |
belaran@999 | 12909 init a new queue repository |
belaran@999 | 12910 |
belaran@999 | 12911 The queue repository is unversioned by default. If -c is |
belaran@999 | 12912 specified, qinit will create a separate nested repository |
belaran@999 | 12913 for patches (qinit -c may also be run later to convert |
belaran@999 | 12914 an unversioned patch repository into a versioned one). |
belaran@999 | 12915 You can use qcommit to commit changes to this queue repository. |
belaran@999 | 12916 |
belaran@999 | 12917 options: |
belaran@999 | 12918 |
belaran@999 | 12919 -c --create-repo create queue repository |
belaran@999 | 12920 |
belaran@999 | 12921 use "hg -v help qinit" to show global options |
belaran@999 | 12922 </screen> |
belaran@999 | 12923 <!-- END mq.qinit-help.help --> |
belaran@999 | 12924 |
belaran@999 | 12925 |
belaran@999 | 12926 <para id="x_3cc">You can use MQ with <emphasis>any</emphasis> Mercurial |
belaran@999 | 12927 repository, and its commands only operate within that |
belaran@999 | 12928 repository. To get started, simply prepare the repository using |
belaran@999 | 12929 the <command role="hg-ext-mq" moreinfo="none">qinit</command> command.</para> |
belaran@999 | 12930 |
belaran@999 | 12931 <!-- BEGIN mq.tutorial.qinit --> |
belaran@999 | 12932 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init mq-sandbox</userinput> |
belaran@999 | 12933 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd mq-sandbox</userinput> |
belaran@999 | 12934 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 1' > file1</userinput> |
belaran@999 | 12935 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'another line 1' > file2</userinput> |
belaran@999 | 12936 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add file1 file2</userinput> |
belaran@999 | 12937 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -m'first change'</userinput> |
belaran@999 | 12938 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> |
belaran@999 | 12939 </screen> |
belaran@999 | 12940 <!-- END mq.tutorial.qinit --> |
belaran@999 | 12941 |
belaran@999 | 12942 |
belaran@999 | 12943 <para id="x_3cd">This command creates an empty directory called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>, where |
belaran@999 | 12944 MQ will keep its metadata. As with many Mercurial commands, the |
belaran@999 | 12945 <command role="hg-ext-mq" moreinfo="none">qinit</command> command prints nothing |
belaran@999 | 12946 if it succeeds.</para> |
belaran@999 | 12947 |
belaran@999 | 12948 <sect2> |
belaran@999 | 12949 <title>Creating a new patch</title> |
belaran@999 | 12950 |
belaran@999 | 12951 <para id="x_3ce">To begin work on a new patch, use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command. This command takes |
belaran@999 | 12952 one argument, the name of the patch to create.</para> |
belaran@999 | 12953 |
belaran@999 | 12954 <para id="x_3cf">MQ will use this as the name of an actual file in the |
belaran@999 | 12955 <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory, as you |
belaran@999 | 12956 can see below.</para> |
belaran@999 | 12957 |
belaran@999 | 12958 <!-- BEGIN mq.tutorial.qnew --> |
belaran@999 | 12959 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 12960 changeset: 0:5d84c303994b |
belaran@999 | 12961 tag: tip |
belaran@999 | 12962 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 12963 date: Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 12964 summary: first change |
belaran@999 | 12965 |
belaran@999 | 12966 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew first.patch</userinput> |
belaran@999 | 12967 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip</userinput> |
belaran@999 | 12968 changeset: 1:ba4d7a3f2149 |
belaran@999 | 12969 tag: qtip |
belaran@999 | 12970 tag: first.patch |
belaran@999 | 12971 tag: tip |
belaran@999 | 12972 tag: qbase |
belaran@999 | 12973 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 12974 date: Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 12975 summary: [mq]: first.patch |
belaran@999 | 12976 |
belaran@999 | 12977 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">ls .hg/patches</userinput> |
belaran@999 | 12978 first.patch series status |
belaran@999 | 12979 </screen> |
belaran@999 | 12980 <!-- END mq.tutorial.qnew --> |
belaran@999 | 12981 |
belaran@999 | 12982 |
belaran@999 | 12983 <para id="x_3d0">Also newly present in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory are two |
belaran@999 | 12984 other files, <filename role="special" moreinfo="none">series</filename> and |
belaran@999 | 12985 <filename role="special" moreinfo="none">status</filename>. The <filename role="special" moreinfo="none">series</filename> file lists all of the |
belaran@999 | 12986 patches that MQ knows about for this repository, with one |
belaran@999 | 12987 patch per line. Mercurial uses the <filename role="special" moreinfo="none">status</filename> file for internal |
belaran@999 | 12988 book-keeping; it tracks all of the patches that MQ has |
belaran@999 | 12989 <emphasis>applied</emphasis> in this repository.</para> |
belaran@999 | 12990 |
belaran@999 | 12991 <note> |
belaran@999 | 12992 <para id="x_3d1"> You may sometimes want to edit the <filename role="special" moreinfo="none">series</filename> file by hand; for |
belaran@999 | 12993 example, to change the sequence in which some patches are |
belaran@999 | 12994 applied. However, manually editing the <filename role="special" moreinfo="none">status</filename> file is almost always a |
belaran@999 | 12995 bad idea, as it's easy to corrupt MQ's idea of what is |
belaran@999 | 12996 happening.</para> |
belaran@999 | 12997 </note> |
belaran@999 | 12998 |
belaran@999 | 12999 <para id="x_3d2">Once you have created your new patch, you can edit files |
belaran@999 | 13000 in the working directory as you usually would. All of the |
belaran@999 | 13001 normal Mercurial commands, such as <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13002 diff</command> and <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13003 annotate</command>, work exactly as they did before.</para> |
belaran@999 | 13004 </sect2> |
belaran@999 | 13005 |
belaran@999 | 13006 <sect2> |
belaran@999 | 13007 <title>Refreshing a patch</title> |
belaran@999 | 13008 |
belaran@999 | 13009 <para id="x_3d3">When you reach a point where you want to save your work, |
belaran@999 | 13010 use the <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command |
belaran@999 | 13011 to update the patch you are working on.</para> |
belaran@999 | 13012 |
belaran@999 | 13013 <!-- BEGIN mq.tutorial.qrefresh --> |
belaran@999 | 13014 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 2' >> file1</userinput> |
belaran@999 | 13015 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> |
belaran@999 | 13016 diff -r ba4d7a3f2149 file1 |
belaran@999 | 13017 --- a/file1 Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 13018 +++ b/file1 Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 13019 @@ -1,1 +1,2 @@ |
belaran@999 | 13020 line 1 |
belaran@999 | 13021 +line 2 |
belaran@999 | 13022 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 13023 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> |
belaran@999 | 13024 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput> |
belaran@999 | 13025 1[qtip,first.patch,tip,qbase] 1aa236e17e55 2009-08-16 14:05 +0000 bos |
belaran@999 | 13026 [mq]: first.patch |
belaran@999 | 13027 |
belaran@999 | 13028 diff -r 5d84c303994b -r 1aa236e17e55 file1 |
belaran@999 | 13029 --- a/file1 Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 13030 +++ b/file1 Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 13031 @@ -1,1 +1,2 @@ |
belaran@999 | 13032 line 1 |
belaran@999 | 13033 +line 2 |
belaran@999 | 13034 |
belaran@999 | 13035 </screen> |
belaran@999 | 13036 <!-- END mq.tutorial.qrefresh --> |
belaran@999 | 13037 |
belaran@999 | 13038 |
belaran@999 | 13039 <para id="x_3d4">This command folds the changes you have made in the |
belaran@999 | 13040 working directory into your patch, and updates its |
belaran@999 | 13041 corresponding changeset to contain those changes.</para> |
belaran@999 | 13042 |
belaran@999 | 13043 <para id="x_3d5">You can run <command role="hg-ext-mq" moreinfo="none">qrefresh</command> |
belaran@999 | 13044 as often as you like, so it's a good way to |
belaran@999 | 13045 <quote>checkpoint</quote> your work. Refresh your patch at an |
belaran@999 | 13046 opportune time; try an experiment; and if the experiment |
belaran@999 | 13047 doesn't work out, <command role="hg-cmd" moreinfo="none">hg revert</command> |
belaran@999 | 13048 your modifications back to the last time you refreshed.</para> |
belaran@999 | 13049 |
belaran@999 | 13050 <!-- BEGIN mq.tutorial.qrefresh2 --> |
belaran@999 | 13051 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 3' >> file1</userinput> |
belaran@999 | 13052 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status</userinput> |
belaran@999 | 13053 M file1 |
belaran@999 | 13054 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 13055 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput> |
belaran@999 | 13056 1[qtip,first.patch,tip,qbase] ebec7ce95e11 2009-08-16 14:05 +0000 bos |
belaran@999 | 13057 [mq]: first.patch |
belaran@999 | 13058 |
belaran@999 | 13059 diff -r 5d84c303994b -r ebec7ce95e11 file1 |
belaran@999 | 13060 --- a/file1 Sun Aug 16 14:05:11 2009 +0000 |
belaran@999 | 13061 +++ b/file1 Sun Aug 16 14:05:12 2009 +0000 |
belaran@999 | 13062 @@ -1,1 +1,3 @@ |
belaran@999 | 13063 line 1 |
belaran@999 | 13064 +line 2 |
belaran@999 | 13065 +line 3 |
belaran@999 | 13066 |
belaran@999 | 13067 </screen> |
belaran@999 | 13068 <!-- END mq.tutorial.qrefresh2 --> |
belaran@999 | 13069 |
belaran@999 | 13070 </sect2> |
belaran@999 | 13071 |
belaran@999 | 13072 <sect2> |
belaran@999 | 13073 <title>Stacking and tracking patches</title> |
belaran@999 | 13074 |
belaran@999 | 13075 <para id="x_3d6">Once you have finished working on a patch, or need to work |
belaran@999 | 13076 on another, you can use the <command role="hg-ext-mq" moreinfo="none">qnew</command> command again to create a |
belaran@999 | 13077 new patch. Mercurial will apply this patch on top of your |
belaran@999 | 13078 existing patch.</para> |
belaran@999 | 13079 |
belaran@999 | 13080 <!-- BEGIN mq.tutorial.qnew2 --> |
belaran@999 | 13081 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew second.patch</userinput> |
belaran@999 | 13082 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log --style=compact --limit=2</userinput> |
belaran@999 | 13083 2[qtip,second.patch,tip] dffbc4265523 2009-08-16 14:05 +0000 bos |
belaran@999 | 13084 [mq]: second.patch |
belaran@999 | 13085 |
belaran@999 | 13086 1[first.patch,qbase] ebec7ce95e11 2009-08-16 14:05 +0000 bos |
belaran@999 | 13087 [mq]: first.patch |
belaran@999 | 13088 |
belaran@999 | 13089 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'line 4' >> file1</userinput> |
belaran@999 | 13090 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 13091 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact --patch</userinput> |
belaran@999 | 13092 2[qtip,second.patch,tip] fdacb9b232ac 2009-08-16 14:05 +0000 bos |
belaran@999 | 13093 [mq]: second.patch |
belaran@999 | 13094 |
belaran@999 | 13095 diff -r ebec7ce95e11 -r fdacb9b232ac file1 |
belaran@999 | 13096 --- a/file1 Sun Aug 16 14:05:12 2009 +0000 |
belaran@999 | 13097 +++ b/file1 Sun Aug 16 14:05:12 2009 +0000 |
belaran@999 | 13098 @@ -1,3 +1,4 @@ |
belaran@999 | 13099 line 1 |
belaran@999 | 13100 line 2 |
belaran@999 | 13101 line 3 |
belaran@999 | 13102 +line 4 |
belaran@999 | 13103 |
belaran@999 | 13104 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg annotate file1</userinput> |
belaran@999 | 13105 0: line 1 |
belaran@999 | 13106 1: line 2 |
belaran@999 | 13107 1: line 3 |
belaran@999 | 13108 2: line 4 |
belaran@999 | 13109 </screen> |
belaran@999 | 13110 <!-- END mq.tutorial.qnew2 --> |
belaran@999 | 13111 |
belaran@999 | 13112 |
belaran@999 | 13113 <para id="x_3d7">Notice that the patch contains the changes in our prior |
belaran@999 | 13114 patch as part of its context (you can see this more clearly in |
belaran@999 | 13115 the output of <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13116 annotate</command>).</para> |
belaran@999 | 13117 |
belaran@999 | 13118 <para id="x_3d8">So far, with the exception of <command role="hg-ext-mq" moreinfo="none">qnew</command> and <command role="hg-ext-mq" moreinfo="none">qrefresh</command>, we've been careful to |
belaran@999 | 13119 only use regular Mercurial commands. However, MQ provides |
belaran@999 | 13120 many commands that are easier to use when you are thinking |
belaran@999 | 13121 about patches, as illustrated below.</para> |
belaran@999 | 13122 |
belaran@999 | 13123 <!-- BEGIN mq.tutorial.qseries --> |
belaran@999 | 13124 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput> |
belaran@999 | 13125 first.patch |
belaran@999 | 13126 second.patch |
belaran@999 | 13127 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> |
belaran@999 | 13128 first.patch |
belaran@999 | 13129 second.patch |
belaran@999 | 13130 </screen> |
belaran@999 | 13131 <!-- END mq.tutorial.qseries --> |
belaran@999 | 13132 |
belaran@999 | 13133 |
belaran@999 | 13134 <itemizedlist> |
belaran@999 | 13135 <listitem><para id="x_3d9">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command lists every |
belaran@999 | 13136 patch that MQ knows about in this repository, from oldest |
belaran@999 | 13137 to newest (most recently |
belaran@999 | 13138 <emphasis>created</emphasis>).</para> |
belaran@999 | 13139 </listitem> |
belaran@999 | 13140 <listitem><para id="x_3da">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command lists every |
belaran@999 | 13141 patch that MQ has <emphasis>applied</emphasis> in this |
belaran@999 | 13142 repository, again from oldest to newest (most recently |
belaran@999 | 13143 applied).</para> |
belaran@999 | 13144 </listitem></itemizedlist> |
belaran@999 | 13145 </sect2> |
belaran@999 | 13146 |
belaran@999 | 13147 <sect2> |
belaran@999 | 13148 <title>Manipulating the patch stack</title> |
belaran@999 | 13149 |
belaran@999 | 13150 <para id="x_3db">The previous discussion implied that there must be a |
belaran@999 | 13151 difference between <quote>known</quote> and |
belaran@999 | 13152 <quote>applied</quote> patches, and there is. MQ can manage a |
belaran@999 | 13153 patch without it being applied in the repository.</para> |
belaran@999 | 13154 |
belaran@999 | 13155 <para id="x_3dc">An <emphasis>applied</emphasis> patch has a corresponding |
belaran@999 | 13156 changeset in the repository, and the effects of the patch and |
belaran@999 | 13157 changeset are visible in the working directory. You can undo |
belaran@999 | 13158 the application of a patch using the <command role="hg-ext-mq" moreinfo="none">qpop</command> command. MQ still |
belaran@999 | 13159 <emphasis>knows about</emphasis>, or manages, a popped patch, |
belaran@999 | 13160 but the patch no longer has a corresponding changeset in the |
belaran@999 | 13161 repository, and the working directory does not contain the |
belaran@999 | 13162 changes made by the patch. <xref linkend="fig:mq:stack"/> illustrates |
belaran@999 | 13163 the difference between applied and tracked patches.</para> |
belaran@999 | 13164 |
belaran@999 | 13165 <figure id="fig:mq:stack" float="0"> |
belaran@999 | 13166 <title>Applied and unapplied patches in the MQ patch |
belaran@999 | 13167 stack</title> |
belaran@999 | 13168 <mediaobject> |
belaran@999 | 13169 <imageobject><imagedata fileref="figs/mq-stack.png"/></imageobject> |
belaran@999 | 13170 <textobject><phrase>XXX add text</phrase></textobject> |
belaran@999 | 13171 </mediaobject> |
belaran@999 | 13172 </figure> |
belaran@999 | 13173 |
belaran@999 | 13174 <para id="x_3de">You can reapply an unapplied, or popped, patch using the |
belaran@999 | 13175 <command role="hg-ext-mq" moreinfo="none">qpush</command> command. This |
belaran@999 | 13176 creates a new changeset to correspond to the patch, and the |
belaran@999 | 13177 patch's changes once again become present in the working |
belaran@999 | 13178 directory. See below for examples of <command role="hg-ext-mq" moreinfo="none">qpop</command> and <command role="hg-ext-mq" moreinfo="none">qpush</command> in action.</para> |
belaran@999 | 13179 |
belaran@999 | 13180 <!-- BEGIN mq.tutorial.qpop --> |
belaran@999 | 13181 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> |
belaran@999 | 13182 first.patch |
belaran@999 | 13183 second.patch |
belaran@999 | 13184 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput> |
belaran@999 | 13185 now at: first.patch |
belaran@999 | 13186 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qseries</userinput> |
belaran@999 | 13187 first.patch |
belaran@999 | 13188 second.patch |
belaran@999 | 13189 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> |
belaran@999 | 13190 first.patch |
belaran@999 | 13191 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput> |
belaran@999 | 13192 line 1 |
belaran@999 | 13193 line 2 |
belaran@999 | 13194 line 3 |
belaran@999 | 13195 </screen> |
belaran@999 | 13196 <!-- END mq.tutorial.qpop --> |
belaran@999 | 13197 |
belaran@999 | 13198 |
belaran@999 | 13199 <para id="x_3df">Notice that once we have popped a patch or two patches, |
belaran@999 | 13200 the output of <command role="hg-ext-mq" moreinfo="none">qseries</command> |
belaran@999 | 13201 remains the same, while that of <command role="hg-ext-mq" moreinfo="none">qapplied</command> has changed.</para> |
belaran@999 | 13202 |
belaran@999 | 13203 </sect2> |
belaran@999 | 13204 |
belaran@999 | 13205 <sect2> |
belaran@999 | 13206 <title>Pushing and popping many patches</title> |
belaran@999 | 13207 |
belaran@999 | 13208 <para id="x_3e0">While <command role="hg-ext-mq" moreinfo="none">qpush</command> and |
belaran@999 | 13209 <command role="hg-ext-mq" moreinfo="none">qpop</command> each operate on a |
belaran@999 | 13210 single patch at a time by default, you can push and pop many |
belaran@999 | 13211 patches in one go. The <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to |
belaran@999 | 13212 <command role="hg-ext-mq" moreinfo="none">qpush</command> causes it to push |
belaran@999 | 13213 all unapplied patches, while the <option role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command role="hg-ext-mq" moreinfo="none">qpop</command> causes it to pop all applied |
belaran@999 | 13214 patches. (For some more ways to push and pop many patches, |
belaran@999 | 13215 see <xref linkend="sec:mq:perf"/> below.)</para> |
belaran@999 | 13216 |
belaran@999 | 13217 <!-- BEGIN mq.tutorial.qpush-a --> |
belaran@999 | 13218 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> |
belaran@999 | 13219 applying second.patch |
belaran@999 | 13220 now at: second.patch |
belaran@999 | 13221 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat file1</userinput> |
belaran@999 | 13222 line 1 |
belaran@999 | 13223 line 2 |
belaran@999 | 13224 line 3 |
belaran@999 | 13225 line 4 |
belaran@999 | 13226 </screen> |
belaran@999 | 13227 <!-- END mq.tutorial.qpush-a --> |
belaran@999 | 13228 |
belaran@999 | 13229 </sect2> |
belaran@999 | 13230 |
belaran@999 | 13231 <sect2> |
belaran@999 | 13232 <title>Safety checks, and overriding them</title> |
belaran@999 | 13233 |
belaran@999 | 13234 <para id="x_3e1">Several MQ commands check the working directory before |
belaran@999 | 13235 they do anything, and fail if they find any modifications. |
belaran@999 | 13236 They do this to ensure that you won't lose any changes that |
belaran@999 | 13237 you have made, but not yet incorporated into a patch. The |
belaran@999 | 13238 example below illustrates this; the <command role="hg-ext-mq" moreinfo="none">qnew</command> command will not create a |
belaran@999 | 13239 new patch if there are outstanding changes, caused in this |
belaran@999 | 13240 case by the <command role="hg-cmd" moreinfo="none">hg add</command> of |
belaran@999 | 13241 <filename moreinfo="none">file3</filename>.</para> |
belaran@999 | 13242 |
belaran@999 | 13243 <!-- BEGIN mq.tutorial.add --> |
belaran@999 | 13244 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo 'file 3, line 1' >> file3</userinput> |
belaran@999 | 13245 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew add-file3.patch</userinput> |
belaran@999 | 13246 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -f add-file3.patch</userinput> |
belaran@999 | 13247 abort: patch "add-file3.patch" already exists |
belaran@999 | 13248 </screen> |
belaran@999 | 13249 <!-- END mq.tutorial.add --> |
belaran@999 | 13250 |
belaran@999 | 13251 |
belaran@999 | 13252 <para id="x_3e2">Commands that check the working directory all take an |
belaran@999 | 13253 <quote>I know what I'm doing</quote> option, which is always |
belaran@999 | 13254 named <option>-f</option>. The exact meaning of |
belaran@999 | 13255 <option>-f</option> depends on the command. For example, |
belaran@999 | 13256 <command role="hg-cmd" moreinfo="none">hg qnew <option role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command> |
belaran@999 | 13257 will incorporate any outstanding changes into the new patch it |
belaran@999 | 13258 creates, but <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command> |
belaran@999 | 13259 will revert modifications to any files affected by the patch |
belaran@999 | 13260 that it is popping. Be sure to read the documentation for a |
belaran@999 | 13261 command's <option>-f</option> option before you use it!</para> |
belaran@999 | 13262 </sect2> |
belaran@999 | 13263 |
belaran@999 | 13264 <sect2> |
belaran@999 | 13265 <title>Working on several patches at once</title> |
belaran@999 | 13266 |
belaran@999 | 13267 <para id="x_3e3">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command |
belaran@999 | 13268 always refreshes the <emphasis>topmost</emphasis> applied |
belaran@999 | 13269 patch. This means that you can suspend work on one patch (by |
belaran@999 | 13270 refreshing it), pop or push to make a different patch the top, |
belaran@999 | 13271 and work on <emphasis>that</emphasis> patch for a |
belaran@999 | 13272 while.</para> |
belaran@999 | 13273 |
belaran@999 | 13274 <para id="x_3e4">Here's an example that illustrates how you can use this |
belaran@999 | 13275 ability. Let's say you're developing a new feature as two |
belaran@999 | 13276 patches. The first is a change to the core of your software, |
belaran@999 | 13277 and the second—layered on top of the |
belaran@999 | 13278 first—changes the user interface to use the code you |
belaran@999 | 13279 just added to the core. If you notice a bug in the core while |
belaran@999 | 13280 you're working on the UI patch, it's easy to fix the core. |
belaran@999 | 13281 Simply <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the UI |
belaran@999 | 13282 patch to save your in-progress changes, and <command role="hg-ext-mq" moreinfo="none">qpop</command> down to the core patch. Fix |
belaran@999 | 13283 the core bug, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the |
belaran@999 | 13284 core patch, and <command role="hg-ext-mq" moreinfo="none">qpush</command> back |
belaran@999 | 13285 to the UI patch to continue where you left off.</para> |
belaran@999 | 13286 </sect2> |
belaran@999 | 13287 </sect1> |
belaran@999 | 13288 |
belaran@999 | 13289 <sect1 id="sec:mq:adv-patch"> |
belaran@999 | 13290 <title>More about patches</title> |
belaran@999 | 13291 |
belaran@999 | 13292 <para id="x_3e5">MQ uses the GNU <command moreinfo="none">patch</command> command to apply |
belaran@999 | 13293 patches, so it's helpful to know a few more detailed aspects of |
belaran@999 | 13294 how <command moreinfo="none">patch</command> works, and about patches |
belaran@999 | 13295 themselves.</para> |
belaran@999 | 13296 |
belaran@999 | 13297 <sect2> |
belaran@999 | 13298 <title>The strip count</title> |
belaran@999 | 13299 |
belaran@999 | 13300 <para id="x_3e6">If you look at the file headers in a patch, you will |
belaran@999 | 13301 notice that the pathnames usually have an extra component on |
belaran@999 | 13302 the front that isn't present in the actual path name. This is |
belaran@999 | 13303 a holdover from the way that people used to generate patches |
belaran@999 | 13304 (people still do this, but it's somewhat rare with modern |
belaran@999 | 13305 revision control tools).</para> |
belaran@999 | 13306 |
belaran@999 | 13307 <para id="x_3e7">Alice would unpack a tarball, edit her files, then decide |
belaran@999 | 13308 that she wanted to create a patch. So she'd rename her |
belaran@999 | 13309 working directory, unpack the tarball again (hence the need |
belaran@999 | 13310 for the rename), and use the <option role="cmd-opt-diff">-r</option> and <option role="cmd-opt-diff">-N</option> options to |
belaran@999 | 13311 <command moreinfo="none">diff</command> to recursively generate a patch |
belaran@999 | 13312 between the unmodified directory and the modified one. The |
belaran@999 | 13313 result would be that the name of the unmodified directory |
belaran@999 | 13314 would be at the front of the left-hand path in every file |
belaran@999 | 13315 header, and the name of the modified directory would be at the |
belaran@999 | 13316 front of the right-hand path.</para> |
belaran@999 | 13317 |
belaran@999 | 13318 <para id="x_3e8">Since someone receiving a patch from the Alices of the net |
belaran@999 | 13319 would be unlikely to have unmodified and modified directories |
belaran@999 | 13320 with exactly the same names, the <command moreinfo="none">patch</command> |
belaran@999 | 13321 command has a <option role="cmd-opt-patch">-p</option> option |
belaran@999 | 13322 that indicates the number of leading path name components to |
belaran@999 | 13323 strip when trying to apply a patch. This number is called the |
belaran@999 | 13324 <emphasis>strip count</emphasis>.</para> |
belaran@999 | 13325 |
belaran@999 | 13326 <para id="x_3e9">An option of <quote><literal moreinfo="none">-p1</literal></quote> means |
belaran@999 | 13327 <quote>use a strip count of one</quote>. If |
belaran@999 | 13328 <command moreinfo="none">patch</command> sees a file name |
belaran@999 | 13329 <filename moreinfo="none">foo/bar/baz</filename> in a file header, it will |
belaran@999 | 13330 strip <filename moreinfo="none">foo</filename> and try to patch a file named |
belaran@999 | 13331 <filename moreinfo="none">bar/baz</filename>. (Strictly speaking, the strip |
belaran@999 | 13332 count refers to the number of <emphasis>path |
belaran@999 | 13333 separators</emphasis> (and the components that go with them |
belaran@999 | 13334 ) to strip. A strip count of one will turn |
belaran@999 | 13335 <filename moreinfo="none">foo/bar</filename> into <filename moreinfo="none">bar</filename>, |
belaran@999 | 13336 but <filename moreinfo="none">/foo/bar</filename> (notice the extra leading |
belaran@999 | 13337 slash) into <filename moreinfo="none">foo/bar</filename>.)</para> |
belaran@999 | 13338 |
belaran@999 | 13339 <para id="x_3ea">The <quote>standard</quote> strip count for patches is |
belaran@999 | 13340 one; almost all patches contain one leading path name |
belaran@999 | 13341 component that needs to be stripped. Mercurial's <command role="hg-cmd" moreinfo="none">hg diff</command> command generates path names |
belaran@999 | 13342 in this form, and the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13343 import</command> command and MQ expect patches to have a |
belaran@999 | 13344 strip count of one.</para> |
belaran@999 | 13345 |
belaran@999 | 13346 <para id="x_3eb">If you receive a patch from someone that you want to add |
belaran@999 | 13347 to your patch queue, and the patch needs a strip count other |
belaran@999 | 13348 than one, you cannot just <command role="hg-ext-mq" moreinfo="none">qimport</command> the patch, because |
belaran@999 | 13349 <command role="hg-ext-mq" moreinfo="none">qimport</command> does not yet have |
belaran@999 | 13350 a <literal moreinfo="none">-p</literal> option (see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue |
belaran@999 | 13351 311</ulink>). Your best bet is to <command role="hg-ext-mq" moreinfo="none">qnew</command> a patch of your own, then |
belaran@999 | 13352 use <command moreinfo="none">patch -pN</command> to apply their patch, |
belaran@999 | 13353 followed by <command role="hg-cmd" moreinfo="none">hg addremove</command> to |
belaran@999 | 13354 pick up any files added or removed by the patch, followed by |
belaran@999 | 13355 <command role="hg-ext-mq" moreinfo="none">hg qrefresh</command>. This |
belaran@999 | 13356 complexity may become unnecessary; see <ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue311">issue |
belaran@999 | 13357 311</ulink> for details. |
belaran@999 | 13358 </para> |
belaran@999 | 13359 </sect2> |
belaran@999 | 13360 |
belaran@999 | 13361 <sect2> |
belaran@999 | 13362 <title>Strategies for applying a patch</title> |
belaran@999 | 13363 |
belaran@999 | 13364 <para id="x_3ec">When <command moreinfo="none">patch</command> applies a hunk, it tries a |
belaran@999 | 13365 handful of successively less accurate strategies to try to |
belaran@999 | 13366 make the hunk apply. This falling-back technique often makes |
belaran@999 | 13367 it possible to take a patch that was generated against an old |
belaran@999 | 13368 version of a file, and apply it against a newer version of |
belaran@999 | 13369 that file.</para> |
belaran@999 | 13370 |
belaran@999 | 13371 <para id="x_3ed">First, <command moreinfo="none">patch</command> tries an exact match, |
belaran@999 | 13372 where the line numbers, the context, and the text to be |
belaran@999 | 13373 modified must apply exactly. If it cannot make an exact |
belaran@999 | 13374 match, it tries to find an exact match for the context, |
belaran@999 | 13375 without honouring the line numbering information. If this |
belaran@999 | 13376 succeeds, it prints a line of output saying that the hunk was |
belaran@999 | 13377 applied, but at some <emphasis>offset</emphasis> from the |
belaran@999 | 13378 original line number.</para> |
belaran@999 | 13379 |
belaran@999 | 13380 <para id="x_3ee">If a context-only match fails, <command moreinfo="none">patch</command> |
belaran@999 | 13381 removes the first and last lines of the context, and tries a |
belaran@999 | 13382 <emphasis>reduced</emphasis> context-only match. If the hunk |
belaran@999 | 13383 with reduced context succeeds, it prints a message saying that |
belaran@999 | 13384 it applied the hunk with a <emphasis>fuzz factor</emphasis> |
belaran@999 | 13385 (the number after the fuzz factor indicates how many lines of |
belaran@999 | 13386 context <command moreinfo="none">patch</command> had to trim before the patch |
belaran@999 | 13387 applied).</para> |
belaran@999 | 13388 |
belaran@999 | 13389 <para id="x_3ef">When neither of these techniques works, |
belaran@999 | 13390 <command moreinfo="none">patch</command> prints a message saying that the hunk |
belaran@999 | 13391 in question was rejected. It saves rejected hunks (also |
belaran@999 | 13392 simply called <quote>rejects</quote>) to a file with the same |
belaran@999 | 13393 name, and an added <filename role="special" moreinfo="none">.rej</filename> |
belaran@999 | 13394 extension. It also saves an unmodified copy of the file with |
belaran@999 | 13395 a <filename role="special" moreinfo="none">.orig</filename> extension; the |
belaran@999 | 13396 copy of the file without any extensions will contain any |
belaran@999 | 13397 changes made by hunks that <emphasis>did</emphasis> apply |
belaran@999 | 13398 cleanly. If you have a patch that modifies |
belaran@999 | 13399 <filename moreinfo="none">foo</filename> with six hunks, and one of them fails |
belaran@999 | 13400 to apply, you will have: an unmodified |
belaran@999 | 13401 <filename moreinfo="none">foo.orig</filename>, a <filename moreinfo="none">foo.rej</filename> |
belaran@999 | 13402 containing one hunk, and <filename moreinfo="none">foo</filename>, containing |
belaran@999 | 13403 the changes made by the five successful hunks.</para> |
belaran@999 | 13404 </sect2> |
belaran@999 | 13405 |
belaran@999 | 13406 <sect2> |
belaran@999 | 13407 <title>Some quirks of patch representation</title> |
belaran@999 | 13408 |
belaran@999 | 13409 <para id="x_3f0">There are a few useful things to know about how |
belaran@999 | 13410 <command moreinfo="none">patch</command> works with files.</para> |
belaran@999 | 13411 <itemizedlist> |
belaran@999 | 13412 <listitem><para id="x_3f1">This should already be obvious, but |
belaran@999 | 13413 <command moreinfo="none">patch</command> cannot handle binary |
belaran@999 | 13414 files.</para> |
belaran@999 | 13415 </listitem> |
belaran@999 | 13416 <listitem><para id="x_3f2">Neither does it care about the executable bit; |
belaran@999 | 13417 it creates new files as readable, but not |
belaran@999 | 13418 executable.</para> |
belaran@999 | 13419 </listitem> |
belaran@999 | 13420 <listitem><para id="x_3f3"><command moreinfo="none">patch</command> treats the removal of |
belaran@999 | 13421 a file as a diff between the file to be removed and the |
belaran@999 | 13422 empty file. So your idea of <quote>I deleted this |
belaran@999 | 13423 file</quote> looks like <quote>every line of this file |
belaran@999 | 13424 was deleted</quote> in a patch.</para> |
belaran@999 | 13425 </listitem> |
belaran@999 | 13426 <listitem><para id="x_3f4">It treats the addition of a file as a diff |
belaran@999 | 13427 between the empty file and the file to be added. So in a |
belaran@999 | 13428 patch, your idea of <quote>I added this file</quote> looks |
belaran@999 | 13429 like <quote>every line of this file was |
belaran@999 | 13430 added</quote>.</para> |
belaran@999 | 13431 </listitem> |
belaran@999 | 13432 <listitem><para id="x_3f5">It treats a renamed file as the removal of the |
belaran@999 | 13433 old name, and the addition of the new name. This means |
belaran@999 | 13434 that renamed files have a big footprint in patches. (Note |
belaran@999 | 13435 also that Mercurial does not currently try to infer when |
belaran@999 | 13436 files have been renamed or copied in a patch.)</para> |
belaran@999 | 13437 </listitem> |
belaran@999 | 13438 <listitem><para id="x_3f6"><command moreinfo="none">patch</command> cannot represent |
belaran@999 | 13439 empty files, so you cannot use a patch to represent the |
belaran@999 | 13440 notion <quote>I added this empty file to the |
belaran@999 | 13441 tree</quote>.</para> |
belaran@999 | 13442 </listitem></itemizedlist> |
belaran@999 | 13443 </sect2> |
belaran@999 | 13444 |
belaran@999 | 13445 <sect2> |
belaran@999 | 13446 <title>Beware the fuzz</title> |
belaran@999 | 13447 |
belaran@999 | 13448 <para id="x_3f7">While applying a hunk at an offset, or with a fuzz factor, |
belaran@999 | 13449 will often be completely successful, these inexact techniques |
belaran@999 | 13450 naturally leave open the possibility of corrupting the patched |
belaran@999 | 13451 file. The most common cases typically involve applying a |
belaran@999 | 13452 patch twice, or at an incorrect location in the file. If |
belaran@999 | 13453 <command moreinfo="none">patch</command> or <command role="hg-ext-mq" moreinfo="none">qpush</command> ever mentions an offset or |
belaran@999 | 13454 fuzz factor, you should make sure that the modified files are |
belaran@999 | 13455 correct afterwards.</para> |
belaran@999 | 13456 |
belaran@999 | 13457 <para id="x_3f8">It's often a good idea to refresh a patch that has applied |
belaran@999 | 13458 with an offset or fuzz factor; refreshing the patch generates |
belaran@999 | 13459 new context information that will make it apply cleanly. I |
belaran@999 | 13460 say <quote>often,</quote> not <quote>always,</quote> because |
belaran@999 | 13461 sometimes refreshing a patch will make it fail to apply |
belaran@999 | 13462 against a different revision of the underlying files. In some |
belaran@999 | 13463 cases, such as when you're maintaining a patch that must sit |
belaran@999 | 13464 on top of multiple versions of a source tree, it's acceptable |
belaran@999 | 13465 to have a patch apply with some fuzz, provided you've verified |
belaran@999 | 13466 the results of the patching process in such cases.</para> |
belaran@999 | 13467 </sect2> |
belaran@999 | 13468 |
belaran@999 | 13469 <sect2> |
belaran@999 | 13470 <title>Handling rejection</title> |
belaran@999 | 13471 |
belaran@999 | 13472 <para id="x_3f9">If <command role="hg-ext-mq" moreinfo="none">qpush</command> fails to |
belaran@999 | 13473 apply a patch, it will print an error message and exit. If it |
belaran@999 | 13474 has left <filename role="special" moreinfo="none">.rej</filename> files |
belaran@999 | 13475 behind, it is usually best to fix up the rejected hunks before |
belaran@999 | 13476 you push more patches or do any further work.</para> |
belaran@999 | 13477 |
belaran@999 | 13478 <para id="x_3fa">If your patch <emphasis>used to</emphasis> apply cleanly, |
belaran@999 | 13479 and no longer does because you've changed the underlying code |
belaran@999 | 13480 that your patches are based on, Mercurial Queues can help; see |
belaran@999 | 13481 <xref linkend="sec:mq:merge"/> for details.</para> |
belaran@999 | 13482 |
belaran@999 | 13483 <para id="x_3fb">Unfortunately, there aren't any great techniques for |
belaran@999 | 13484 dealing with rejected hunks. Most often, you'll need to view |
belaran@999 | 13485 the <filename role="special" moreinfo="none">.rej</filename> file and edit the |
belaran@999 | 13486 target file, applying the rejected hunks by hand.</para> |
belaran@999 | 13487 |
belaran@999 | 13488 <para id="x_3fd">A Linux kernel hacker, Chris Mason (the author |
belaran@999 | 13489 of Mercurial Queues), wrote a tool called |
belaran@999 | 13490 <command moreinfo="none">mpatch</command> (<ulink url="http://oss.oracle.com/~mason/mpatch/">http://oss.oracle.com/~mason/mpatch/</ulink>), |
belaran@999 | 13491 which takes a simple approach to automating the application of |
belaran@999 | 13492 hunks rejected by <command moreinfo="none">patch</command>. The |
belaran@999 | 13493 <command moreinfo="none">mpatch</command> command can help with four common |
belaran@999 | 13494 reasons that a hunk may be rejected:</para> |
belaran@999 | 13495 |
belaran@999 | 13496 <itemizedlist> |
belaran@999 | 13497 <listitem><para id="x_3fe">The context in the middle of a hunk has |
belaran@999 | 13498 changed.</para> |
belaran@999 | 13499 </listitem> |
belaran@999 | 13500 <listitem><para id="x_3ff">A hunk is missing some context at the |
belaran@999 | 13501 beginning or end.</para> |
belaran@999 | 13502 </listitem> |
belaran@999 | 13503 <listitem><para id="x_400">A large hunk might apply better—either |
belaran@999 | 13504 entirely or in part—if it was broken up into |
belaran@999 | 13505 smaller hunks.</para> |
belaran@999 | 13506 </listitem> |
belaran@999 | 13507 <listitem><para id="x_401">A hunk removes lines with slightly different |
belaran@999 | 13508 content than those currently present in the file.</para> |
belaran@999 | 13509 </listitem></itemizedlist> |
belaran@999 | 13510 |
belaran@999 | 13511 <para id="x_402">If you use <command moreinfo="none">mpatch</command>, you |
belaran@999 | 13512 should be doubly careful to check your results when you're |
belaran@999 | 13513 done. In fact, <command moreinfo="none">mpatch</command> enforces this method |
belaran@999 | 13514 of double-checking the tool's output, by automatically |
belaran@999 | 13515 dropping you into a merge program when it has done its job, so |
belaran@999 | 13516 that you can verify its work and finish off any remaining |
belaran@999 | 13517 merges.</para> |
belaran@999 | 13518 </sect2> |
belaran@999 | 13519 </sect1> |
belaran@999 | 13520 |
belaran@999 | 13521 <sect1> |
belaran@999 | 13522 <title>More on patch management</title> |
belaran@999 | 13523 |
belaran@999 | 13524 <para id="x_6db">As you grow familiar with MQ, you will find yourself wanting |
belaran@999 | 13525 to perform other kinds of patch management operations.</para> |
belaran@999 | 13526 |
belaran@999 | 13527 <sect2> |
belaran@999 | 13528 <title>Deleting unwanted patches</title> |
belaran@999 | 13529 |
belaran@999 | 13530 <para id="x_6dc">If you want to get rid of a patch, use the <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> command to delete the |
belaran@999 | 13531 patch file and remove its entry from the patch series. If you |
belaran@999 | 13532 try to delete a patch that is still applied, <command role="hg-ext-mq" moreinfo="none">hg qdelete</command> will refuse.</para> |
belaran@999 | 13533 |
belaran@999 | 13534 <!-- BEGIN ch11/qdelete.go --> |
belaran@999 | 13535 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init myrepo</userinput> |
belaran@999 | 13536 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd myrepo</userinput> |
belaran@999 | 13537 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> |
belaran@999 | 13538 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew bad.patch</userinput> |
belaran@999 | 13539 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 13540 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> |
belaran@999 | 13541 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 13542 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput> |
belaran@999 | 13543 abort: cannot delete applied patch bad.patch |
belaran@999 | 13544 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop</userinput> |
belaran@999 | 13545 patch queue now empty |
belaran@999 | 13546 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qdelete bad.patch</userinput> |
belaran@999 | 13547 </screen> |
belaran@999 | 13548 <!-- END ch11/qdelete.go --> |
belaran@999 | 13549 |
belaran@999 | 13550 </sect2> |
belaran@999 | 13551 |
belaran@999 | 13552 <sect2> |
belaran@999 | 13553 <title>Converting to and from permanent revisions</title> |
belaran@999 | 13554 |
belaran@999 | 13555 <para id="x_6dd">Once you're done working on a patch and want to |
belaran@999 | 13556 turn it into a permanent changeset, use the <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command. Pass a revision |
belaran@999 | 13557 to the command to identify the patch that you want to turn into |
belaran@999 | 13558 a regular changeset; this patch must already be applied.</para> |
belaran@999 | 13559 |
belaran@999 | 13560 <!-- BEGIN ch11/qdelete.convert --> |
belaran@999 | 13561 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew good.patch</userinput> |
belaran@999 | 13562 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo a > a</userinput> |
belaran@999 | 13563 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add a</userinput> |
belaran@999 | 13564 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh -m 'Good change'</userinput> |
belaran@999 | 13565 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qfinish tip</userinput> |
belaran@999 | 13566 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> |
belaran@999 | 13567 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip --style=compact</userinput> |
belaran@999 | 13568 0[tip] 32fc5ce6b092 2009-08-16 14:04 +0000 bos |
belaran@999 | 13569 Good change |
belaran@999 | 13570 |
belaran@999 | 13571 </screen> |
belaran@999 | 13572 <!-- END ch11/qdelete.convert --> |
belaran@999 | 13573 |
belaran@999 | 13574 |
belaran@999 | 13575 <para id="x_6e0">The <command role="hg-ext-mq" moreinfo="none">hg qfinish</command> command |
belaran@999 | 13576 accepts an <option>--all</option> or <option>-a</option> |
belaran@999 | 13577 option, which turns all applied patches into regular |
belaran@999 | 13578 changesets.</para> |
belaran@999 | 13579 |
belaran@999 | 13580 <para id="x_6de">It is also possible to turn an existing changeset into a |
belaran@999 | 13581 patch, by passing the <option>-r</option> option to <command role="hg-ext-mq" moreinfo="none">hg qimport</command>.</para> |
belaran@999 | 13582 |
belaran@999 | 13583 <!-- BEGIN ch11/qdelete.import --> |
belaran@999 | 13584 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qimport -r tip</userinput> |
belaran@999 | 13585 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> |
belaran@999 | 13586 0.diff |
belaran@999 | 13587 </screen> |
belaran@999 | 13588 <!-- END ch11/qdelete.import --> |
belaran@999 | 13589 |
belaran@999 | 13590 |
belaran@999 | 13591 <para id="x_6df">Note that it only makes sense to convert a changeset into |
belaran@999 | 13592 a patch if you have not propagated that changeset into any |
belaran@999 | 13593 other repositories. The imported changeset's ID will change |
belaran@999 | 13594 every time you refresh the patch, which will make Mercurial |
belaran@999 | 13595 treat it as unrelated to the original changeset if you have |
belaran@999 | 13596 pushed it somewhere else.</para> |
belaran@999 | 13597 </sect2> |
belaran@999 | 13598 </sect1> |
belaran@999 | 13599 |
belaran@999 | 13600 <sect1 id="sec:mq:perf"> |
belaran@999 | 13601 <title>Getting the best performance out of MQ</title> |
belaran@999 | 13602 |
belaran@999 | 13603 <para id="x_403">MQ is very efficient at handling a large number |
belaran@999 | 13604 of patches. I ran some performance experiments in mid-2006 for a |
belaran@999 | 13605 talk that I gave at the 2006 EuroPython conference (on modern |
belaran@999 | 13606 hardware, you should expect better performance than you'll see |
belaran@999 | 13607 below). I used as my data set the Linux 2.6.17-mm1 patch |
belaran@999 | 13608 series, which consists of 1,738 patches. I applied these on top |
belaran@999 | 13609 of a Linux kernel repository containing all 27,472 revisions |
belaran@999 | 13610 between Linux 2.6.12-rc2 and Linux 2.6.17.</para> |
belaran@999 | 13611 |
belaran@999 | 13612 <para id="x_404">On my old, slow laptop, I was able to <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> all |
belaran@999 | 13613 1,738 patches in 3.5 minutes, and <command role="hg-cmd" moreinfo="none">hg qpop |
belaran@999 | 13614 <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> |
belaran@999 | 13615 them all in 30 seconds. (On a newer laptop, the time to push |
belaran@999 | 13616 all patches dropped to two minutes.) I could <command role="hg-ext-mq" moreinfo="none">qrefresh</command> one of the biggest patches |
belaran@999 | 13617 (which made 22,779 lines of changes to 287 files) in 6.6 |
belaran@999 | 13618 seconds.</para> |
belaran@999 | 13619 |
belaran@999 | 13620 <para id="x_405">Clearly, MQ is well suited to working in large trees, but |
belaran@999 | 13621 there are a few tricks you can use to get the best performance |
belaran@999 | 13622 of it.</para> |
belaran@999 | 13623 |
belaran@999 | 13624 <para id="x_406">First of all, try to <quote>batch</quote> operations |
belaran@999 | 13625 together. Every time you run <command role="hg-ext-mq" moreinfo="none">qpush</command> or <command role="hg-ext-mq" moreinfo="none">qpop</command>, these commands scan the |
belaran@999 | 13626 working directory once to make sure you haven't made some |
belaran@999 | 13627 changes and then forgotten to run <command role="hg-ext-mq" moreinfo="none">qrefresh</command>. On a small tree, the |
belaran@999 | 13628 time that this scan takes is unnoticeable. However, on a |
belaran@999 | 13629 medium-sized tree (containing tens of thousands of files), it |
belaran@999 | 13630 can take a second or more.</para> |
belaran@999 | 13631 |
belaran@999 | 13632 <para id="x_407">The <command role="hg-ext-mq" moreinfo="none">qpush</command> and <command role="hg-ext-mq" moreinfo="none">qpop</command> commands allow you to push and |
belaran@999 | 13633 pop multiple patches at a time. You can identify the |
belaran@999 | 13634 <quote>destination patch</quote> that you want to end up at. |
belaran@999 | 13635 When you <command role="hg-ext-mq" moreinfo="none">qpush</command> with a |
belaran@999 | 13636 destination specified, it will push patches until that patch is |
belaran@999 | 13637 at the top of the applied stack. When you <command role="hg-ext-mq" moreinfo="none">qpop</command> to a destination, MQ will pop |
belaran@999 | 13638 patches until the destination patch is at the top.</para> |
belaran@999 | 13639 |
belaran@999 | 13640 <para id="x_408">You can identify a destination patch using either the name |
belaran@999 | 13641 of the patch, or by number. If you use numeric addressing, |
belaran@999 | 13642 patches are counted from zero; this means that the first patch |
belaran@999 | 13643 is zero, the second is one, and so on.</para> |
belaran@999 | 13644 </sect1> |
belaran@999 | 13645 |
belaran@999 | 13646 <sect1 id="sec:mq:merge"> |
belaran@999 | 13647 <title>Updating your patches when the underlying code |
belaran@999 | 13648 changes</title> |
belaran@999 | 13649 |
belaran@999 | 13650 <para id="x_409">It's common to have a stack of patches on top of an |
belaran@999 | 13651 underlying repository that you don't modify directly. If you're |
belaran@999 | 13652 working on changes to third-party code, or on a feature that is |
belaran@999 | 13653 taking longer to develop than the rate of change of the code |
belaran@999 | 13654 beneath, you will often need to sync up with the underlying |
belaran@999 | 13655 code, and fix up any hunks in your patches that no longer apply. |
belaran@999 | 13656 This is called <emphasis>rebasing</emphasis> your patch |
belaran@999 | 13657 series.</para> |
belaran@999 | 13658 |
belaran@999 | 13659 <para id="x_40a">The simplest way to do this is to <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13660 qpop <option role="hg-ext-mq-cmd-qpop-opt">hg |
belaran@999 | 13661 -a</option></command> your patches, then <command role="hg-cmd" moreinfo="none">hg pull</command> changes into the underlying |
belaran@999 | 13662 repository, and finally <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your |
belaran@999 | 13663 patches again. MQ will stop pushing any time it runs across a |
belaran@999 | 13664 patch that fails to apply during conflicts, allowing you to fix |
belaran@999 | 13665 your conflicts, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the |
belaran@999 | 13666 affected patch, and continue pushing until you have fixed your |
belaran@999 | 13667 entire stack.</para> |
belaran@999 | 13668 |
belaran@999 | 13669 <para id="x_40b">This approach is easy to use and works well if you don't |
belaran@999 | 13670 expect changes to the underlying code to affect how well your |
belaran@999 | 13671 patches apply. If your patch stack touches code that is modified |
belaran@999 | 13672 frequently or invasively in the underlying repository, however, |
belaran@999 | 13673 fixing up rejected hunks by hand quickly becomes |
belaran@999 | 13674 tiresome.</para> |
belaran@999 | 13675 |
belaran@999 | 13676 <para id="x_40c">It's possible to partially automate the rebasing process. |
belaran@999 | 13677 If your patches apply cleanly against some revision of the |
belaran@999 | 13678 underlying repo, MQ can use this information to help you to |
belaran@999 | 13679 resolve conflicts between your patches and a different |
belaran@999 | 13680 revision.</para> |
belaran@999 | 13681 |
belaran@999 | 13682 <para id="x_40d">The process is a little involved.</para> |
belaran@999 | 13683 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 13684 <listitem><para id="x_40e">To begin, <command role="hg-cmd" moreinfo="none">hg qpush |
belaran@999 | 13685 -a</command> all of your patches on top of the revision |
belaran@999 | 13686 where you know that they apply cleanly.</para> |
belaran@999 | 13687 </listitem> |
belaran@999 | 13688 <listitem><para id="x_40f">Save a backup copy of your patch directory using |
belaran@999 | 13689 <command role="hg-cmd" moreinfo="none">hg qsave <option role="hg-ext-mq-cmd-qsave-opt">hg -e</option> <option role="hg-ext-mq-cmd-qsave-opt">hg -c</option></command>. |
belaran@999 | 13690 This prints the name of the directory that it has saved the |
belaran@999 | 13691 patches in. It will save the patches to a directory called |
belaran@999 | 13692 <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>, where |
belaran@999 | 13693 <literal moreinfo="none">N</literal> is a small integer. It also commits a |
belaran@999 | 13694 <quote>save changeset</quote> on top of your applied |
belaran@999 | 13695 patches; this is for internal book-keeping, and records the |
belaran@999 | 13696 states of the <filename role="special" moreinfo="none">series</filename> and |
belaran@999 | 13697 <filename role="special" moreinfo="none">status</filename> files.</para> |
belaran@999 | 13698 </listitem> |
belaran@999 | 13699 <listitem><para id="x_410">Use <command role="hg-cmd" moreinfo="none">hg pull</command> to |
belaran@999 | 13700 bring new changes into the underlying repository. (Don't |
belaran@999 | 13701 run <command role="hg-cmd" moreinfo="none">hg pull -u</command>; see below |
belaran@999 | 13702 for why.)</para> |
belaran@999 | 13703 </listitem> |
belaran@999 | 13704 <listitem><para id="x_411">Update to the new tip revision, using <command role="hg-cmd" moreinfo="none">hg update <option role="hg-opt-update">-C</option></command> to override |
belaran@999 | 13705 the patches you have pushed.</para> |
belaran@999 | 13706 </listitem> |
belaran@999 | 13707 <listitem><para id="x_412">Merge all patches using <command moreinfo="none">hg qpush -m |
belaran@999 | 13708 -a</command>. The <option role="hg-ext-mq-cmd-qpush-opt">-m</option> option to |
belaran@999 | 13709 <command role="hg-ext-mq" moreinfo="none">qpush</command> tells MQ to |
belaran@999 | 13710 perform a three-way merge if the patch fails to |
belaran@999 | 13711 apply.</para> |
belaran@999 | 13712 </listitem></orderedlist> |
belaran@999 | 13713 |
belaran@999 | 13714 <para id="x_413">During the <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>, |
belaran@999 | 13715 each patch in the <filename role="special" moreinfo="none">series</filename> |
belaran@999 | 13716 file is applied normally. If a patch applies with fuzz or |
belaran@999 | 13717 rejects, MQ looks at the queue you <command role="hg-ext-mq" moreinfo="none">qsave</command>d, and performs a three-way |
belaran@999 | 13718 merge with the corresponding changeset. This merge uses |
belaran@999 | 13719 Mercurial's normal merge machinery, so it may pop up a GUI merge |
belaran@999 | 13720 tool to help you to resolve problems.</para> |
belaran@999 | 13721 |
belaran@999 | 13722 <para id="x_414">When you finish resolving the effects of a patch, MQ |
belaran@999 | 13723 refreshes your patch based on the result of the merge.</para> |
belaran@999 | 13724 |
belaran@999 | 13725 <para id="x_415">At the end of this process, your repository will have one |
belaran@999 | 13726 extra head from the old patch queue, and a copy of the old patch |
belaran@999 | 13727 queue will be in <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename>. You can remove the |
belaran@999 | 13728 extra head using <command role="hg-cmd" moreinfo="none">hg qpop -a -n |
belaran@999 | 13729 patches.N</command> or <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13730 strip</command>. You can delete <filename role="special" class="directory" moreinfo="none">.hg/patches.N</filename> once you are sure |
belaran@999 | 13731 that you no longer need it as a backup.</para> |
belaran@999 | 13732 </sect1> |
belaran@999 | 13733 |
belaran@999 | 13734 <sect1> |
belaran@999 | 13735 <title>Identifying patches</title> |
belaran@999 | 13736 |
belaran@999 | 13737 <para id="x_416">MQ commands that work with patches let you refer to a patch |
belaran@999 | 13738 either by using its name or by a number. By name is obvious |
belaran@999 | 13739 enough; pass the name <filename moreinfo="none">foo.patch</filename> to <command role="hg-ext-mq" moreinfo="none">qpush</command>, for example, and it will |
belaran@999 | 13740 push patches until <filename moreinfo="none">foo.patch</filename> is |
belaran@999 | 13741 applied.</para> |
belaran@999 | 13742 |
belaran@999 | 13743 <para id="x_417">As a shortcut, you can refer to a patch using both a name |
belaran@999 | 13744 and a numeric offset; <literal moreinfo="none">foo.patch-2</literal> means |
belaran@999 | 13745 <quote>two patches before <literal moreinfo="none">foo.patch</literal></quote>, |
belaran@999 | 13746 while <literal moreinfo="none">bar.patch+4</literal> means <quote>four patches |
belaran@999 | 13747 after <literal moreinfo="none">bar.patch</literal></quote>.</para> |
belaran@999 | 13748 |
belaran@999 | 13749 <para id="x_418">Referring to a patch by index isn't much different. The |
belaran@999 | 13750 first patch printed in the output of <command role="hg-ext-mq" moreinfo="none">qseries</command> is patch zero (yes, it's |
belaran@999 | 13751 one of those start-at-zero counting systems); the second is |
belaran@999 | 13752 patch one; and so on.</para> |
belaran@999 | 13753 |
belaran@999 | 13754 <para id="x_419">MQ also makes it easy to work with patches when you are |
belaran@999 | 13755 using normal Mercurial commands. Every command that accepts a |
belaran@999 | 13756 changeset ID will also accept the name of an applied patch. MQ |
belaran@999 | 13757 augments the tags normally in the repository with an eponymous |
belaran@999 | 13758 one for each applied patch. In addition, the special tags |
belaran@999 | 13759 <literal role="tag" moreinfo="none">qbase</literal> and |
belaran@999 | 13760 <literal role="tag" moreinfo="none">qtip</literal> identify |
belaran@999 | 13761 the <quote>bottom-most</quote> and topmost applied patches, |
belaran@999 | 13762 respectively.</para> |
belaran@999 | 13763 |
belaran@999 | 13764 <para id="x_41a">These additions to Mercurial's normal tagging capabilities |
belaran@999 | 13765 make dealing with patches even more of a breeze.</para> |
belaran@999 | 13766 <itemizedlist> |
belaran@999 | 13767 <listitem><para id="x_41b">Want to patchbomb a mailing list with your |
belaran@999 | 13768 latest series of changes?</para> |
belaran@999 | 13769 <programlisting format="linespecific">hg email qbase:qtip</programlisting> |
belaran@999 | 13770 <para id="x_41c"> (Don't know what <quote>patchbombing</quote> is? See |
belaran@999 | 13771 <xref linkend="sec:hgext:patchbomb"/>.)</para> |
belaran@999 | 13772 </listitem> |
belaran@999 | 13773 <listitem><para id="x_41d">Need to see all of the patches since |
belaran@999 | 13774 <literal moreinfo="none">foo.patch</literal> that have touched files in a |
belaran@999 | 13775 subdirectory of your tree?</para> |
belaran@999 | 13776 <programlisting format="linespecific">hg log -r foo.patch:qtip subdir</programlisting> |
belaran@999 | 13777 </listitem> |
belaran@999 | 13778 </itemizedlist> |
belaran@999 | 13779 |
belaran@999 | 13780 <para id="x_41e">Because MQ makes the names of patches available to the rest |
belaran@999 | 13781 of Mercurial through its normal internal tag machinery, you |
belaran@999 | 13782 don't need to type in the entire name of a patch when you want |
belaran@999 | 13783 to identify it by name.</para> |
belaran@999 | 13784 |
belaran@999 | 13785 <para id="x_41f">Another nice consequence of representing patch names as tags |
belaran@999 | 13786 is that when you run the <command role="hg-cmd" moreinfo="none">hg log</command> |
belaran@999 | 13787 command, it will display a patch's name as a tag, simply as part |
belaran@999 | 13788 of its normal output. This makes it easy to visually |
belaran@999 | 13789 distinguish applied patches from underlying |
belaran@999 | 13790 <quote>normal</quote> revisions. The following example shows a |
belaran@999 | 13791 few normal Mercurial commands in use with applied |
belaran@999 | 13792 patches.</para> |
belaran@999 | 13793 |
belaran@999 | 13794 <!-- BEGIN mq.id.output --> |
belaran@999 | 13795 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qapplied</userinput> |
belaran@999 | 13796 first.patch |
belaran@999 | 13797 second.patch |
belaran@999 | 13798 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg log -r qbase:qtip</userinput> |
belaran@999 | 13799 changeset: 1:c3bcf3b7335a |
belaran@999 | 13800 tag: first.patch |
belaran@999 | 13801 tag: qbase |
belaran@999 | 13802 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 13803 date: Sun Aug 16 14:05:08 2009 +0000 |
belaran@999 | 13804 summary: [mq]: first.patch |
belaran@999 | 13805 |
belaran@999 | 13806 changeset: 2:d189ba63b5f7 |
belaran@999 | 13807 tag: qtip |
belaran@999 | 13808 tag: second.patch |
belaran@999 | 13809 tag: tip |
belaran@999 | 13810 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 13811 date: Sun Aug 16 14:05:09 2009 +0000 |
belaran@999 | 13812 summary: [mq]: second.patch |
belaran@999 | 13813 |
belaran@999 | 13814 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg export second.patch</userinput> |
belaran@999 | 13815 # HG changeset patch |
belaran@999 | 13816 # User Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 13817 # Date 1250431509 0 |
belaran@999 | 13818 # Node ID d189ba63b5f7427f9644663c01fc16fe80399c65 |
belaran@999 | 13819 # Parent c3bcf3b7335afc0a250e85c51a1266d35d43a545 |
belaran@999 | 13820 [mq]: second.patch |
belaran@999 | 13821 |
belaran@999 | 13822 diff -r c3bcf3b7335a -r d189ba63b5f7 other.c |
belaran@999 | 13823 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 |
belaran@999 | 13824 +++ b/other.c Sun Aug 16 14:05:09 2009 +0000 |
belaran@999 | 13825 @@ -0,0 +1,1 @@ |
belaran@999 | 13826 +double u; |
belaran@999 | 13827 </screen> |
belaran@999 | 13828 <!-- END mq.id.output --> |
belaran@999 | 13829 |
belaran@999 | 13830 </sect1> |
belaran@999 | 13831 |
belaran@999 | 13832 <sect1> |
belaran@999 | 13833 <title>Useful things to know about</title> |
belaran@999 | 13834 |
belaran@999 | 13835 <para id="x_420">There are a number of aspects of MQ usage that don't fit |
belaran@999 | 13836 tidily into sections of their own, but that are good to know. |
belaran@999 | 13837 Here they are, in one place.</para> |
belaran@999 | 13838 |
belaran@999 | 13839 <itemizedlist> |
belaran@999 | 13840 <listitem><para id="x_421">Normally, when you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the changeset |
belaran@999 | 13841 that represents the patch after the pop/push will have a |
belaran@999 | 13842 <emphasis>different identity</emphasis> than the changeset |
belaran@999 | 13843 that represented the hash beforehand. See <xref linkend="sec:mqref:cmd:qpush"/> for |
belaran@999 | 13844 information as to why this is.</para> |
belaran@999 | 13845 </listitem> |
belaran@999 | 13846 <listitem><para id="x_422">It's not a good idea to <command role="hg-cmd" moreinfo="none">hg merge</command> changes from another |
belaran@999 | 13847 branch with a patch changeset, at least if you want to |
belaran@999 | 13848 maintain the <quote>patchiness</quote> of that changeset and |
belaran@999 | 13849 changesets below it on the patch stack. If you try to do |
belaran@999 | 13850 this, it will appear to succeed, but MQ will become |
belaran@999 | 13851 confused.</para> |
belaran@999 | 13852 </listitem></itemizedlist> |
belaran@999 | 13853 </sect1> |
belaran@999 | 13854 |
belaran@999 | 13855 <sect1 id="sec:mq:repo"> |
belaran@999 | 13856 <title>Managing patches in a repository</title> |
belaran@999 | 13857 |
belaran@999 | 13858 <para id="x_423">Because MQ's <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory resides |
belaran@999 | 13859 outside a Mercurial repository's working directory, the |
belaran@999 | 13860 <quote>underlying</quote> Mercurial repository knows nothing |
belaran@999 | 13861 about the management or presence of patches.</para> |
belaran@999 | 13862 |
belaran@999 | 13863 <para id="x_424">This presents the interesting possibility of managing the |
belaran@999 | 13864 contents of the patch directory as a Mercurial repository in its |
belaran@999 | 13865 own right. This can be a useful way to work. For example, you |
belaran@999 | 13866 can work on a patch for a while, <command role="hg-ext-mq" moreinfo="none">qrefresh</command> it, then <command role="hg-cmd" moreinfo="none">hg commit</command> the current state of the |
belaran@999 | 13867 patch. This lets you <quote>roll back</quote> to that version |
belaran@999 | 13868 of the patch later on.</para> |
belaran@999 | 13869 |
belaran@999 | 13870 <para id="x_425">You can then share different versions of the same patch |
belaran@999 | 13871 stack among multiple underlying repositories. I use this when I |
belaran@999 | 13872 am developing a Linux kernel feature. I have a pristine copy of |
belaran@999 | 13873 my kernel sources for each of several CPU architectures, and a |
belaran@999 | 13874 cloned repository under each that contains the patches I am |
belaran@999 | 13875 working on. When I want to test a change on a different |
belaran@999 | 13876 architecture, I push my current patches to the patch repository |
belaran@999 | 13877 associated with that kernel tree, pop and push all of my |
belaran@999 | 13878 patches, and build and test that kernel.</para> |
belaran@999 | 13879 |
belaran@999 | 13880 <para id="x_426">Managing patches in a repository makes it possible for |
belaran@999 | 13881 multiple developers to work on the same patch series without |
belaran@999 | 13882 colliding with each other, all on top of an underlying source |
belaran@999 | 13883 base that they may or may not control.</para> |
belaran@999 | 13884 |
belaran@999 | 13885 <sect2> |
belaran@999 | 13886 <title>MQ support for patch repositories</title> |
belaran@999 | 13887 |
belaran@999 | 13888 <para id="x_427">MQ helps you to work with the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a |
belaran@999 | 13889 repository; when you prepare a repository for working with |
belaran@999 | 13890 patches using <command role="hg-ext-mq" moreinfo="none">qinit</command>, you |
belaran@999 | 13891 can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg |
belaran@999 | 13892 -c</option> option to create the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory as a |
belaran@999 | 13893 Mercurial repository.</para> |
belaran@999 | 13894 |
belaran@999 | 13895 <note> |
belaran@999 | 13896 <para id="x_428"> If you forget to use the <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you |
belaran@999 | 13897 can simply go into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory at any |
belaran@999 | 13898 time and run <command role="hg-cmd" moreinfo="none">hg init</command>. |
belaran@999 | 13899 Don't forget to add an entry for the <filename role="special" moreinfo="none">status</filename> file to the <filename role="special" moreinfo="none">.hgignore</filename> file, though</para> |
belaran@999 | 13900 |
belaran@999 | 13901 <para id="x_429"> (<command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command> |
belaran@999 | 13902 does this for you automatically); you |
belaran@999 | 13903 <emphasis>really</emphasis> don't want to manage the |
belaran@999 | 13904 <filename role="special" moreinfo="none">status</filename> file.</para> |
belaran@999 | 13905 </note> |
belaran@999 | 13906 |
belaran@999 | 13907 <para id="x_42a">As a convenience, if MQ notices that the <filename class="directory" moreinfo="none">.hg/patches</filename> directory is a |
belaran@999 | 13908 repository, it will automatically <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13909 add</command> every patch that you create and import.</para> |
belaran@999 | 13910 |
belaran@999 | 13911 <para id="x_42b">MQ provides a shortcut command, <command role="hg-ext-mq" moreinfo="none">qcommit</command>, that runs <command role="hg-cmd" moreinfo="none">hg commit</command> in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> |
belaran@999 | 13912 directory. This saves some bothersome typing.</para> |
belaran@999 | 13913 |
belaran@999 | 13914 <para id="x_42c">Finally, as a convenience to manage the patch directory, |
belaran@999 | 13915 you can define the alias <command moreinfo="none">mq</command> on Unix |
belaran@999 | 13916 systems. For example, on Linux systems using the |
belaran@999 | 13917 <command moreinfo="none">bash</command> shell, you can include the following |
belaran@999 | 13918 snippet in your <filename role="home" moreinfo="none">~/.bashrc</filename>.</para> |
belaran@999 | 13919 |
belaran@999 | 13920 <programlisting format="linespecific">alias mq=`hg -R $(hg root)/.hg/patches'</programlisting> |
belaran@999 | 13921 |
belaran@999 | 13922 <para id="x_42d">You can then issue commands of the form <command moreinfo="none">mq |
belaran@999 | 13923 pull</command> from the main repository.</para> |
belaran@999 | 13924 </sect2> |
belaran@999 | 13925 |
belaran@999 | 13926 <sect2> |
belaran@999 | 13927 <title>A few things to watch out for</title> |
belaran@999 | 13928 |
belaran@999 | 13929 <para id="x_42e">MQ's support for working with a repository full of patches |
belaran@999 | 13930 is limited in a few small respects.</para> |
belaran@999 | 13931 |
belaran@999 | 13932 <para id="x_42f">MQ cannot automatically detect changes that you make to |
belaran@999 | 13933 the patch directory. If you <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13934 pull</command>, manually edit, or <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 13935 update</command> changes to patches or the <filename role="special" moreinfo="none">series</filename> file, you will have to |
belaran@999 | 13936 <command role="hg-cmd" moreinfo="none">hg qpop <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and |
belaran@999 | 13937 then <command role="hg-cmd" moreinfo="none">hg qpush <option role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in |
belaran@999 | 13938 the underlying repository to see those changes show up there. |
belaran@999 | 13939 If you forget to do this, you can confuse MQ's idea of which |
belaran@999 | 13940 patches are applied.</para> |
belaran@999 | 13941 |
belaran@999 | 13942 </sect2> |
belaran@999 | 13943 </sect1> |
belaran@999 | 13944 <sect1 id="sec:mq:tools"> |
belaran@999 | 13945 <title>Third party tools for working with patches</title> |
belaran@999 | 13946 |
belaran@999 | 13947 <para id="x_430">Once you've been working with patches for a while, you'll |
belaran@999 | 13948 find yourself hungry for tools that will help you to understand |
belaran@999 | 13949 and manipulate the patches you're dealing with.</para> |
belaran@999 | 13950 |
belaran@999 | 13951 <para id="x_431">The <command moreinfo="none">diffstat</command> command |
belaran@999 | 13952 <citation>web:diffstat</citation> generates a histogram of the |
belaran@999 | 13953 modifications made to each file in a patch. It provides a good |
belaran@999 | 13954 way to <quote>get a sense of</quote> a patch—which files |
belaran@999 | 13955 it affects, and how much change it introduces to each file and |
belaran@999 | 13956 as a whole. (I find that it's a good idea to use |
belaran@999 | 13957 <command moreinfo="none">diffstat</command>'s <option role="cmd-opt-diffstat">-p</option> option as a matter of |
belaran@999 | 13958 course, as otherwise it will try to do clever things with |
belaran@999 | 13959 prefixes of file names that inevitably confuse at least |
belaran@999 | 13960 me.)</para> |
belaran@999 | 13961 |
belaran@999 | 13962 <!-- BEGIN mq.tools.tools --> |
belaran@999 | 13963 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">diffstat -p1 remove-redundant-null-checks.patch</userinput> |
belaran@999 | 13964 drivers/char/agp/sgi-agp.c | 5 ++--- |
belaran@999 | 13965 drivers/char/hvcs.c | 11 +++++------ |
belaran@999 | 13966 drivers/message/fusion/mptfc.c | 6 ++---- |
belaran@999 | 13967 drivers/message/fusion/mptsas.c | 3 +-- |
belaran@999 | 13968 drivers/net/fs_enet/fs_enet-mii.c | 3 +-- |
belaran@999 | 13969 drivers/net/wireless/ipw2200.c | 22 ++++++---------------- |
belaran@999 | 13970 drivers/scsi/libata-scsi.c | 4 +--- |
belaran@999 | 13971 drivers/video/au1100fb.c | 3 +-- |
belaran@999 | 13972 8 files changed, 19 insertions(+), 38 deletions(-) |
belaran@999 | 13973 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">filterdiff -i '*/video/*' remove-redundant-null-checks.patch</userinput> |
belaran@999 | 13974 --- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers |
belaran@999 | 13975 +++ a/drivers/video/au1100fb.c |
belaran@999 | 13976 @@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void) |
belaran@999 | 13977 { |
belaran@999 | 13978 driver_unregister(&au1100fb_driver); |
belaran@999 | 13979 |
belaran@999 | 13980 - if (drv_info.opt_mode) |
belaran@999 | 13981 - kfree(drv_info.opt_mode); |
belaran@999 | 13982 + kfree(drv_info.opt_mode); |
belaran@999 | 13983 } |
belaran@999 | 13984 |
belaran@999 | 13985 module_init(au1100fb_init); |
belaran@999 | 13986 </screen> |
belaran@999 | 13987 <!-- END mq.tools.tools --> |
belaran@999 | 13988 |
belaran@999 | 13989 |
belaran@999 | 13990 <para id="x_432">The <literal role="package" moreinfo="none">patchutils</literal> package |
belaran@999 | 13991 <citation>web:patchutils</citation> is invaluable. It provides a |
belaran@999 | 13992 set of small utilities that follow the <quote>Unix |
belaran@999 | 13993 philosophy;</quote> each does one useful thing with a patch. |
belaran@999 | 13994 The <literal role="package" moreinfo="none">patchutils</literal> command I use |
belaran@999 | 13995 most is <command moreinfo="none">filterdiff</command>, which extracts subsets |
belaran@999 | 13996 from a patch file. For example, given a patch that modifies |
belaran@999 | 13997 hundreds of files across dozens of directories, a single |
belaran@999 | 13998 invocation of <command moreinfo="none">filterdiff</command> can generate a |
belaran@999 | 13999 smaller patch that only touches files whose names match a |
belaran@999 | 14000 particular glob pattern. See <xref linkend="mq-collab:tips:interdiff"/> for another |
belaran@999 | 14001 example.</para> |
belaran@999 | 14002 |
belaran@999 | 14003 </sect1> |
belaran@999 | 14004 <sect1> |
belaran@999 | 14005 <title>Good ways to work with patches</title> |
belaran@999 | 14006 |
belaran@999 | 14007 <para id="x_433">Whether you are working on a patch series to submit to a |
belaran@999 | 14008 free software or open source project, or a series that you |
belaran@999 | 14009 intend to treat as a sequence of regular changesets when you're |
belaran@999 | 14010 done, you can use some simple techniques to keep your work well |
belaran@999 | 14011 organized.</para> |
belaran@999 | 14012 |
belaran@999 | 14013 <para id="x_434">Give your patches descriptive names. A good name for a |
belaran@999 | 14014 patch might be <filename moreinfo="none">rework-device-alloc.patch</filename>, |
belaran@999 | 14015 because it will immediately give you a hint what the purpose of |
belaran@999 | 14016 the patch is. Long names shouldn't be a problem; you won't be |
belaran@999 | 14017 typing the names often, but you <emphasis>will</emphasis> be |
belaran@999 | 14018 running commands like <command role="hg-ext-mq" moreinfo="none">qapplied</command> and <command role="hg-ext-mq" moreinfo="none">qtop</command> over and over. Good naming |
belaran@999 | 14019 becomes especially important when you have a number of patches |
belaran@999 | 14020 to work with, or if you are juggling a number of different tasks |
belaran@999 | 14021 and your patches only get a fraction of your attention.</para> |
belaran@999 | 14022 |
belaran@999 | 14023 <para id="x_435">Be aware of what patch you're working on. Use the <command role="hg-ext-mq" moreinfo="none">qtop</command> command and skim over the text |
belaran@999 | 14024 of your patches frequently—for example, using <command role="hg-cmd" moreinfo="none">hg tip <option role="hg-opt-tip">-p</option></command>)—to be sure |
belaran@999 | 14025 of where you stand. I have several times worked on and <command role="hg-ext-mq" moreinfo="none">qrefresh</command>ed a patch other than the |
belaran@999 | 14026 one I intended, and it's often tricky to migrate changes into |
belaran@999 | 14027 the right patch after making them in the wrong one.</para> |
belaran@999 | 14028 |
belaran@999 | 14029 <para id="x_436">For this reason, it is very much worth investing a little |
belaran@999 | 14030 time to learn how to use some of the third-party tools I |
belaran@999 | 14031 described in <xref linkend="sec:mq:tools"/>, |
belaran@999 | 14032 particularly |
belaran@999 | 14033 <command moreinfo="none">diffstat</command> and <command moreinfo="none">filterdiff</command>. |
belaran@999 | 14034 The former will give you a quick idea of what changes your patch |
belaran@999 | 14035 is making, while the latter makes it easy to splice hunks |
belaran@999 | 14036 selectively out of one patch and into another.</para> |
belaran@999 | 14037 |
belaran@999 | 14038 </sect1> |
belaran@999 | 14039 <sect1> |
belaran@999 | 14040 <title>MQ cookbook</title> |
belaran@999 | 14041 |
belaran@999 | 14042 <sect2> |
belaran@999 | 14043 <title>Manage <quote>trivial</quote> patches</title> |
belaran@999 | 14044 |
belaran@999 | 14045 <para id="x_437">Because the overhead of dropping files into a new |
belaran@999 | 14046 Mercurial repository is so low, it makes a lot of sense to |
belaran@999 | 14047 manage patches this way even if you simply want to make a few |
belaran@999 | 14048 changes to a source tarball that you downloaded.</para> |
belaran@999 | 14049 |
belaran@999 | 14050 <para id="x_438">Begin by downloading and unpacking the source tarball, and |
belaran@999 | 14051 turning it into a Mercurial repository.</para> |
belaran@999 | 14052 |
belaran@999 | 14053 <!-- BEGIN mq.tarball.download --> |
belaran@999 | 14054 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.5.tar.bz2</userinput> |
belaran@999 | 14055 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.5.tar.bz2</userinput> |
belaran@999 | 14056 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.5</userinput> |
belaran@999 | 14057 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg init</userinput> |
belaran@999 | 14058 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit -q --addremove --message netplug-1.2.5</userinput> |
belaran@999 | 14059 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 14060 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug</userinput> |
belaran@999 | 14061 updating working directory |
belaran@999 | 14062 18 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 14063 </screen> |
belaran@999 | 14064 <!-- END mq.tarball.download --> |
belaran@999 | 14065 |
belaran@999 | 14066 |
belaran@999 | 14067 <para id="x_439">Continue by creating a patch stack and making your |
belaran@999 | 14068 changes.</para> |
belaran@999 | 14069 |
belaran@999 | 14070 <!-- BEGIN mq.tarball.qinit --> |
belaran@999 | 14071 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug</userinput> |
belaran@999 | 14072 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> |
belaran@999 | 14073 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew -m 'fix build problem with gcc 4' build-fix.patch</userinput> |
belaran@999 | 14074 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c</userinput> |
belaran@999 | 14075 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 14076 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg tip -p</userinput> |
belaran@999 | 14077 changeset: 1:eeab56666c54 |
belaran@999 | 14078 tag: qtip |
belaran@999 | 14079 tag: build-fix.patch |
belaran@999 | 14080 tag: tip |
belaran@999 | 14081 tag: qbase |
belaran@999 | 14082 user: Bryan O'Sullivan <bos@serpentine.com> |
belaran@999 | 14083 date: Sun Aug 16 14:05:10 2009 +0000 |
belaran@999 | 14084 summary: fix build problem with gcc 4 |
belaran@999 | 14085 |
belaran@999 | 14086 diff -r 1f6afe9a2d68 -r eeab56666c54 netlink.c |
belaran@999 | 14087 --- a/netlink.c Sun Aug 16 14:05:09 2009 +0000 |
belaran@999 | 14088 +++ b/netlink.c Sun Aug 16 14:05:10 2009 +0000 |
belaran@999 | 14089 @@ -275,7 +275,7 @@ |
belaran@999 | 14090 exit(1); |
belaran@999 | 14091 } |
belaran@999 | 14092 |
belaran@999 | 14093 - int addr_len = sizeof(addr); |
belaran@999 | 14094 + socklen_t addr_len = sizeof(addr); |
belaran@999 | 14095 |
belaran@999 | 14096 if (getsockname(fd, (struct sockaddr *) &addr, &addr_len) == -1) { |
belaran@999 | 14097 do_log(LOG_ERR, "Could not get socket details: %m"); |
belaran@999 | 14098 |
belaran@999 | 14099 </screen> |
belaran@999 | 14100 <!-- END mq.tarball.qinit --> |
belaran@999 | 14101 |
belaran@999 | 14102 |
belaran@999 | 14103 <para id="x_43a">Let's say a few weeks or months pass, and your package |
belaran@999 | 14104 author releases a new version. First, bring their changes |
belaran@999 | 14105 into the repository.</para> |
belaran@999 | 14106 |
belaran@999 | 14107 <!-- BEGIN mq.tarball.newsource --> |
belaran@999 | 14108 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> |
belaran@999 | 14109 patch queue now empty |
belaran@999 | 14110 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 14111 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">download netplug-1.2.8.tar.bz2</userinput> |
belaran@999 | 14112 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg clone netplug-1.2.5 netplug-1.2.8</userinput> |
belaran@999 | 14113 updating working directory |
belaran@999 | 14114 18 files updated, 0 files merged, 0 files removed, 0 files unresolved |
belaran@999 | 14115 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput> |
belaran@999 | 14116 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg locate -0 | xargs -0 rm</userinput> |
belaran@999 | 14117 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ..</userinput> |
belaran@999 | 14118 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">tar jxf netplug-1.2.8.tar.bz2</userinput> |
belaran@999 | 14119 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd netplug-1.2.8</userinput> |
belaran@999 | 14120 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg commit --addremove --message netplug-1.2.8</userinput> |
belaran@999 | 14121 </screen> |
belaran@999 | 14122 <!-- END mq.tarball.newsource --> |
belaran@999 | 14123 |
belaran@999 | 14124 |
belaran@999 | 14125 <para id="x_43b">The pipeline starting with <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 14126 locate</command> above deletes all files in the working |
belaran@999 | 14127 directory, so that <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 14128 commit</command>'s <option role="hg-opt-commit">--addremove</option> option can |
belaran@999 | 14129 actually tell which files have really been removed in the |
belaran@999 | 14130 newer version of the source.</para> |
belaran@999 | 14131 |
belaran@999 | 14132 <para id="x_43c">Finally, you can apply your patches on top of the new |
belaran@999 | 14133 tree.</para> |
belaran@999 | 14134 |
belaran@999 | 14135 <!-- BEGIN mq.tarball.repush --> |
belaran@999 | 14136 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cd ../netplug</userinput> |
belaran@999 | 14137 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg pull ../netplug-1.2.8</userinput> |
belaran@999 | 14138 pulling from ../netplug-1.2.8 |
belaran@999 | 14139 searching for changes |
belaran@999 | 14140 adding changesets |
belaran@999 | 14141 adding manifests |
belaran@999 | 14142 adding file changes |
belaran@999 | 14143 added 1 changesets with 12 changes to 12 files |
belaran@999 | 14144 (run 'hg update' to get a working copy) |
belaran@999 | 14145 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> |
belaran@999 | 14146 (working directory not at tip) |
belaran@999 | 14147 applying build-fix.patch |
belaran@999 | 14148 now at: build-fix.patch |
belaran@999 | 14149 </screen> |
belaran@999 | 14150 <!-- END mq.tarball.repush --> |
belaran@999 | 14151 |
belaran@999 | 14152 </sect2> |
belaran@999 | 14153 |
belaran@999 | 14154 <sect2 id="sec:mq:combine"> |
belaran@999 | 14155 <title>Combining entire patches</title> |
belaran@999 | 14156 |
belaran@999 | 14157 <para id="x_43d">MQ provides a command, <command role="hg-ext-mq" moreinfo="none">qfold</command> that lets you combine |
belaran@999 | 14158 entire patches. This <quote>folds</quote> the patches you |
belaran@999 | 14159 name, in the order you name them, into the topmost applied |
belaran@999 | 14160 patch, and concatenates their descriptions onto the end of its |
belaran@999 | 14161 description. The patches that you fold must be unapplied |
belaran@999 | 14162 before you fold them.</para> |
belaran@999 | 14163 |
belaran@999 | 14164 <para id="x_43e">The order in which you fold patches matters. If your |
belaran@999 | 14165 topmost applied patch is <literal moreinfo="none">foo</literal>, and you |
belaran@999 | 14166 <command role="hg-ext-mq" moreinfo="none">qfold</command> |
belaran@999 | 14167 <literal moreinfo="none">bar</literal> and <literal moreinfo="none">quux</literal> into it, |
belaran@999 | 14168 you will end up with a patch that has the same effect as if |
belaran@999 | 14169 you applied first <literal moreinfo="none">foo</literal>, then |
belaran@999 | 14170 <literal moreinfo="none">bar</literal>, followed by |
belaran@999 | 14171 <literal moreinfo="none">quux</literal>.</para> |
belaran@999 | 14172 </sect2> |
belaran@999 | 14173 |
belaran@999 | 14174 <sect2> |
belaran@999 | 14175 <title>Merging part of one patch into another</title> |
belaran@999 | 14176 |
belaran@999 | 14177 <para id="x_43f">Merging <emphasis>part</emphasis> of one patch into |
belaran@999 | 14178 another is more difficult than combining entire |
belaran@999 | 14179 patches.</para> |
belaran@999 | 14180 |
belaran@999 | 14181 <para id="x_440">If you want to move changes to entire files, you can use |
belaran@999 | 14182 <command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">-i</option> and <option role="cmd-opt-filterdiff">-x</option> options to choose the |
belaran@999 | 14183 modifications to snip out of one patch, concatenating its |
belaran@999 | 14184 output onto the end of the patch you want to merge into. You |
belaran@999 | 14185 usually won't need to modify the patch you've merged the |
belaran@999 | 14186 changes from. Instead, MQ will report some rejected hunks |
belaran@999 | 14187 when you <command role="hg-ext-mq" moreinfo="none">qpush</command> it (from |
belaran@999 | 14188 the hunks you moved into the other patch), and you can simply |
belaran@999 | 14189 <command role="hg-ext-mq" moreinfo="none">qrefresh</command> the patch to drop |
belaran@999 | 14190 the duplicate hunks.</para> |
belaran@999 | 14191 |
belaran@999 | 14192 <para id="x_441">If you have a patch that has multiple hunks modifying a |
belaran@999 | 14193 file, and you only want to move a few of those hunks, the job |
belaran@999 | 14194 becomes more messy, but you can still partly automate it. Use |
belaran@999 | 14195 <command moreinfo="none">lsdiff -nvv</command> to print some metadata about |
belaran@999 | 14196 the patch.</para> |
belaran@999 | 14197 |
belaran@999 | 14198 <!-- BEGIN mq.tools.lsdiff --> |
belaran@999 | 14199 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">lsdiff -nvv remove-redundant-null-checks.patch</userinput> |
belaran@999 | 14200 22 File #1 a/drivers/char/agp/sgi-agp.c |
belaran@999 | 14201 24 Hunk #1 static int __devinit agp_sgi_init(void) |
belaran@999 | 14202 37 File #2 a/drivers/char/hvcs.c |
belaran@999 | 14203 39 Hunk #1 static struct tty_operations hvcs_ops = |
belaran@999 | 14204 53 Hunk #2 static int hvcs_alloc_index_list(int n) |
belaran@999 | 14205 69 File #3 a/drivers/message/fusion/mptfc.c |
belaran@999 | 14206 71 Hunk #1 mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in |
belaran@999 | 14207 85 File #4 a/drivers/message/fusion/mptsas.c |
belaran@999 | 14208 87 Hunk #1 mptsas_probe_hba_phys(MPT_ADAPTER *ioc) |
belaran@999 | 14209 98 File #5 a/drivers/net/fs_enet/fs_enet-mii.c |
belaran@999 | 14210 100 Hunk #1 static struct fs_enet_mii_bus *create_bu |
belaran@999 | 14211 111 File #6 a/drivers/net/wireless/ipw2200.c |
belaran@999 | 14212 113 Hunk #1 static struct ipw_fw_error *ipw_alloc_er |
belaran@999 | 14213 126 Hunk #2 static ssize_t clear_error(struct device |
belaran@999 | 14214 140 Hunk #3 static void ipw_irq_tasklet(struct ipw_p |
belaran@999 | 14215 150 Hunk #4 static void ipw_pci_remove(struct pci_de |
belaran@999 | 14216 164 File #7 a/drivers/scsi/libata-scsi.c |
belaran@999 | 14217 166 Hunk #1 int ata_cmd_ioctl(struct scsi_device *sc |
belaran@999 | 14218 178 File #8 a/drivers/video/au1100fb.c |
belaran@999 | 14219 180 Hunk #1 void __exit au1100fb_cleanup(void) |
belaran@999 | 14220 </screen> |
belaran@999 | 14221 <!-- END mq.tools.lsdiff --> |
belaran@999 | 14222 |
belaran@999 | 14223 |
belaran@999 | 14224 <para id="x_442">This command prints three different kinds of |
belaran@999 | 14225 number:</para> |
belaran@999 | 14226 <itemizedlist> |
belaran@999 | 14227 <listitem><para id="x_443">(in the first column) a <emphasis>file |
belaran@999 | 14228 number</emphasis> to identify each file modified in the |
belaran@999 | 14229 patch;</para> |
belaran@999 | 14230 </listitem> |
belaran@999 | 14231 <listitem><para id="x_444">(on the next line, indented) the line number |
belaran@999 | 14232 within a modified file where a hunk starts; and</para> |
belaran@999 | 14233 </listitem> |
belaran@999 | 14234 <listitem><para id="x_445">(on the same line) a <emphasis>hunk |
belaran@999 | 14235 number</emphasis> to identify that hunk.</para> |
belaran@999 | 14236 </listitem></itemizedlist> |
belaran@999 | 14237 |
belaran@999 | 14238 <para id="x_446">You'll have to use some visual inspection, and reading of |
belaran@999 | 14239 the patch, to identify the file and hunk numbers you'll want, |
belaran@999 | 14240 but you can then pass them to to |
belaran@999 | 14241 <command moreinfo="none">filterdiff</command>'s <option role="cmd-opt-filterdiff">--files</option> and <option role="cmd-opt-filterdiff">--hunks</option> options, to |
belaran@999 | 14242 select exactly the file and hunk you want to extract.</para> |
belaran@999 | 14243 |
belaran@999 | 14244 <para id="x_447">Once you have this hunk, you can concatenate it onto the |
belaran@999 | 14245 end of your destination patch and continue with the remainder |
belaran@999 | 14246 of <xref linkend="sec:mq:combine"/>.</para> |
belaran@999 | 14247 |
belaran@999 | 14248 </sect2> |
belaran@999 | 14249 </sect1> |
belaran@999 | 14250 <sect1> |
belaran@999 | 14251 <title>Differences between quilt and MQ</title> |
belaran@999 | 14252 |
belaran@999 | 14253 <para id="x_448">If you are already familiar with quilt, MQ provides a |
belaran@999 | 14254 similar command set. There are a few differences in the way |
belaran@999 | 14255 that it works.</para> |
belaran@999 | 14256 |
belaran@999 | 14257 <para id="x_449">You will already have noticed that most quilt commands have |
belaran@999 | 14258 MQ counterparts that simply begin with a |
belaran@999 | 14259 <quote><literal moreinfo="none">q</literal></quote>. The exceptions are quilt's |
belaran@999 | 14260 <literal moreinfo="none">add</literal> and <literal moreinfo="none">remove</literal> commands, |
belaran@999 | 14261 the counterparts for which are the normal Mercurial <command role="hg-cmd" moreinfo="none">hg add</command> and <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 14262 remove</command> commands. There is no MQ equivalent of the |
belaran@999 | 14263 quilt <literal moreinfo="none">edit</literal> command.</para> |
belaran@999 | 14264 |
belaran@999 | 14265 </sect1> |
belaran@999 | 14266 </chapter> |
belaran@999 | 14267 |
belaran@999 | 14268 <!-- |
belaran@999 | 14269 local variables: |
belaran@999 | 14270 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 14271 end: |
belaran@999 | 14272 --> |
belaran@999 | 14273 |
belaran@999 | 14274 <!-- BEGIN ch13 --> |
belaran@999 | 14275 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 14276 |
belaran@999 | 14277 <chapter id="chap:mq-collab"> |
belaran@999 | 14278 <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?> |
belaran@999 | 14279 <title>Advanced uses of Mercurial Queues</title> |
belaran@999 | 14280 |
belaran@999 | 14281 <para id="x_15d">While it's easy to pick up straightforward uses of Mercurial |
belaran@999 | 14282 Queues, use of a little discipline and some of MQ's less |
belaran@999 | 14283 frequently used capabilities makes it possible to work in |
belaran@999 | 14284 complicated development environments.</para> |
belaran@999 | 14285 |
belaran@999 | 14286 <para id="x_15e">In this chapter, I will use as an example a technique I have |
belaran@999 | 14287 used to manage the development of an Infiniband device driver for |
belaran@999 | 14288 the Linux kernel. The driver in question is large (at least as |
belaran@999 | 14289 drivers go), with 25,000 lines of code spread across 35 source |
belaran@999 | 14290 files. It is maintained by a small team of developers.</para> |
belaran@999 | 14291 |
belaran@999 | 14292 <para id="x_15f">While much of the material in this chapter is specific to |
belaran@999 | 14293 Linux, the same principles apply to any code base for which you're |
belaran@999 | 14294 not the primary owner, and upon which you need to do a lot of |
belaran@999 | 14295 development.</para> |
belaran@999 | 14296 |
belaran@999 | 14297 <sect1> |
belaran@999 | 14298 <title>The problem of many targets</title> |
belaran@999 | 14299 |
belaran@999 | 14300 <para id="x_160">The Linux kernel changes rapidly, and has never been |
belaran@999 | 14301 internally stable; developers frequently make drastic changes |
belaran@999 | 14302 between releases. This means that a version of the driver that |
belaran@999 | 14303 works well with a particular released version of the kernel will |
belaran@999 | 14304 not even <emphasis>compile</emphasis> correctly against, |
belaran@999 | 14305 typically, any other version.</para> |
belaran@999 | 14306 |
belaran@999 | 14307 <para id="x_161">To maintain a driver, we have to keep a number of distinct |
belaran@999 | 14308 versions of Linux in mind.</para> |
belaran@999 | 14309 <itemizedlist> |
belaran@999 | 14310 <listitem><para id="x_162">One target is the main Linux kernel development |
belaran@999 | 14311 tree. Maintenance of the code is in this case partly shared |
belaran@999 | 14312 by other developers in the kernel community, who make |
belaran@999 | 14313 <quote>drive-by</quote> modifications to the driver as they |
belaran@999 | 14314 develop and refine kernel subsystems.</para> |
belaran@999 | 14315 </listitem> |
belaran@999 | 14316 <listitem><para id="x_163">We also maintain a number of |
belaran@999 | 14317 <quote>backports</quote> to older versions of the Linux |
belaran@999 | 14318 kernel, to support the needs of customers who are running |
belaran@999 | 14319 older Linux distributions that do not incorporate our |
belaran@999 | 14320 drivers. (To <emphasis>backport</emphasis> a piece of code |
belaran@999 | 14321 is to modify it to work in an older version of its target |
belaran@999 | 14322 environment than the version it was developed for.)</para> |
belaran@999 | 14323 </listitem> |
belaran@999 | 14324 <listitem><para id="x_164">Finally, we make software releases on a schedule |
belaran@999 | 14325 that is necessarily not aligned with those used by Linux |
belaran@999 | 14326 distributors and kernel developers, so that we can deliver |
belaran@999 | 14327 new features to customers without forcing them to upgrade |
belaran@999 | 14328 their entire kernels or distributions.</para> |
belaran@999 | 14329 </listitem></itemizedlist> |
belaran@999 | 14330 |
belaran@999 | 14331 <sect2> |
belaran@999 | 14332 <title>Tempting approaches that don't work well</title> |
belaran@999 | 14333 |
belaran@999 | 14334 <para id="x_165">There are two <quote>standard</quote> ways to maintain a |
belaran@999 | 14335 piece of software that has to target many different |
belaran@999 | 14336 environments.</para> |
belaran@999 | 14337 |
belaran@999 | 14338 <para id="x_166">The first is to maintain a number of branches, each |
belaran@999 | 14339 intended for a single target. The trouble with this approach |
belaran@999 | 14340 is that you must maintain iron discipline in the flow of |
belaran@999 | 14341 changes between repositories. A new feature or bug fix must |
belaran@999 | 14342 start life in a <quote>pristine</quote> repository, then |
belaran@999 | 14343 percolate out to every backport repository. Backport changes |
belaran@999 | 14344 are more limited in the branches they should propagate to; a |
belaran@999 | 14345 backport change that is applied to a branch where it doesn't |
belaran@999 | 14346 belong will probably stop the driver from compiling.</para> |
belaran@999 | 14347 |
belaran@999 | 14348 <para id="x_167">The second is to maintain a single source tree filled with |
belaran@999 | 14349 conditional statements that turn chunks of code on or off |
belaran@999 | 14350 depending on the intended target. Because these |
belaran@999 | 14351 <quote>ifdefs</quote> are not allowed in the Linux kernel |
belaran@999 | 14352 tree, a manual or automatic process must be followed to strip |
belaran@999 | 14353 them out and yield a clean tree. A code base maintained in |
belaran@999 | 14354 this fashion rapidly becomes a rat's nest of conditional |
belaran@999 | 14355 blocks that are difficult to understand and maintain.</para> |
belaran@999 | 14356 |
belaran@999 | 14357 <para id="x_168">Neither of these approaches is well suited to a situation |
belaran@999 | 14358 where you don't <quote>own</quote> the canonical copy of a |
belaran@999 | 14359 source tree. In the case of a Linux driver that is |
belaran@999 | 14360 distributed with the standard kernel, Linus's tree contains |
belaran@999 | 14361 the copy of the code that will be treated by the world as |
belaran@999 | 14362 canonical. The upstream version of <quote>my</quote> driver |
belaran@999 | 14363 can be modified by people I don't know, without me even |
belaran@999 | 14364 finding out about it until after the changes show up in |
belaran@999 | 14365 Linus's tree.</para> |
belaran@999 | 14366 |
belaran@999 | 14367 <para id="x_169">These approaches have the added weakness of making it |
belaran@999 | 14368 difficult to generate well-formed patches to submit |
belaran@999 | 14369 upstream.</para> |
belaran@999 | 14370 |
belaran@999 | 14371 <para id="x_16a">In principle, Mercurial Queues seems like a good candidate |
belaran@999 | 14372 to manage a development scenario such as the above. While |
belaran@999 | 14373 this is indeed the case, MQ contains a few added features that |
belaran@999 | 14374 make the job more pleasant.</para> |
belaran@999 | 14375 |
belaran@999 | 14376 </sect2> |
belaran@999 | 14377 </sect1> |
belaran@999 | 14378 <sect1> |
belaran@999 | 14379 <title>Conditionally applying patches with guards</title> |
belaran@999 | 14380 |
belaran@999 | 14381 <para id="x_16b">Perhaps the best way to maintain sanity with so many targets |
belaran@999 | 14382 is to be able to choose specific patches to apply for a given |
belaran@999 | 14383 situation. MQ provides a feature called <quote>guards</quote> |
belaran@999 | 14384 (which originates with quilt's <literal moreinfo="none">guards</literal> |
belaran@999 | 14385 command) that does just this. To start off, let's create a |
belaran@999 | 14386 simple repository for experimenting in.</para> |
belaran@999 | 14387 |
belaran@999 | 14388 <!-- BEGIN mq.guards.init --> |
belaran@999 | 14389 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qinit</userinput> |
belaran@999 | 14390 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew hello.patch</userinput> |
belaran@999 | 14391 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo hello > hello</userinput> |
belaran@999 | 14392 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add hello</userinput> |
belaran@999 | 14393 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 14394 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qnew goodbye.patch</userinput> |
belaran@999 | 14395 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo goodbye > goodbye</userinput> |
belaran@999 | 14396 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg add goodbye</userinput> |
belaran@999 | 14397 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qrefresh</userinput> |
belaran@999 | 14398 </screen> |
belaran@999 | 14399 <!-- END mq.guards.init --> |
belaran@999 | 14400 |
belaran@999 | 14401 |
belaran@999 | 14402 <para id="x_16c">This gives us a tiny repository that contains two patches |
belaran@999 | 14403 that don't have any dependencies on each other, because they |
belaran@999 | 14404 touch different files.</para> |
belaran@999 | 14405 |
belaran@999 | 14406 <para id="x_16d">The idea behind conditional application is that you can |
belaran@999 | 14407 <quote>tag</quote> a patch with a <emphasis>guard</emphasis>, |
belaran@999 | 14408 which is simply a text string of your choosing, then tell MQ to |
belaran@999 | 14409 select specific guards to use when applying patches. MQ will |
belaran@999 | 14410 then either apply, or skip over, a guarded patch, depending on |
belaran@999 | 14411 the guards that you have selected.</para> |
belaran@999 | 14412 |
belaran@999 | 14413 <para id="x_16e">A patch can have an arbitrary number of guards; each one is |
belaran@999 | 14414 <emphasis>positive</emphasis> (<quote>apply this patch if this |
belaran@999 | 14415 guard is selected</quote>) or <emphasis>negative</emphasis> |
belaran@999 | 14416 (<quote>skip this patch if this guard is selected</quote>). A |
belaran@999 | 14417 patch with no guards is always applied.</para> |
belaran@999 | 14418 |
belaran@999 | 14419 </sect1> |
belaran@999 | 14420 <sect1> |
belaran@999 | 14421 <title>Controlling the guards on a patch</title> |
belaran@999 | 14422 |
belaran@999 | 14423 <para id="x_16f">The <command role="hg-ext-mq" moreinfo="none">qguard</command> command lets |
belaran@999 | 14424 you determine which guards should apply to a patch, or display |
belaran@999 | 14425 the guards that are already in effect. Without any arguments, it |
belaran@999 | 14426 displays the guards on the current topmost patch.</para> |
belaran@999 | 14427 |
belaran@999 | 14428 <!-- BEGIN mq.guards.qguard --> |
belaran@999 | 14429 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput> |
belaran@999 | 14430 goodbye.patch: unguarded |
belaran@999 | 14431 </screen> |
belaran@999 | 14432 <!-- END mq.guards.qguard --> |
belaran@999 | 14433 |
belaran@999 | 14434 |
belaran@999 | 14435 <para id="x_170">To set a positive guard on a patch, prefix the name of the |
belaran@999 | 14436 guard with a <quote><literal moreinfo="none">+</literal></quote>.</para> |
belaran@999 | 14437 |
belaran@999 | 14438 <!-- BEGIN mq.guards.qguard.pos --> |
belaran@999 | 14439 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard +foo</userinput> |
belaran@999 | 14440 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard</userinput> |
belaran@999 | 14441 goodbye.patch: +foo |
belaran@999 | 14442 </screen> |
belaran@999 | 14443 <!-- END mq.guards.qguard.pos --> |
belaran@999 | 14444 |
belaran@999 | 14445 |
belaran@999 | 14446 <para id="x_171">To set a negative guard |
belaran@999 | 14447 on a patch, prefix the name of the guard with a |
belaran@999 | 14448 <quote><literal moreinfo="none">-</literal></quote>.</para> |
belaran@999 | 14449 |
belaran@999 | 14450 <!-- BEGIN mq.guards.qguard.neg --> |
belaran@999 | 14451 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard -- hello.patch -quux</userinput> |
belaran@999 | 14452 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qguard hello.patch</userinput> |
belaran@999 | 14453 hello.patch: -quux |
belaran@999 | 14454 </screen> |
belaran@999 | 14455 <!-- END mq.guards.qguard.neg --> |
belaran@999 | 14456 |
belaran@999 | 14457 |
belaran@999 | 14458 <para id="x_74a">Notice that we prefixed the arguments to the <command moreinfo="none">hg |
belaran@999 | 14459 qguard</command> command with a <literal moreinfo="none">--</literal> here, so |
belaran@999 | 14460 that Mercurial would not interpret the text |
belaran@999 | 14461 <literal moreinfo="none">-quux</literal> as an option.</para> |
belaran@999 | 14462 |
belaran@999 | 14463 <note> |
belaran@999 | 14464 <title>Setting vs. modifying</title> |
belaran@999 | 14465 |
belaran@999 | 14466 <para id="x_172"> The <command role="hg-ext-mq" moreinfo="none">qguard</command> command |
belaran@999 | 14467 <emphasis>sets</emphasis> the guards on a patch; it doesn't |
belaran@999 | 14468 <emphasis>modify</emphasis> them. What this means is that if |
belaran@999 | 14469 you run <command role="hg-cmd" moreinfo="none">hg qguard +a +b</command> on a |
belaran@999 | 14470 patch, then <command role="hg-cmd" moreinfo="none">hg qguard +c</command> on |
belaran@999 | 14471 the same patch, the <emphasis>only</emphasis> guard that will |
belaran@999 | 14472 be set on it afterwards is <literal moreinfo="none">+c</literal>.</para> |
belaran@999 | 14473 </note> |
belaran@999 | 14474 |
belaran@999 | 14475 <para id="x_173">Mercurial stores guards in the <filename role="special" moreinfo="none">series</filename> file; the form in which they |
belaran@999 | 14476 are stored is easy both to understand and to edit by hand. (In |
belaran@999 | 14477 other words, you don't have to use the <command role="hg-ext-mq" moreinfo="none">qguard</command> command if you don't want |
belaran@999 | 14478 to; it's okay to simply edit the <filename role="special" moreinfo="none">series</filename> file.)</para> |
belaran@999 | 14479 |
belaran@999 | 14480 <!-- BEGIN mq.guards.series --> |
belaran@999 | 14481 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/series</userinput> |
belaran@999 | 14482 hello.patch #-quux |
belaran@999 | 14483 goodbye.patch #+foo |
belaran@999 | 14484 </screen> |
belaran@999 | 14485 <!-- END mq.guards.series --> |
belaran@999 | 14486 |
belaran@999 | 14487 |
belaran@999 | 14488 </sect1> |
belaran@999 | 14489 <sect1> |
belaran@999 | 14490 <title>Selecting the guards to use</title> |
belaran@999 | 14491 |
belaran@999 | 14492 <para id="x_174">The <command role="hg-ext-mq" moreinfo="none">qselect</command> command |
belaran@999 | 14493 determines which guards are active at a given time. The effect |
belaran@999 | 14494 of this is to determine which patches MQ will apply the next |
belaran@999 | 14495 time you run <command role="hg-ext-mq" moreinfo="none">qpush</command>. It has |
belaran@999 | 14496 no other effect; in particular, it doesn't do anything to |
belaran@999 | 14497 patches that are already applied.</para> |
belaran@999 | 14498 |
belaran@999 | 14499 <para id="x_175">With no arguments, the <command role="hg-ext-mq" moreinfo="none">qselect</command> command lists the guards |
belaran@999 | 14500 currently in effect, one per line of output. Each argument is |
belaran@999 | 14501 treated as the name of a guard to apply.</para> |
belaran@999 | 14502 |
belaran@999 | 14503 <!-- BEGIN mq.guards.qselect.foo --> |
belaran@999 | 14504 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> |
belaran@999 | 14505 patch queue now empty |
belaran@999 | 14506 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput> |
belaran@999 | 14507 no active guards |
belaran@999 | 14508 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo</userinput> |
belaran@999 | 14509 number of unguarded, unapplied patches has changed from 1 to 2 |
belaran@999 | 14510 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect</userinput> |
belaran@999 | 14511 foo |
belaran@999 | 14512 </screen> |
belaran@999 | 14513 <!-- END mq.guards.qselect.foo --> |
belaran@999 | 14514 |
belaran@999 | 14515 |
belaran@999 | 14516 <para id="x_176">In case you're interested, the currently selected guards are |
belaran@999 | 14517 stored in the <filename role="special" moreinfo="none">guards</filename> file.</para> |
belaran@999 | 14518 |
belaran@999 | 14519 <!-- BEGIN mq.guards.qselect.cat --> |
belaran@999 | 14520 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">cat .hg/patches/guards</userinput> |
belaran@999 | 14521 foo |
belaran@999 | 14522 </screen> |
belaran@999 | 14523 <!-- END mq.guards.qselect.cat --> |
belaran@999 | 14524 |
belaran@999 | 14525 |
belaran@999 | 14526 <para id="x_177">We can see the effect the selected guards have when we run |
belaran@999 | 14527 <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para> |
belaran@999 | 14528 |
belaran@999 | 14529 <!-- BEGIN mq.guards.qselect.qpush --> |
belaran@999 | 14530 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> |
belaran@999 | 14531 applying hello.patch |
belaran@999 | 14532 applying goodbye.patch |
belaran@999 | 14533 now at: goodbye.patch |
belaran@999 | 14534 </screen> |
belaran@999 | 14535 <!-- END mq.guards.qselect.qpush --> |
belaran@999 | 14536 |
belaran@999 | 14537 |
belaran@999 | 14538 <para id="x_178">A guard cannot start with a |
belaran@999 | 14539 <quote><literal moreinfo="none">+</literal></quote> or |
belaran@999 | 14540 <quote><literal moreinfo="none">-</literal></quote> character. The name of a |
belaran@999 | 14541 guard must not contain white space, but most other characters |
belaran@999 | 14542 are acceptable. If you try to use a guard with an invalid name, |
belaran@999 | 14543 MQ will complain:</para> |
belaran@999 | 14544 |
belaran@999 | 14545 <!-- BEGIN mq.guards.qselect.error --> |
belaran@999 | 14546 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect +foo</userinput> |
belaran@999 | 14547 abort: guard '+foo' starts with invalid character: '+' |
belaran@999 | 14548 </screen> |
belaran@999 | 14549 <!-- END mq.guards.qselect.error --> |
belaran@999 | 14550 |
belaran@999 | 14551 |
belaran@999 | 14552 <para id="x_179">Changing the selected guards changes the patches that are |
belaran@999 | 14553 applied.</para> |
belaran@999 | 14554 |
belaran@999 | 14555 <!-- BEGIN mq.guards.qselect.quux --> |
belaran@999 | 14556 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect quux</userinput> |
belaran@999 | 14557 number of guarded, applied patches has changed from 0 to 2 |
belaran@999 | 14558 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> |
belaran@999 | 14559 patch queue now empty |
belaran@999 | 14560 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> |
belaran@999 | 14561 patch series already fully applied |
belaran@999 | 14562 </screen> |
belaran@999 | 14563 <!-- END mq.guards.qselect.quux --> |
belaran@999 | 14564 |
belaran@999 | 14565 |
belaran@999 | 14566 <para id="x_17a">You can see in the example below that negative guards take |
belaran@999 | 14567 precedence over positive guards.</para> |
belaran@999 | 14568 |
belaran@999 | 14569 <!-- BEGIN mq.guards.qselect.foobar --> |
belaran@999 | 14570 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qselect foo bar</userinput> |
belaran@999 | 14571 number of unguarded, unapplied patches has changed from 0 to 2 |
belaran@999 | 14572 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpop -a</userinput> |
belaran@999 | 14573 no patches applied |
belaran@999 | 14574 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg qpush -a</userinput> |
belaran@999 | 14575 applying hello.patch |
belaran@999 | 14576 applying goodbye.patch |
belaran@999 | 14577 now at: goodbye.patch |
belaran@999 | 14578 </screen> |
belaran@999 | 14579 <!-- END mq.guards.qselect.foobar --> |
belaran@999 | 14580 |
belaran@999 | 14581 |
belaran@999 | 14582 </sect1> |
belaran@999 | 14583 <sect1> |
belaran@999 | 14584 <title>MQ's rules for applying patches</title> |
belaran@999 | 14585 |
belaran@999 | 14586 <para id="x_17b">The rules that MQ uses when deciding whether to apply a |
belaran@999 | 14587 patch are as follows.</para> |
belaran@999 | 14588 <itemizedlist> |
belaran@999 | 14589 <listitem><para id="x_17c">A patch that has no guards is always |
belaran@999 | 14590 applied.</para> |
belaran@999 | 14591 </listitem> |
belaran@999 | 14592 <listitem><para id="x_17d">If the patch has any negative guard that matches |
belaran@999 | 14593 any currently selected guard, the patch is skipped.</para> |
belaran@999 | 14594 </listitem> |
belaran@999 | 14595 <listitem><para id="x_17e">If the patch has any positive guard that matches |
belaran@999 | 14596 any currently selected guard, the patch is applied.</para> |
belaran@999 | 14597 </listitem> |
belaran@999 | 14598 <listitem><para id="x_17f">If the patch has positive or negative guards, |
belaran@999 | 14599 but none matches any currently selected guard, the patch is |
belaran@999 | 14600 skipped.</para> |
belaran@999 | 14601 </listitem></itemizedlist> |
belaran@999 | 14602 |
belaran@999 | 14603 </sect1> |
belaran@999 | 14604 <sect1> |
belaran@999 | 14605 <title>Trimming the work environment</title> |
belaran@999 | 14606 |
belaran@999 | 14607 <para id="x_180">In working on the device driver I mentioned earlier, I don't |
belaran@999 | 14608 apply the patches to a normal Linux kernel tree. Instead, I use |
belaran@999 | 14609 a repository that contains only a snapshot of the source files |
belaran@999 | 14610 and headers that are relevant to Infiniband development. This |
belaran@999 | 14611 repository is 1% the size of a kernel repository, so it's easier |
belaran@999 | 14612 to work with.</para> |
belaran@999 | 14613 |
belaran@999 | 14614 <para id="x_181">I then choose a <quote>base</quote> version on top of which |
belaran@999 | 14615 the patches are applied. This is a snapshot of the Linux kernel |
belaran@999 | 14616 tree as of a revision of my choosing. When I take the snapshot, |
belaran@999 | 14617 I record the changeset ID from the kernel repository in the |
belaran@999 | 14618 commit message. Since the snapshot preserves the |
belaran@999 | 14619 <quote>shape</quote> and content of the relevant parts of the |
belaran@999 | 14620 kernel tree, I can apply my patches on top of either my tiny |
belaran@999 | 14621 repository or a normal kernel tree.</para> |
belaran@999 | 14622 |
belaran@999 | 14623 <para id="x_182">Normally, the base tree atop which the patches apply should |
belaran@999 | 14624 be a snapshot of a very recent upstream tree. This best |
belaran@999 | 14625 facilitates the development of patches that can easily be |
belaran@999 | 14626 submitted upstream with few or no modifications.</para> |
belaran@999 | 14627 |
belaran@999 | 14628 </sect1> |
belaran@999 | 14629 <sect1> |
belaran@999 | 14630 <title>Dividing up the <filename role="special" moreinfo="none">series</filename> |
belaran@999 | 14631 file</title> |
belaran@999 | 14632 |
belaran@999 | 14633 <para id="x_183">I categorise the patches in the <filename role="special" moreinfo="none">series</filename> file into a number of logical |
belaran@999 | 14634 groups. Each section of like patches begins with a block of |
belaran@999 | 14635 comments that describes the purpose of the patches that |
belaran@999 | 14636 follow.</para> |
belaran@999 | 14637 |
belaran@999 | 14638 <para id="x_184">The sequence of patch groups that I maintain follows. The |
belaran@999 | 14639 ordering of these groups is important; I'll describe why after I |
belaran@999 | 14640 introduce the groups.</para> |
belaran@999 | 14641 <itemizedlist> |
belaran@999 | 14642 <listitem><para id="x_185">The <quote>accepted</quote> group. Patches that |
belaran@999 | 14643 the development team has submitted to the maintainer of the |
belaran@999 | 14644 Infiniband subsystem, and which he has accepted, but which |
belaran@999 | 14645 are not present in the snapshot that the tiny repository is |
belaran@999 | 14646 based on. These are <quote>read only</quote> patches, |
belaran@999 | 14647 present only to transform the tree into a similar state as |
belaran@999 | 14648 it is in the upstream maintainer's repository.</para> |
belaran@999 | 14649 </listitem> |
belaran@999 | 14650 <listitem><para id="x_186">The <quote>rework</quote> group. Patches that I |
belaran@999 | 14651 have submitted, but that the upstream maintainer has |
belaran@999 | 14652 requested modifications to before he will accept |
belaran@999 | 14653 them.</para> |
belaran@999 | 14654 </listitem> |
belaran@999 | 14655 <listitem><para id="x_187">The <quote>pending</quote> group. Patches that |
belaran@999 | 14656 I have not yet submitted to the upstream maintainer, but |
belaran@999 | 14657 which we have finished working on. These will be <quote>read |
belaran@999 | 14658 only</quote> for a while. If the upstream maintainer |
belaran@999 | 14659 accepts them upon submission, I'll move them to the end of |
belaran@999 | 14660 the <quote>accepted</quote> group. If he requests that I |
belaran@999 | 14661 modify any, I'll move them to the beginning of the |
belaran@999 | 14662 <quote>rework</quote> group.</para> |
belaran@999 | 14663 </listitem> |
belaran@999 | 14664 <listitem><para id="x_188">The <quote>in progress</quote> group. Patches |
belaran@999 | 14665 that are actively being developed, and should not be |
belaran@999 | 14666 submitted anywhere yet.</para> |
belaran@999 | 14667 </listitem> |
belaran@999 | 14668 <listitem><para id="x_189">The <quote>backport</quote> group. Patches that |
belaran@999 | 14669 adapt the source tree to older versions of the kernel |
belaran@999 | 14670 tree.</para> |
belaran@999 | 14671 </listitem> |
belaran@999 | 14672 <listitem><para id="x_18a">The <quote>do not ship</quote> group. Patches |
belaran@999 | 14673 that for some reason should never be submitted upstream. |
belaran@999 | 14674 For example, one such patch might change embedded driver |
belaran@999 | 14675 identification strings to make it easier to distinguish, in |
belaran@999 | 14676 the field, between an out-of-tree version of the driver and |
belaran@999 | 14677 a version shipped by a distribution vendor.</para> |
belaran@999 | 14678 </listitem></itemizedlist> |
belaran@999 | 14679 |
belaran@999 | 14680 <para id="x_18b">Now to return to the reasons for ordering groups of patches |
belaran@999 | 14681 in this way. We would like the lowest patches in the stack to |
belaran@999 | 14682 be as stable as possible, so that we will not need to rework |
belaran@999 | 14683 higher patches due to changes in context. Putting patches that |
belaran@999 | 14684 will never be changed first in the <filename role="special" moreinfo="none">series</filename> file serves this |
belaran@999 | 14685 purpose.</para> |
belaran@999 | 14686 |
belaran@999 | 14687 <para id="x_18c">We would also like the patches that we know we'll need to |
belaran@999 | 14688 modify to be applied on top of a source tree that resembles the |
belaran@999 | 14689 upstream tree as closely as possible. This is why we keep |
belaran@999 | 14690 accepted patches around for a while.</para> |
belaran@999 | 14691 |
belaran@999 | 14692 <para id="x_18d">The <quote>backport</quote> and <quote>do not ship</quote> |
belaran@999 | 14693 patches float at the end of the <filename role="special" moreinfo="none">series</filename> file. The backport patches |
belaran@999 | 14694 must be applied on top of all other patches, and the <quote>do |
belaran@999 | 14695 not ship</quote> patches might as well stay out of harm's |
belaran@999 | 14696 way.</para> |
belaran@999 | 14697 |
belaran@999 | 14698 </sect1> |
belaran@999 | 14699 <sect1> |
belaran@999 | 14700 <title>Maintaining the patch series</title> |
belaran@999 | 14701 |
belaran@999 | 14702 <para id="x_18e">In my work, I use a number of guards to control which |
belaran@999 | 14703 patches are to be applied.</para> |
belaran@999 | 14704 |
belaran@999 | 14705 <itemizedlist> |
belaran@999 | 14706 <listitem><para id="x_18f"><quote>Accepted</quote> patches are guarded with |
belaran@999 | 14707 <literal moreinfo="none">accepted</literal>. I enable this guard most of |
belaran@999 | 14708 the time. When I'm applying the patches on top of a tree |
belaran@999 | 14709 where the patches are already present, I can turn this patch |
belaran@999 | 14710 off, and the patches that follow it will apply |
belaran@999 | 14711 cleanly.</para> |
belaran@999 | 14712 </listitem> |
belaran@999 | 14713 <listitem><para id="x_190">Patches that are <quote>finished</quote>, but |
belaran@999 | 14714 not yet submitted, have no guards. If I'm applying the |
belaran@999 | 14715 patch stack to a copy of the upstream tree, I don't need to |
belaran@999 | 14716 enable any guards in order to get a reasonably safe source |
belaran@999 | 14717 tree.</para> |
belaran@999 | 14718 </listitem> |
belaran@999 | 14719 <listitem><para id="x_191">Those patches that need reworking before being |
belaran@999 | 14720 resubmitted are guarded with |
belaran@999 | 14721 <literal moreinfo="none">rework</literal>.</para> |
belaran@999 | 14722 </listitem> |
belaran@999 | 14723 <listitem><para id="x_192">For those patches that are still under |
belaran@999 | 14724 development, I use <literal moreinfo="none">devel</literal>.</para> |
belaran@999 | 14725 </listitem> |
belaran@999 | 14726 <listitem><para id="x_193">A backport patch may have several guards, one |
belaran@999 | 14727 for each version of the kernel to which it applies. For |
belaran@999 | 14728 example, a patch that backports a piece of code to 2.6.9 |
belaran@999 | 14729 will have a <literal moreinfo="none">2.6.9</literal> guard.</para> |
belaran@999 | 14730 </listitem></itemizedlist> |
belaran@999 | 14731 <para id="x_194">This variety of guards gives me considerable flexibility in |
belaran@999 | 14732 determining what kind of source tree I want to end up with. For |
belaran@999 | 14733 most situations, the selection of appropriate guards is |
belaran@999 | 14734 automated during the build process, but I can manually tune the |
belaran@999 | 14735 guards to use for less common circumstances.</para> |
belaran@999 | 14736 |
belaran@999 | 14737 <sect2> |
belaran@999 | 14738 <title>The art of writing backport patches</title> |
belaran@999 | 14739 |
belaran@999 | 14740 <para id="x_195">Using MQ, writing a backport patch is a simple process. |
belaran@999 | 14741 All such a patch has to do is modify a piece of code that uses |
belaran@999 | 14742 a kernel feature not present in the older version of the |
belaran@999 | 14743 kernel, so that the driver continues to work correctly under |
belaran@999 | 14744 that older version.</para> |
belaran@999 | 14745 |
belaran@999 | 14746 <para id="x_196">A useful goal when writing a good backport patch is to |
belaran@999 | 14747 make your code look as if it was written for the older version |
belaran@999 | 14748 of the kernel you're targeting. The less obtrusive the patch, |
belaran@999 | 14749 the easier it will be to understand and maintain. If you're |
belaran@999 | 14750 writing a collection of backport patches to avoid the |
belaran@999 | 14751 <quote>rat's nest</quote> effect of lots of |
belaran@999 | 14752 <literal moreinfo="none">#ifdef</literal>s (hunks of source code that are only |
belaran@999 | 14753 used conditionally) in your code, don't introduce |
belaran@999 | 14754 version-dependent <literal moreinfo="none">#ifdef</literal>s into the patches. |
belaran@999 | 14755 Instead, write several patches, each of which makes |
belaran@999 | 14756 unconditional changes, and control their application using |
belaran@999 | 14757 guards.</para> |
belaran@999 | 14758 |
belaran@999 | 14759 <para id="x_197">There are two reasons to divide backport patches into a |
belaran@999 | 14760 distinct group, away from the <quote>regular</quote> patches |
belaran@999 | 14761 whose effects they modify. The first is that intermingling the |
belaran@999 | 14762 two makes it more difficult to use a tool like the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension to automate the |
belaran@999 | 14763 process of submitting the patches to an upstream maintainer. |
belaran@999 | 14764 The second is that a backport patch could perturb the context |
belaran@999 | 14765 in which a subsequent regular patch is applied, making it |
belaran@999 | 14766 impossible to apply the regular patch cleanly |
belaran@999 | 14767 <emphasis>without</emphasis> the earlier backport patch |
belaran@999 | 14768 already being applied.</para> |
belaran@999 | 14769 |
belaran@999 | 14770 </sect2> |
belaran@999 | 14771 </sect1> |
belaran@999 | 14772 <sect1> |
belaran@999 | 14773 <title>Useful tips for developing with MQ</title> |
belaran@999 | 14774 |
belaran@999 | 14775 <sect2> |
belaran@999 | 14776 <title>Organising patches in directories</title> |
belaran@999 | 14777 |
belaran@999 | 14778 <para id="x_198">If you're working on a substantial project with MQ, it's |
belaran@999 | 14779 not difficult to accumulate a large number of patches. For |
belaran@999 | 14780 example, I have one patch repository that contains over 250 |
belaran@999 | 14781 patches.</para> |
belaran@999 | 14782 |
belaran@999 | 14783 <para id="x_199">If you can group these patches into separate logical |
belaran@999 | 14784 categories, you can if you like store them in different |
belaran@999 | 14785 directories; MQ has no problems with patch names that contain |
belaran@999 | 14786 path separators.</para> |
belaran@999 | 14787 |
belaran@999 | 14788 </sect2> |
belaran@999 | 14789 <sect2 id="mq-collab:tips:interdiff"> |
belaran@999 | 14790 <title>Viewing the history of a patch</title> |
belaran@999 | 14791 |
belaran@999 | 14792 <para id="x_19a">If you're developing a set of patches over a long time, |
belaran@999 | 14793 it's a good idea to maintain them in a repository, as |
belaran@999 | 14794 discussed in <xref linkend="sec:mq:repo"/>. If you do |
belaran@999 | 14795 so, you'll quickly |
belaran@999 | 14796 discover that using the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 14797 diff</command> command to look at the history of changes to |
belaran@999 | 14798 a patch is unworkable. This is in part because you're looking |
belaran@999 | 14799 at the second derivative of the real code (a diff of a diff), |
belaran@999 | 14800 but also because MQ adds noise to the process by modifying |
belaran@999 | 14801 time stamps and directory names when it updates a |
belaran@999 | 14802 patch.</para> |
belaran@999 | 14803 |
belaran@999 | 14804 <para id="x_19b">However, you can use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension, which is bundled |
belaran@999 | 14805 with Mercurial, to turn a diff of two versions of a patch into |
belaran@999 | 14806 something readable. To do this, you will need a third-party |
belaran@999 | 14807 package called <literal role="package" moreinfo="none">patchutils</literal> |
belaran@999 | 14808 <citation>web:patchutils</citation>. This provides a command |
belaran@999 | 14809 named <command moreinfo="none">interdiff</command>, which shows the |
belaran@999 | 14810 differences between two diffs as a diff. Used on two versions |
belaran@999 | 14811 of the same diff, it generates a diff that represents the diff |
belaran@999 | 14812 from the first to the second version.</para> |
belaran@999 | 14813 |
belaran@999 | 14814 <para id="x_19c">You can enable the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension in the usual way, |
belaran@999 | 14815 by adding a line to the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your |
belaran@999 | 14816 <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> |
belaran@999 | 14817 <programlisting format="linespecific">[extensions] |
belaran@999 | 14818 extdiff =</programlisting> |
belaran@999 | 14819 <para id="x_19d">The <command moreinfo="none">interdiff</command> command expects to be |
belaran@999 | 14820 passed the names of two files, but the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension passes the program |
belaran@999 | 14821 it runs a pair of directories, each of which can contain an |
belaran@999 | 14822 arbitrary number of files. We thus need a small program that |
belaran@999 | 14823 will run <command moreinfo="none">interdiff</command> on each pair of files in |
belaran@999 | 14824 these two directories. This program is available as <filename role="special" moreinfo="none">hg-interdiff</filename> in the <filename class="directory" moreinfo="none">examples</filename> directory of the |
belaran@999 | 14825 source code repository that accompanies this book. <!-- |
belaran@999 | 14826 &example.hg-interdiff; --></para> |
belaran@999 | 14827 |
belaran@999 | 14828 <para id="x_19e">With the <filename role="special" moreinfo="none">hg-interdiff</filename> |
belaran@999 | 14829 program in your shell's search path, you can run it as |
belaran@999 | 14830 follows, from inside an MQ patch directory:</para> |
belaran@999 | 14831 <programlisting format="linespecific">hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting> |
belaran@999 | 14832 <para id="x_19f">Since you'll probably want to use this long-winded command |
belaran@999 | 14833 a lot, you can get <literal role="hg-ext" moreinfo="none">hgext</literal> to |
belaran@999 | 14834 make it available as a normal Mercurial command, again by |
belaran@999 | 14835 editing your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> |
belaran@999 | 14836 <programlisting format="linespecific">[extdiff] |
belaran@999 | 14837 cmd.interdiff = hg-interdiff</programlisting> |
belaran@999 | 14838 <para id="x_1a0">This directs <literal role="hg-ext" moreinfo="none">hgext</literal> to |
belaran@999 | 14839 make an <literal moreinfo="none">interdiff</literal> command available, so you |
belaran@999 | 14840 can now shorten the previous invocation of <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> to something a |
belaran@999 | 14841 little more wieldy.</para> |
belaran@999 | 14842 <programlisting format="linespecific">hg interdiff -r A:B my-change.patch</programlisting> |
belaran@999 | 14843 |
belaran@999 | 14844 <note> |
belaran@999 | 14845 <para id="x_1a1"> The <command moreinfo="none">interdiff</command> command works well |
belaran@999 | 14846 only if the underlying files against which versions of a |
belaran@999 | 14847 patch are generated remain the same. If you create a patch, |
belaran@999 | 14848 modify the underlying files, and then regenerate the patch, |
belaran@999 | 14849 <command moreinfo="none">interdiff</command> may not produce useful |
belaran@999 | 14850 output.</para> |
belaran@999 | 14851 </note> |
belaran@999 | 14852 |
belaran@999 | 14853 <para id="x_1a2">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is |
belaran@999 | 14854 useful for more than merely improving the presentation of MQ |
belaran@999 | 14855 patches. To read more about it, go to <xref linkend="sec:hgext:extdiff"/>.</para> |
belaran@999 | 14856 |
belaran@999 | 14857 </sect2> |
belaran@999 | 14858 </sect1> |
belaran@999 | 14859 </chapter> |
belaran@999 | 14860 |
belaran@999 | 14861 <!-- |
belaran@999 | 14862 local variables: |
belaran@999 | 14863 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 14864 end: |
belaran@999 | 14865 --> |
belaran@999 | 14866 |
belaran@999 | 14867 <!-- BEGIN ch14 --> |
belaran@999 | 14868 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 14869 |
belaran@999 | 14870 <chapter id="chap:hgext"> |
belaran@999 | 14871 <?dbhtml filename="adding-functionality-with-extensions.html"?> |
belaran@999 | 14872 <title>Adding functionality with extensions</title> |
belaran@999 | 14873 |
belaran@999 | 14874 <para id="x_4fe">While the core of Mercurial is quite complete from a |
belaran@999 | 14875 functionality standpoint, it's deliberately shorn of fancy |
belaran@999 | 14876 features. This approach of preserving simplicity keeps the |
belaran@999 | 14877 software easy to deal with for both maintainers and users.</para> |
belaran@999 | 14878 |
belaran@999 | 14879 <para id="x_4ff">However, Mercurial doesn't box you in with an inflexible |
belaran@999 | 14880 command set: you can add features to it as |
belaran@999 | 14881 <emphasis>extensions</emphasis> (sometimes known as |
belaran@999 | 14882 <emphasis>plugins</emphasis>). We've already discussed a few of |
belaran@999 | 14883 these extensions in earlier chapters.</para> |
belaran@999 | 14884 <itemizedlist> |
belaran@999 | 14885 <listitem><para id="x_500"><xref linkend="sec:tour-merge:fetch"/> |
belaran@999 | 14886 covers the <literal role="hg-ext" moreinfo="none">fetch</literal> extension; |
belaran@999 | 14887 this combines pulling new changes and merging them with local |
belaran@999 | 14888 changes into a single command, <command role="hg-ext-fetch" moreinfo="none">fetch</command>.</para> |
belaran@999 | 14889 </listitem> |
belaran@999 | 14890 <listitem><para id="x_501">In <xref linkend="chap:hook"/>, we covered |
belaran@999 | 14891 several extensions that are useful for hook-related |
belaran@999 | 14892 functionality: <literal role="hg-ext" moreinfo="none">acl</literal> adds |
belaran@999 | 14893 access control lists; <literal role="hg-ext" moreinfo="none">bugzilla</literal> adds integration with the |
belaran@999 | 14894 Bugzilla bug tracking system; and <literal role="hg-ext" moreinfo="none">notify</literal> sends notification emails on |
belaran@999 | 14895 new changes.</para> |
belaran@999 | 14896 </listitem> |
belaran@999 | 14897 <listitem><para id="x_502">The Mercurial Queues patch management extension is |
belaran@999 | 14898 so invaluable that it merits two chapters and an appendix all |
belaran@999 | 14899 to itself. <xref linkend="chap:mq"/> covers the |
belaran@999 | 14900 basics; <xref linkend="chap:mq-collab"/> discusses advanced topics; |
belaran@999 | 14901 and <xref linkend="chap:mqref"/> goes into detail on |
belaran@999 | 14902 each |
belaran@999 | 14903 command.</para> |
belaran@999 | 14904 </listitem></itemizedlist> |
belaran@999 | 14905 |
belaran@999 | 14906 <para id="x_503">In this chapter, we'll cover some of the other extensions that |
belaran@999 | 14907 are available for Mercurial, and briefly touch on some of the |
belaran@999 | 14908 machinery you'll need to know about if you want to write an |
belaran@999 | 14909 extension of your own.</para> |
belaran@999 | 14910 <itemizedlist> |
belaran@999 | 14911 <listitem><para id="x_504">In <xref linkend="sec:hgext:inotify"/>, |
belaran@999 | 14912 we'll discuss the possibility of <emphasis>huge</emphasis> |
belaran@999 | 14913 performance improvements using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension.</para> |
belaran@999 | 14914 </listitem></itemizedlist> |
belaran@999 | 14915 |
belaran@999 | 14916 <sect1 id="sec:hgext:inotify"> |
belaran@999 | 14917 <title>Improve performance with the <literal role="hg-ext" moreinfo="none">inotify</literal> extension</title> |
belaran@999 | 14918 |
belaran@999 | 14919 <para id="x_505">Are you interested in having some of the most common |
belaran@999 | 14920 Mercurial operations run as much as a hundred times faster? |
belaran@999 | 14921 Read on!</para> |
belaran@999 | 14922 |
belaran@999 | 14923 <para id="x_506">Mercurial has great performance under normal circumstances. |
belaran@999 | 14924 For example, when you run the <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 14925 status</command> command, Mercurial has to scan almost every |
belaran@999 | 14926 directory and file in your repository so that it can display |
belaran@999 | 14927 file status. Many other Mercurial commands need to do the same |
belaran@999 | 14928 work behind the scenes; for example, the <command role="hg-cmd" moreinfo="none">hg diff</command> command uses the status |
belaran@999 | 14929 machinery to avoid doing an expensive comparison operation on |
belaran@999 | 14930 files that obviously haven't changed.</para> |
belaran@999 | 14931 |
belaran@999 | 14932 <para id="x_507">Because obtaining file status is crucial to good |
belaran@999 | 14933 performance, the authors of Mercurial have optimised this code |
belaran@999 | 14934 to within an inch of its life. However, there's no avoiding the |
belaran@999 | 14935 fact that when you run <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 14936 status</command>, Mercurial is going to have to perform at |
belaran@999 | 14937 least one expensive system call for each managed file to |
belaran@999 | 14938 determine whether it's changed since the last time Mercurial |
belaran@999 | 14939 checked. For a sufficiently large repository, this can take a |
belaran@999 | 14940 long time.</para> |
belaran@999 | 14941 |
belaran@999 | 14942 <para id="x_508">To put a number on the magnitude of this effect, I created a |
belaran@999 | 14943 repository containing 150,000 managed files. I timed <command role="hg-cmd" moreinfo="none">hg status</command> as taking ten seconds to |
belaran@999 | 14944 run, even when <emphasis>none</emphasis> of those files had been |
belaran@999 | 14945 modified.</para> |
belaran@999 | 14946 |
belaran@999 | 14947 <para id="x_509">Many modern operating systems contain a file notification |
belaran@999 | 14948 facility. If a program signs up to an appropriate service, the |
belaran@999 | 14949 operating system will notify it every time a file of interest is |
belaran@999 | 14950 created, modified, or deleted. On Linux systems, the kernel |
belaran@999 | 14951 component that does this is called |
belaran@999 | 14952 <literal moreinfo="none">inotify</literal>.</para> |
belaran@999 | 14953 |
belaran@999 | 14954 <para id="x_50a">Mercurial's <literal role="hg-ext" moreinfo="none">inotify</literal> |
belaran@999 | 14955 extension talks to the kernel's <literal moreinfo="none">inotify</literal> |
belaran@999 | 14956 component to optimise <command role="hg-cmd" moreinfo="none">hg status</command> |
belaran@999 | 14957 commands. The extension has two components. A daemon sits in |
belaran@999 | 14958 the background and receives notifications from the |
belaran@999 | 14959 <literal moreinfo="none">inotify</literal> subsystem. It also listens for |
belaran@999 | 14960 connections from a regular Mercurial command. The extension |
belaran@999 | 14961 modifies Mercurial's behavior so that instead of scanning the |
belaran@999 | 14962 filesystem, it queries the daemon. Since the daemon has perfect |
belaran@999 | 14963 information about the state of the repository, it can respond |
belaran@999 | 14964 with a result instantaneously, avoiding the need to scan every |
belaran@999 | 14965 directory and file in the repository.</para> |
belaran@999 | 14966 |
belaran@999 | 14967 <para id="x_50b">Recall the ten seconds that I measured plain Mercurial as |
belaran@999 | 14968 taking to run <command role="hg-cmd" moreinfo="none">hg status</command> on a |
belaran@999 | 14969 150,000 file repository. With the <literal role="hg-ext" moreinfo="none">inotify</literal> extension enabled, the time |
belaran@999 | 14970 dropped to 0.1 seconds, a factor of <emphasis>one |
belaran@999 | 14971 hundred</emphasis> faster.</para> |
belaran@999 | 14972 |
belaran@999 | 14973 <para id="x_50c">Before we continue, please pay attention to some |
belaran@999 | 14974 caveats.</para> |
belaran@999 | 14975 <itemizedlist> |
belaran@999 | 14976 <listitem><para id="x_50d">The <literal role="hg-ext" moreinfo="none">inotify</literal> |
belaran@999 | 14977 extension is Linux-specific. Because it interfaces directly |
belaran@999 | 14978 to the Linux kernel's <literal moreinfo="none">inotify</literal> subsystem, |
belaran@999 | 14979 it does not work on other operating systems.</para> |
belaran@999 | 14980 </listitem> |
belaran@999 | 14981 <listitem><para id="x_50e">It should work on any Linux distribution that |
belaran@999 | 14982 was released after early 2005. Older distributions are |
belaran@999 | 14983 likely to have a kernel that lacks |
belaran@999 | 14984 <literal moreinfo="none">inotify</literal>, or a version of |
belaran@999 | 14985 <literal moreinfo="none">glibc</literal> that does not have the necessary |
belaran@999 | 14986 interfacing support.</para> |
belaran@999 | 14987 </listitem> |
belaran@999 | 14988 <listitem><para id="x_50f">Not all filesystems are suitable for use with |
belaran@999 | 14989 the <literal role="hg-ext" moreinfo="none">inotify</literal> extension. |
belaran@999 | 14990 Network filesystems such as NFS are a non-starter, for |
belaran@999 | 14991 example, particularly if you're running Mercurial on several |
belaran@999 | 14992 systems, all mounting the same network filesystem. The |
belaran@999 | 14993 kernel's <literal moreinfo="none">inotify</literal> system has no way of |
belaran@999 | 14994 knowing about changes made on another system. Most local |
belaran@999 | 14995 filesystems (e.g. ext3, XFS, ReiserFS) should work |
belaran@999 | 14996 fine.</para> |
belaran@999 | 14997 </listitem></itemizedlist> |
belaran@999 | 14998 |
belaran@999 | 14999 <para id="x_510">The <literal role="hg-ext" moreinfo="none">inotify</literal> extension is |
belaran@999 | 15000 not yet shipped with Mercurial as of May 2007, so it's a little |
belaran@999 | 15001 more involved to set up than other extensions. But the |
belaran@999 | 15002 performance improvement is worth it!</para> |
belaran@999 | 15003 |
belaran@999 | 15004 <para id="x_511">The extension currently comes in two parts: a set of patches |
belaran@999 | 15005 to the Mercurial source code, and a library of Python bindings |
belaran@999 | 15006 to the <literal moreinfo="none">inotify</literal> subsystem.</para> |
belaran@999 | 15007 <note> |
belaran@999 | 15008 <para id="x_512"> There are <emphasis>two</emphasis> Python |
belaran@999 | 15009 <literal moreinfo="none">inotify</literal> binding libraries. One of them is |
belaran@999 | 15010 called <literal moreinfo="none">pyinotify</literal>, and is packaged by some |
belaran@999 | 15011 Linux distributions as <literal moreinfo="none">python-inotify</literal>. |
belaran@999 | 15012 This is <emphasis>not</emphasis> the one you'll need, as it is |
belaran@999 | 15013 too buggy and inefficient to be practical.</para> |
belaran@999 | 15014 </note> |
belaran@999 | 15015 <para id="x_513">To get going, it's best to already have a functioning copy |
belaran@999 | 15016 of Mercurial installed.</para> |
belaran@999 | 15017 <note> |
belaran@999 | 15018 <para id="x_514"> If you follow the instructions below, you'll be |
belaran@999 | 15019 <emphasis>replacing</emphasis> and overwriting any existing |
belaran@999 | 15020 installation of Mercurial that you might already have, using |
belaran@999 | 15021 the latest <quote>bleeding edge</quote> Mercurial code. Don't |
belaran@999 | 15022 say you weren't warned!</para> |
belaran@999 | 15023 </note> |
belaran@999 | 15024 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 15025 <listitem><para id="x_515">Clone the Python <literal moreinfo="none">inotify</literal> |
belaran@999 | 15026 binding repository. Build and install it.</para> |
belaran@999 | 15027 <programlisting format="linespecific">hg clone http://hg.kublai.com/python/inotify |
belaran@999 | 15028 cd inotify |
belaran@999 | 15029 python setup.py build --force |
belaran@999 | 15030 sudo python setup.py install --skip-build</programlisting> |
belaran@999 | 15031 </listitem> |
belaran@999 | 15032 <listitem><para id="x_516">Clone the <filename class="directory" moreinfo="none">crew</filename> Mercurial repository. |
belaran@999 | 15033 Clone the <literal role="hg-ext" moreinfo="none">inotify</literal> patch |
belaran@999 | 15034 repository so that Mercurial Queues will be able to apply |
belaran@999 | 15035 patches to your cope of the <filename class="directory" moreinfo="none">crew</filename> repository.</para> |
belaran@999 | 15036 <programlisting format="linespecific">hg clone http://hg.intevation.org/mercurial/crew |
belaran@999 | 15037 hg clone crew inotify |
belaran@999 | 15038 hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches</programlisting> |
belaran@999 | 15039 </listitem> |
belaran@999 | 15040 <listitem><para id="x_517">Make sure that you have the Mercurial Queues |
belaran@999 | 15041 extension, <literal role="hg-ext" moreinfo="none">mq</literal>, enabled. If |
belaran@999 | 15042 you've never used MQ, read <xref linkend="sec:mq:start"/> to get started |
belaran@999 | 15043 quickly.</para> |
belaran@999 | 15044 </listitem> |
belaran@999 | 15045 <listitem><para id="x_518">Go into the <filename class="directory" moreinfo="none">inotify</filename> repo, and apply all |
belaran@999 | 15046 of the <literal role="hg-ext" moreinfo="none">inotify</literal> patches |
belaran@999 | 15047 using the <option role="hg-ext-mq-cmd-qpush-opt">hg |
belaran@999 | 15048 -a</option> option to the <command role="hg-ext-mq" moreinfo="none">qpush</command> command.</para> |
belaran@999 | 15049 <programlisting format="linespecific">cd inotify |
belaran@999 | 15050 hg qpush -a</programlisting> |
belaran@999 | 15051 </listitem> |
belaran@999 | 15052 <listitem><para id="x_519"> If you get an error message from <command role="hg-ext-mq" moreinfo="none">qpush</command>, you should not continue. |
belaran@999 | 15053 Instead, ask for help.</para> |
belaran@999 | 15054 </listitem> |
belaran@999 | 15055 <listitem><para id="x_51a">Build and install the patched version of |
belaran@999 | 15056 Mercurial.</para> |
belaran@999 | 15057 <programlisting format="linespecific">python setup.py build --force |
belaran@999 | 15058 sudo python setup.py install --skip-build</programlisting> |
belaran@999 | 15059 </listitem> |
belaran@999 | 15060 </orderedlist> |
belaran@999 | 15061 <para id="x_51b">Once you've build a suitably patched version of Mercurial, |
belaran@999 | 15062 all you need to do to enable the <literal role="hg-ext" moreinfo="none">inotify</literal> extension is add an entry to |
belaran@999 | 15063 your <filename role="special" moreinfo="none">~/.hgrc</filename>.</para> |
belaran@999 | 15064 <programlisting format="linespecific">[extensions] inotify =</programlisting> |
belaran@999 | 15065 <para id="x_51c">When the <literal role="hg-ext" moreinfo="none">inotify</literal> extension |
belaran@999 | 15066 is enabled, Mercurial will automatically and transparently start |
belaran@999 | 15067 the status daemon the first time you run a command that needs |
belaran@999 | 15068 status in a repository. It runs one status daemon per |
belaran@999 | 15069 repository.</para> |
belaran@999 | 15070 |
belaran@999 | 15071 <para id="x_51d">The status daemon is started silently, and runs in the |
belaran@999 | 15072 background. If you look at a list of running processes after |
belaran@999 | 15073 you've enabled the <literal role="hg-ext" moreinfo="none">inotify</literal> |
belaran@999 | 15074 extension and run a few commands in different repositories, |
belaran@999 | 15075 you'll thus see a few <literal moreinfo="none">hg</literal> processes sitting |
belaran@999 | 15076 around, waiting for updates from the kernel and queries from |
belaran@999 | 15077 Mercurial.</para> |
belaran@999 | 15078 |
belaran@999 | 15079 <para id="x_51e">The first time you run a Mercurial command in a repository |
belaran@999 | 15080 when you have the <literal role="hg-ext" moreinfo="none">inotify</literal> |
belaran@999 | 15081 extension enabled, it will run with about the same performance |
belaran@999 | 15082 as a normal Mercurial command. This is because the status |
belaran@999 | 15083 daemon needs to perform a normal status scan so that it has a |
belaran@999 | 15084 baseline against which to apply later updates from the kernel. |
belaran@999 | 15085 However, <emphasis>every</emphasis> subsequent command that does |
belaran@999 | 15086 any kind of status check should be noticeably faster on |
belaran@999 | 15087 repositories of even fairly modest size. Better yet, the bigger |
belaran@999 | 15088 your repository is, the greater a performance advantage you'll |
belaran@999 | 15089 see. The <literal role="hg-ext" moreinfo="none">inotify</literal> daemon makes |
belaran@999 | 15090 status operations almost instantaneous on repositories of all |
belaran@999 | 15091 sizes!</para> |
belaran@999 | 15092 |
belaran@999 | 15093 <para id="x_51f">If you like, you can manually start a status daemon using |
belaran@999 | 15094 the <command role="hg-ext-inotify" moreinfo="none">inserve</command> command. |
belaran@999 | 15095 This gives you slightly finer control over how the daemon ought |
belaran@999 | 15096 to run. This command will of course only be available when the |
belaran@999 | 15097 <literal role="hg-ext" moreinfo="none">inotify</literal> extension is |
belaran@999 | 15098 enabled.</para> |
belaran@999 | 15099 |
belaran@999 | 15100 <para id="x_520">When you're using the <literal role="hg-ext" moreinfo="none">inotify</literal> extension, you should notice |
belaran@999 | 15101 <emphasis>no difference at all</emphasis> in Mercurial's |
belaran@999 | 15102 behavior, with the sole exception of status-related commands |
belaran@999 | 15103 running a whole lot faster than they used to. You should |
belaran@999 | 15104 specifically expect that commands will not print different |
belaran@999 | 15105 output; neither should they give different results. If either of |
belaran@999 | 15106 these situations occurs, please report a bug.</para> |
belaran@999 | 15107 |
belaran@999 | 15108 </sect1> |
belaran@999 | 15109 <sect1 id="sec:hgext:extdiff"> |
belaran@999 | 15110 <title>Flexible diff support with the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension</title> |
belaran@999 | 15111 |
belaran@999 | 15112 <para id="x_521">Mercurial's built-in <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 15113 diff</command> command outputs plaintext unified diffs.</para> |
belaran@999 | 15114 |
belaran@999 | 15115 <!-- BEGIN extdiff.diff --> |
belaran@999 | 15116 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg diff</userinput> |
belaran@999 | 15117 diff -r 801b35c37d8b myfile |
belaran@999 | 15118 --- a/myfile Sun Aug 16 14:05:02 2009 +0000 |
belaran@999 | 15119 +++ b/myfile Sun Aug 16 14:05:02 2009 +0000 |
belaran@999 | 15120 @@ -1,1 +1,2 @@ |
belaran@999 | 15121 The first line. |
belaran@999 | 15122 +The second line. |
belaran@999 | 15123 </screen> |
belaran@999 | 15124 <!-- END extdiff.diff --> |
belaran@999 | 15125 |
belaran@999 | 15126 |
belaran@999 | 15127 <para id="x_522">If you would like to use an external tool to display |
belaran@999 | 15128 modifications, you'll want to use the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension. This will let you |
belaran@999 | 15129 use, for example, a graphical diff tool.</para> |
belaran@999 | 15130 |
belaran@999 | 15131 <para id="x_523">The <literal role="hg-ext" moreinfo="none">extdiff</literal> extension is |
belaran@999 | 15132 bundled with Mercurial, so it's easy to set up. In the <literal role="rc-extensions" moreinfo="none">extensions</literal> section of your |
belaran@999 | 15133 <filename role="special" moreinfo="none">~/.hgrc</filename>, simply add a |
belaran@999 | 15134 one-line entry to enable the extension.</para> |
belaran@999 | 15135 <programlisting format="linespecific">[extensions] |
belaran@999 | 15136 extdiff =</programlisting> |
belaran@999 | 15137 <para id="x_524">This introduces a command named <command role="hg-ext-extdiff" moreinfo="none">extdiff</command>, which by default uses |
belaran@999 | 15138 your system's <command moreinfo="none">diff</command> command to generate a |
belaran@999 | 15139 unified diff in the same form as the built-in <command role="hg-cmd" moreinfo="none">hg diff</command> command.</para> |
belaran@999 | 15140 |
belaran@999 | 15141 <!-- BEGIN extdiff.extdiff --> |
belaran@999 | 15142 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff</userinput> |
belaran@999 | 15143 --- a.801b35c37d8b/myfile 2009-08-16 14:05:02.000000000 +0000 |
belaran@999 | 15144 +++ /tmp/extdiffl1y_s9/a/myfile 2009-08-16 14:05:02.000000000 +0000 |
belaran@999 | 15145 @@ -1 +1,2 @@ |
belaran@999 | 15146 The first line. |
belaran@999 | 15147 +The second line. |
belaran@999 | 15148 </screen> |
belaran@999 | 15149 <!-- END extdiff.extdiff --> |
belaran@999 | 15150 |
belaran@999 | 15151 |
belaran@999 | 15152 <para id="x_525">The result won't be exactly the same as with the built-in |
belaran@999 | 15153 <command role="hg-cmd" moreinfo="none">hg diff</command> variations, because the |
belaran@999 | 15154 output of <command moreinfo="none">diff</command> varies from one system to |
belaran@999 | 15155 another, even when passed the same options.</para> |
belaran@999 | 15156 |
belaran@999 | 15157 <para id="x_526">As the <quote><literal moreinfo="none">making snapshot</literal></quote> |
belaran@999 | 15158 lines of output above imply, the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command works by |
belaran@999 | 15159 creating two snapshots of your source tree. The first snapshot |
belaran@999 | 15160 is of the source revision; the second, of the target revision or |
belaran@999 | 15161 working directory. The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command generates |
belaran@999 | 15162 these snapshots in a temporary directory, passes the name of |
belaran@999 | 15163 each directory to an external diff viewer, then deletes the |
belaran@999 | 15164 temporary directory. For efficiency, it only snapshots the |
belaran@999 | 15165 directories and files that have changed between the two |
belaran@999 | 15166 revisions.</para> |
belaran@999 | 15167 |
belaran@999 | 15168 <para id="x_527">Snapshot directory names have the same base name as your |
belaran@999 | 15169 repository. If your repository path is <filename class="directory" moreinfo="none">/quux/bar/foo</filename>, then <filename class="directory" moreinfo="none">foo</filename> will be the name of each |
belaran@999 | 15170 snapshot directory. Each snapshot directory name has its |
belaran@999 | 15171 changeset ID appended, if appropriate. If a snapshot is of |
belaran@999 | 15172 revision <literal moreinfo="none">a631aca1083f</literal>, the directory will be |
belaran@999 | 15173 named <filename class="directory" moreinfo="none">foo.a631aca1083f</filename>. |
belaran@999 | 15174 A snapshot of the working directory won't have a changeset ID |
belaran@999 | 15175 appended, so it would just be <filename class="directory" moreinfo="none">foo</filename> in this example. To see what |
belaran@999 | 15176 this looks like in practice, look again at the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> example above. Notice |
belaran@999 | 15177 that the diff has the snapshot directory names embedded in its |
belaran@999 | 15178 header.</para> |
belaran@999 | 15179 |
belaran@999 | 15180 <para id="x_528">The <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command |
belaran@999 | 15181 accepts two important options. The <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option |
belaran@999 | 15182 lets you choose a program to view differences with, instead of |
belaran@999 | 15183 <command moreinfo="none">diff</command>. With the <option role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option, |
belaran@999 | 15184 you can change the options that <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> passes to the program |
belaran@999 | 15185 (by default, these options are |
belaran@999 | 15186 <quote><literal moreinfo="none">-Npru</literal></quote>, which only make sense |
belaran@999 | 15187 if you're running <command moreinfo="none">diff</command>). In other respects, |
belaran@999 | 15188 the <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command |
belaran@999 | 15189 acts similarly to the built-in <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 15190 diff</command> command: you use the same option names, syntax, |
belaran@999 | 15191 and arguments to specify the revisions you want, the files you |
belaran@999 | 15192 want, and so on.</para> |
belaran@999 | 15193 |
belaran@999 | 15194 <para id="x_529">As an example, here's how to run the normal system |
belaran@999 | 15195 <command moreinfo="none">diff</command> command, getting it to generate context |
belaran@999 | 15196 diffs (using the <option role="cmd-opt-diff">-c</option> option) |
belaran@999 | 15197 instead of unified diffs, and five lines of context instead of |
belaran@999 | 15198 the default three (passing <literal moreinfo="none">5</literal> as the argument |
belaran@999 | 15199 to the <option role="cmd-opt-diff">-C</option> option).</para> |
belaran@999 | 15200 |
belaran@999 | 15201 <!-- BEGIN extdiff.extdiff-ctx --> |
belaran@999 | 15202 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg extdiff -o -NprcC5</userinput> |
belaran@999 | 15203 *** a.801b35c37d8b/myfile Sun Aug 16 14:05:02 2009 |
belaran@999 | 15204 --- /tmp/extdiffl1y_s9/a/myfile Sun Aug 16 14:05:02 2009 |
belaran@999 | 15205 *************** |
belaran@999 | 15206 *** 1 **** |
belaran@999 | 15207 --- 1,2 ---- |
belaran@999 | 15208 The first line. |
belaran@999 | 15209 + The second line. |
belaran@999 | 15210 </screen> |
belaran@999 | 15211 <!-- END extdiff.extdiff-ctx --> |
belaran@999 | 15212 |
belaran@999 | 15213 |
belaran@999 | 15214 <para id="x_52a">Launching a visual diff tool is just as easy. Here's how to |
belaran@999 | 15215 launch the <command moreinfo="none">kdiff3</command> viewer.</para> |
belaran@999 | 15216 <programlisting format="linespecific">hg extdiff -p kdiff3 -o</programlisting> |
belaran@999 | 15217 |
belaran@999 | 15218 <para id="x_52b">If your diff viewing command can't deal with directories, |
belaran@999 | 15219 you can easily work around this with a little scripting. For an |
belaran@999 | 15220 example of such scripting in action with the <literal role="hg-ext" moreinfo="none">mq</literal> extension and the |
belaran@999 | 15221 <command moreinfo="none">interdiff</command> command, see <xref linkend="mq-collab:tips:interdiff"/>.</para> |
belaran@999 | 15222 |
belaran@999 | 15223 <sect2> |
belaran@999 | 15224 <title>Defining command aliases</title> |
belaran@999 | 15225 |
belaran@999 | 15226 <para id="x_52c">It can be cumbersome to remember the options to both the |
belaran@999 | 15227 <command role="hg-ext-extdiff" moreinfo="none">extdiff</command> command and |
belaran@999 | 15228 the diff viewer you want to use, so the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension lets you define |
belaran@999 | 15229 <emphasis>new</emphasis> commands that will invoke your diff |
belaran@999 | 15230 viewer with exactly the right options.</para> |
belaran@999 | 15231 |
belaran@999 | 15232 <para id="x_52d">All you need to do is edit your <filename role="special" moreinfo="none">~/.hgrc</filename>, and add a section named |
belaran@999 | 15233 <literal role="rc-extdiff" moreinfo="none">extdiff</literal>. Inside this |
belaran@999 | 15234 section, you can define multiple commands. Here's how to add |
belaran@999 | 15235 a <literal moreinfo="none">kdiff3</literal> command. Once you've defined |
belaran@999 | 15236 this, you can type <quote><literal moreinfo="none">hg kdiff3</literal></quote> |
belaran@999 | 15237 and the <literal role="hg-ext" moreinfo="none">extdiff</literal> extension |
belaran@999 | 15238 will run <command moreinfo="none">kdiff3</command> for you.</para> |
belaran@999 | 15239 <programlisting format="linespecific">[extdiff] |
belaran@999 | 15240 cmd.kdiff3 =</programlisting> |
belaran@999 | 15241 <para id="x_52e">If you leave the right hand side of the definition empty, |
belaran@999 | 15242 as above, the <literal role="hg-ext" moreinfo="none">extdiff</literal> |
belaran@999 | 15243 extension uses the name of the command you defined as the name |
belaran@999 | 15244 of the external program to run. But these names don't have to |
belaran@999 | 15245 be the same. Here, we define a command named |
belaran@999 | 15246 <quote><literal moreinfo="none">hg wibble</literal></quote>, which runs |
belaran@999 | 15247 <command moreinfo="none">kdiff3</command>.</para> |
belaran@999 | 15248 <programlisting format="linespecific">[extdiff] |
belaran@999 | 15249 cmd.wibble = kdiff3</programlisting> |
belaran@999 | 15250 |
belaran@999 | 15251 <para id="x_52f">You can also specify the default options that you want to |
belaran@999 | 15252 invoke your diff viewing program with. The prefix to use is |
belaran@999 | 15253 <quote><literal moreinfo="none">opts.</literal></quote>, followed by the name |
belaran@999 | 15254 of the command to which the options apply. This example |
belaran@999 | 15255 defines a <quote><literal moreinfo="none">hg vimdiff</literal></quote> command |
belaran@999 | 15256 that runs the <command moreinfo="none">vim</command> editor's |
belaran@999 | 15257 <literal moreinfo="none">DirDiff</literal> extension.</para> |
belaran@999 | 15258 <programlisting format="linespecific">[extdiff] |
belaran@999 | 15259 cmd.vimdiff = vim |
belaran@999 | 15260 opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting> |
belaran@999 | 15261 |
belaran@999 | 15262 </sect2> |
belaran@999 | 15263 </sect1> |
belaran@999 | 15264 <sect1 id="sec:hgext:transplant"> |
belaran@999 | 15265 <title>Cherrypicking changes with the <literal role="hg-ext" moreinfo="none">transplant</literal> extension</title> |
belaran@999 | 15266 |
belaran@999 | 15267 <para id="x_530">Need to have a long chat with Brendan about this.</para> |
belaran@999 | 15268 |
belaran@999 | 15269 </sect1> |
belaran@999 | 15270 <sect1 id="sec:hgext:patchbomb"> |
belaran@999 | 15271 <title>Send changes via email with the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension</title> |
belaran@999 | 15272 |
belaran@999 | 15273 <para id="x_531">Many projects have a culture of <quote>change |
belaran@999 | 15274 review</quote>, in which people send their modifications to a |
belaran@999 | 15275 mailing list for others to read and comment on before they |
belaran@999 | 15276 commit the final version to a shared repository. Some projects |
belaran@999 | 15277 have people who act as gatekeepers; they apply changes from |
belaran@999 | 15278 other people to a repository to which those others don't have |
belaran@999 | 15279 access.</para> |
belaran@999 | 15280 |
belaran@999 | 15281 <para id="x_532">Mercurial makes it easy to send changes over email for |
belaran@999 | 15282 review or application, via its <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension. The extension is |
belaran@999 | 15283 so named because changes are formatted as patches, and it's usual |
belaran@999 | 15284 to send one changeset per email message. Sending a long series |
belaran@999 | 15285 of changes by email is thus much like <quote>bombing</quote> the |
belaran@999 | 15286 recipient's inbox, hence <quote>patchbomb</quote>.</para> |
belaran@999 | 15287 |
belaran@999 | 15288 <para id="x_533">As usual, the basic configuration of the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension takes just one or |
belaran@999 | 15289 two lines in your <filename role="special" moreinfo="none"> |
belaran@999 | 15290 /.hgrc</filename>.</para> |
belaran@999 | 15291 <programlisting format="linespecific">[extensions] |
belaran@999 | 15292 patchbomb =</programlisting> |
belaran@999 | 15293 <para id="x_534">Once you've enabled the extension, you will have a new |
belaran@999 | 15294 command available, named <command role="hg-ext-patchbomb" moreinfo="none">email</command>.</para> |
belaran@999 | 15295 |
belaran@999 | 15296 <para id="x_535">The safest and best way to invoke the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command is to |
belaran@999 | 15297 <emphasis>always</emphasis> run it first with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option. |
belaran@999 | 15298 This will show you what the command <emphasis>would</emphasis> |
belaran@999 | 15299 send, without actually sending anything. Once you've had a |
belaran@999 | 15300 quick glance over the changes and verified that you are sending |
belaran@999 | 15301 the right ones, you can rerun the same command, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option |
belaran@999 | 15302 removed.</para> |
belaran@999 | 15303 |
belaran@999 | 15304 <para id="x_536">The <command role="hg-ext-patchbomb" moreinfo="none">email</command> command |
belaran@999 | 15305 accepts the same kind of revision syntax as every other |
belaran@999 | 15306 Mercurial command. For example, this command will send every |
belaran@999 | 15307 revision between 7 and <literal moreinfo="none">tip</literal>, inclusive.</para> |
belaran@999 | 15308 <programlisting format="linespecific">hg email -n 7:tip</programlisting> |
belaran@999 | 15309 <para id="x_537">You can also specify a <emphasis>repository</emphasis> to |
belaran@999 | 15310 compare with. If you provide a repository but no revisions, the |
belaran@999 | 15311 <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will |
belaran@999 | 15312 send all revisions in the local repository that are not present |
belaran@999 | 15313 in the remote repository. If you additionally specify revisions |
belaran@999 | 15314 or a branch name (the latter using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option), |
belaran@999 | 15315 this will constrain the revisions sent.</para> |
belaran@999 | 15316 |
belaran@999 | 15317 <para id="x_538">It's perfectly safe to run the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command without the |
belaran@999 | 15318 names of the people you want to send to: if you do this, it will |
belaran@999 | 15319 just prompt you for those values interactively. (If you're |
belaran@999 | 15320 using a Linux or Unix-like system, you should have enhanced |
belaran@999 | 15321 <literal moreinfo="none">readline</literal>-style editing capabilities when |
belaran@999 | 15322 entering those headers, too, which is useful.)</para> |
belaran@999 | 15323 |
belaran@999 | 15324 <para id="x_539">When you are sending just one revision, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will by |
belaran@999 | 15325 default use the first line of the changeset description as the |
belaran@999 | 15326 subject of the single email message it sends.</para> |
belaran@999 | 15327 |
belaran@999 | 15328 <para id="x_53a">If you send multiple revisions, the <command role="hg-ext-patchbomb" moreinfo="none">email</command> command will usually |
belaran@999 | 15329 send one message per changeset. It will preface the series with |
belaran@999 | 15330 an introductory message, in which you should describe the |
belaran@999 | 15331 purpose of the series of changes you're sending.</para> |
belaran@999 | 15332 |
belaran@999 | 15333 <sect2> |
belaran@999 | 15334 <title>Changing the behavior of patchbombs</title> |
belaran@999 | 15335 |
belaran@999 | 15336 <para id="x_53b">Not every project has exactly the same conventions for |
belaran@999 | 15337 sending changes in email; the <literal role="hg-ext" moreinfo="none">patchbomb</literal> extension tries to |
belaran@999 | 15338 accommodate a number of variations through command line |
belaran@999 | 15339 options.</para> |
belaran@999 | 15340 <itemizedlist> |
belaran@999 | 15341 <listitem><para id="x_53c">You can write a subject for the introductory |
belaran@999 | 15342 message on the command line using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -s</option> |
belaran@999 | 15343 option. This takes one argument, the text of the subject |
belaran@999 | 15344 to use.</para> |
belaran@999 | 15345 </listitem> |
belaran@999 | 15346 <listitem><para id="x_53d">To change the email address from which the |
belaran@999 | 15347 messages originate, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -f</option> |
belaran@999 | 15348 option. This takes one argument, the email address to |
belaran@999 | 15349 use.</para> |
belaran@999 | 15350 </listitem> |
belaran@999 | 15351 <listitem><para id="x_53e">The default behavior is to send unified diffs |
belaran@999 | 15352 (see <xref linkend="sec:mq:patch"/> for a |
belaran@999 | 15353 description of the |
belaran@999 | 15354 format), one per message. You can send a binary bundle |
belaran@999 | 15355 instead with the <option role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> |
belaran@999 | 15356 option.</para> |
belaran@999 | 15357 </listitem> |
belaran@999 | 15358 <listitem><para id="x_53f">Unified diffs are normally prefaced with a |
belaran@999 | 15359 metadata header. You can omit this, and send unadorned |
belaran@999 | 15360 diffs, with the <option role="hg-ext-patchbomb-cmd-email-opt">hg |
belaran@999 | 15361 --plain</option> option.</para> |
belaran@999 | 15362 </listitem> |
belaran@999 | 15363 <listitem><para id="x_540">Diffs are normally sent <quote>inline</quote>, |
belaran@999 | 15364 in the same body part as the description of a patch. This |
belaran@999 | 15365 makes it easiest for the largest number of readers to |
belaran@999 | 15366 quote and respond to parts of a diff, as some mail clients |
belaran@999 | 15367 will only quote the first MIME body part in a message. If |
belaran@999 | 15368 you'd prefer to send the description and the diff in |
belaran@999 | 15369 separate body parts, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -a</option> |
belaran@999 | 15370 option.</para> |
belaran@999 | 15371 </listitem> |
belaran@999 | 15372 <listitem><para id="x_541">Instead of sending mail messages, you can |
belaran@999 | 15373 write them to an <literal moreinfo="none">mbox</literal>-format mail |
belaran@999 | 15374 folder using the <option role="hg-ext-patchbomb-cmd-email-opt">hg -m</option> |
belaran@999 | 15375 option. That option takes one argument, the name of the |
belaran@999 | 15376 file to write to.</para> |
belaran@999 | 15377 </listitem> |
belaran@999 | 15378 <listitem><para id="x_542">If you would like to add a |
belaran@999 | 15379 <command moreinfo="none">diffstat</command>-format summary to each patch, |
belaran@999 | 15380 and one to the introductory message, use the <option role="hg-ext-patchbomb-cmd-email-opt">hg -d</option> |
belaran@999 | 15381 option. The <command moreinfo="none">diffstat</command> command displays |
belaran@999 | 15382 a table containing the name of each file patched, the |
belaran@999 | 15383 number of lines affected, and a histogram showing how much |
belaran@999 | 15384 each file is modified. This gives readers a qualitative |
belaran@999 | 15385 glance at how complex a patch is.</para> |
belaran@999 | 15386 </listitem></itemizedlist> |
belaran@999 | 15387 |
belaran@999 | 15388 </sect2> |
belaran@999 | 15389 </sect1> |
belaran@999 | 15390 </chapter> |
belaran@999 | 15391 |
belaran@999 | 15392 <!-- |
belaran@999 | 15393 local variables: |
belaran@999 | 15394 sgml-parent-document: ("00book.xml" "book" "chapter") |
belaran@999 | 15395 end: |
belaran@999 | 15396 --> |
belaran@999 | 15397 |
belaran@999 | 15398 <!-- BEGIN appA --> |
belaran@999 | 15399 |
belaran@999 | 15400 |
belaran@999 | 15401 <appendix id="svn"> |
belaran@999 | 15402 <?dbhtml filename="migrating-to-mercurial.html"?> |
belaran@999 | 15403 <title>Migrer vers Mercurial</title> |
belaran@999 | 15404 |
belaran@999 | 15405 <para id="x_6e1">Une manière courante de s'essayer à un nouveau |
belaran@999 | 15406 gestionnaire de révisions est d'expérimenter en migrant un |
belaran@999 | 15407 projet existant, plutôt que le faire avec un nouveau projet. |
belaran@999 | 15408 </para> |
belaran@999 | 15409 |
belaran@999 | 15410 <para id="x_6e2">Dans cette annexe, nous discuterons comment importer |
belaran@999 | 15411 l'historique d'un projet dans Mercurial, et à quoi faire attention |
belaran@999 | 15412 si vous êtes habitués à un autre outil de gestion de révisions. |
belaran@999 | 15413 </para> |
belaran@999 | 15414 |
belaran@999 | 15415 <sect1> |
belaran@999 | 15416 <title>Importer l'historique depuis un autre système</title> |
belaran@999 | 15417 |
belaran@999 | 15418 <para id="x_6e3">Mercurial est livré avec une extension nommée |
belaran@999 | 15419 <literal moreinfo="none">convert</literal>, qui permet d'importer un historique |
belaran@999 | 15420 depuis les gestionnaire de révisions les plus courants. Au moment de |
belaran@999 | 15421 l'écriture de ce livre, il pouvait importer l'historique depuis: |
belaran@999 | 15422 </para> |
belaran@999 | 15423 <itemizedlist> |
belaran@999 | 15424 <listitem> |
belaran@999 | 15425 <para id="x_6e4">Subversion</para> |
belaran@999 | 15426 </listitem> |
belaran@999 | 15427 <listitem> |
belaran@999 | 15428 <para id="x_6e5">CVS</para> |
belaran@999 | 15429 </listitem> |
belaran@999 | 15430 <listitem> |
belaran@999 | 15431 <para id="x_6e6">git</para> |
belaran@999 | 15432 </listitem> |
belaran@999 | 15433 <listitem> |
belaran@999 | 15434 <para id="x_6e7">Darcs</para> |
belaran@999 | 15435 </listitem> |
belaran@999 | 15436 <listitem> |
belaran@999 | 15437 <para id="x_6e8">Bazaar</para> |
belaran@999 | 15438 </listitem> |
belaran@999 | 15439 <listitem> |
belaran@999 | 15440 <para id="x_6e9">Monotone</para> |
belaran@999 | 15441 </listitem> |
belaran@999 | 15442 <listitem> |
belaran@999 | 15443 <para id="x_6ea">GNU Arch</para> |
belaran@999 | 15444 </listitem> |
belaran@999 | 15445 <listitem> |
belaran@999 | 15446 <para id="x_6eb">Mercurial</para> |
belaran@999 | 15447 </listitem> |
belaran@999 | 15448 </itemizedlist> |
belaran@999 | 15449 |
belaran@999 | 15450 <para id="x_6ec">(Pour savoir pourquoi Mercurial lui même est supporté |
belaran@999 | 15451 comme source, voir <xref linkend="svn.filemap"/>.)</para> |
belaran@999 | 15452 |
belaran@999 | 15453 <para id="x_6ed">Vous pouvez activer l'extension de la manière |
belaran@999 | 15454 habituelle, en éditant votre fichier <filename moreinfo="none">~/.hgrc</filename></para> |
belaran@999 | 15455 |
belaran@999 | 15456 <programlisting format="linespecific">[extensions] |
belaran@999 | 15457 convert =</programlisting> |
belaran@999 | 15458 |
belaran@999 | 15459 <para id="x_6ee">Ceci rendra la commande <command moreinfo="none">hg convert</command> |
belaran@999 | 15460 disponible. La commande est facile à utiliser. Par exemple, la |
belaran@999 | 15461 commande suivante va importer l'historique Subversion du <emphasis remap="it">framework</emphasis> de test <quote>Nose Unit</quote> dans Mercurial. |
belaran@999 | 15462 </para> |
belaran@999 | 15463 |
belaran@999 | 15464 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen> |
belaran@999 | 15465 |
belaran@999 | 15466 <para id="x_6ef">L'extension <literal moreinfo="none">convert</literal> opère de |
belaran@999 | 15467 manière incrémentale. En d'autres mots, après une première exécution de |
belaran@999 | 15468 la commande <command moreinfo="none">hg convert</command>, les exécutions ultérieures |
belaran@999 | 15469 importeront les révisions ultérieures à l'exécution précédente. |
belaran@999 | 15470 La conversion incrémentale ne réussira que si |
belaran@999 | 15471 vous exécutez <command moreinfo="none">hg convert</command> dans le même dépôt que vous |
belaran@999 | 15472 aviez utilisé à l'origine, ceci parce que l'extension <literal moreinfo="none">convert</literal> |
belaran@999 | 15473 sauvegarde un certain nombre de méta-données privées dans le fichier |
belaran@999 | 15474 <filename moreinfo="none">.hg/shamap</filename> (non versioné) au sein du dépôt cible. |
belaran@999 | 15475 </para> |
belaran@999 | 15476 |
belaran@999 | 15477 <para id="x_707">Lorsque vous voulez faire des modifications en utilisant |
belaran@999 | 15478 Mercurial, le mieux est de faire un clone de l'ensemble de l'arborescence |
belaran@999 | 15479 que vous souhaitez convertir, et de laisser l'arborescence d'origine pour |
belaran@999 | 15480 de futures conversions incrémentales. C'est la manière la plus sûre pour vous laisser |
belaran@999 | 15481 récupérer et fusionner les modifications futures depuis l'outil de gestion |
belaran@999 | 15482 de révisions dans votre nouveau dépôt Mercurial.</para> |
belaran@999 | 15483 |
belaran@999 | 15484 <sect2> |
belaran@999 | 15485 <title>Convertir plusieurs branches</title> |
belaran@999 | 15486 |
belaran@999 | 15487 <para id="x_708">La commande <command moreinfo="none">hg convert</command> citée |
belaran@999 | 15488 ci-dessus convertit seulement l'historique de la <literal moreinfo="none">branche |
belaran@999 | 15489 principale (trunk)</literal> du dépôt Subversion. Si nous utilisons |
belaran@999 | 15490 à la place l'URL <literal moreinfo="none">http://python-nose.googlecode.com/svn</literal>, |
belaran@999 | 15491 Mercurial va automatiquement détecter la |
belaran@999 | 15492 <literal moreinfo="none">branche principale (trunk)</literal>, les <literal moreinfo="none">étiquettes |
belaran@999 | 15493 (tags)</literal>, et les <literal moreinfo="none">branches</literal> que les dépôts |
belaran@999 | 15494 Subversion utilisent généralement, et les importera chacun dans |
belaran@999 | 15495 une branche Mercurial distincte.</para> |
belaran@999 | 15496 |
belaran@999 | 15497 <para id="x_709">Par défaut, chaque branche Subversion importée |
belaran@999 | 15498 dans Mercurial se voit attribuer un nom de branche. Une fois la |
belaran@999 | 15499 conversion achevée, vous pouvez obtenir la liste des noms des branches |
belaran@999 | 15500 actives dans le dépôt Mercurial en utilisant la commande |
belaran@999 | 15501 <command moreinfo="none">hg branches -a</command>. Si vous préférez importer les |
belaran@999 | 15502 branches Subversion sans noms, ajoutez l'option <option>--config |
belaran@999 | 15503 convert.hg.usebranches=false</option> à la commande |
belaran@999 | 15504 <command moreinfo="none">hg convert</command>.</para> |
belaran@999 | 15505 |
belaran@999 | 15506 <para id="x_70a">Une fois votre arborescence convertie, |
belaran@999 | 15507 si vous souhaitez travailler selon la pratique habituelle sous Mercurial |
belaran@999 | 15508 avec une arborescence qui ne contient qu'une seule branche, vous pouvez cloner |
belaran@999 | 15509 cette seule branche en utilisant |
belaran@999 | 15510 <command moreinfo="none">hg clone -r nomdemabranche</command>.</para> |
belaran@999 | 15511 </sect2> |
belaran@999 | 15512 |
belaran@999 | 15513 <sect2> |
belaran@999 | 15514 <title>Associer les noms d'utilisateurs</title> |
belaran@999 | 15515 |
belaran@999 | 15516 <para id="x_6f0">Certains outils de gestion de révisions |
belaran@999 | 15517 ne sauvegardent, avec les modifications, que les noms |
belaran@999 | 15518 d'utilisateurs raccourcis. Ceux-ci peuvent être difficiles à |
belaran@999 | 15519 interpréter. La norme avec Mercurial est de sauvegarder le |
belaran@999 | 15520 nom du <emphasis remap="it">committeur</emphasis> et son adresse |
belaran@999 | 15521 mail, ce qui est beaucoup plus utile pour discuter avec lui |
belaran@999 | 15522 par la suite.</para> |
belaran@999 | 15523 |
belaran@999 | 15524 <para id="x_6f1">Si vous convertissez une arborescence depuis |
belaran@999 | 15525 un gestionnaire de révisions qui utilise seulement les noms |
belaran@999 | 15526 raccourcis, vous pouvez associer ces noms à des équivalents |
belaran@999 | 15527 plus détaillés en passant l'option <option>--authors</option> |
belaran@999 | 15528 à la commande <command moreinfo="none">hg convert</command>. Cette option |
belaran@999 | 15529 attend un fichier qui contient des entrées sous la forme suivante: |
belaran@999 | 15530 </para> |
belaran@999 | 15531 |
belaran@999 | 15532 <programlisting format="linespecific">arist = Aristotle <aristotle@phil.example.gr> |
belaran@999 | 15533 soc = Socrates <socrates@phil.example.gr></programlisting> |
belaran@999 | 15534 |
belaran@999 | 15535 <para id="x_6f2">Quand <literal moreinfo="none">convert</literal> trouve une |
belaran@999 | 15536 modification associée au nom <literal moreinfo="none">arist</literal> dans le |
belaran@999 | 15537 dépôt de source, il va utiliser le nom <literal moreinfo="none">Aristotle |
belaran@999 | 15538 <aristotle@phil.example.gr></literal> dans les révisions |
belaran@999 | 15539 Mercurial. Si aucune correspondance n'est trouvé, il utilise |
belaran@999 | 15540 le nom tel quel.</para> |
belaran@999 | 15541 </sect2> |
belaran@999 | 15542 |
belaran@999 | 15543 <sect2 id="svn.filemap"> |
belaran@999 | 15544 <title>Nettoyer l'arboresence</title> |
belaran@999 | 15545 |
belaran@999 | 15546 <para id="x_6f3">Tous les projets n'ont pas un historique parfait. |
belaran@999 | 15547 Il peut y avoir des répertoires qui n'auraient jamais dû être ajoutés, |
belaran@999 | 15548 un fichier qui est trop volumineux, ou même une partie de la |
belaran@999 | 15549 hiérarchie qui devrait être réorganisée.</para> |
belaran@999 | 15550 |
belaran@999 | 15551 <para id="x_6f4">L'extension <literal moreinfo="none">convert</literal> permet |
belaran@999 | 15552 d'utiliser un <quote>fichier d'association</quote> qui peut |
belaran@999 | 15553 réorganiser les fichiers et les répertoires dans un projet lors de |
belaran@999 | 15554 l'importation de son historique. Ceci est utile non seulement quand vous |
belaran@999 | 15555 importez l'historique d'un autre gestionnaire de révisions, mais |
belaran@999 | 15556 aussi pour nettoyer ou réorganiser l'arborescence d'un projet |
belaran@999 | 15557 Mercurial.</para> |
belaran@999 | 15558 |
belaran@999 | 15559 <para id="x_6f5">Pour indiquer le fichier d'association, on utilise |
belaran@999 | 15560 l'option <option>--filemap</option> en lui fournissant un nom de |
belaran@999 | 15561 fichier. Le fichier d'association contient des lignes de la forme |
belaran@999 | 15562 suivante :</para> |
belaran@999 | 15563 |
belaran@999 | 15564 <programlisting format="linespecific"># Ceci est un commentaire. |
belaran@999 | 15565 # Les lignes vides sont ignorées. |
belaran@999 | 15566 |
belaran@999 | 15567 include path/to/file |
belaran@999 | 15568 |
belaran@999 | 15569 exclude path/to/file |
belaran@999 | 15570 |
belaran@999 | 15571 rename from/some/path to/some/other/place |
belaran@999 | 15572 </programlisting> |
belaran@999 | 15573 |
belaran@999 | 15574 <para id="x_6f6">La directive <literal moreinfo="none">include</literal> inclut un |
belaran@999 | 15575 fichier, ou l'ensemble des fichiers d'un répertoire, dans le dépôt |
belaran@999 | 15576 de destination. La directive <literal moreinfo="none">exclude</literal> omet les |
belaran@999 | 15577 fichiers ou répertoires du dépôt. Ceci inclut aussi les autres |
belaran@999 | 15578 fichiers et répertoires qui ne sont pas explicitement inclus. |
belaran@999 | 15579 La directive <literal moreinfo="none">exclude</literal> entraine l'omission |
belaran@999 | 15580 des fichiers ou répertoires, et autres fichiers qui ne sont pas |
belaran@999 | 15581 explicitement inclus.</para> |
belaran@999 | 15582 |
belaran@999 | 15583 <para id="x_6f7">Pour déplacer un fichier ou un répertoire d'un |
belaran@999 | 15584 emplacement à un autre, utilisez la directive |
belaran@999 | 15585 <literal moreinfo="none">rename</literal>. Si vous avez besoin de déplacer un |
belaran@999 | 15586 fichier ou un répertoire depuis un sous répertoire dans la racine |
belaran@999 | 15587 du dépôt, utilisez <literal moreinfo="none">.</literal> comme second argument de |
belaran@999 | 15588 la directive <literal moreinfo="none">rename</literal>.</para> |
belaran@999 | 15589 </sect2> |
belaran@999 | 15590 |
belaran@999 | 15591 <sect2> |
belaran@999 | 15592 <title>Améliorer les performances de la conversion Subversion</title> |
belaran@999 | 15593 |
belaran@999 | 15594 <para id="x_70b">Vous aurez souvent besoin de plusieurs essais |
belaran@999 | 15595 avant d'arriver à la parfaite combinaison de fichier d'association de fichiers, |
belaran@999 | 15596 de fichier d'association de noms d'utilisateurs et des autres paramètres. Or, |
belaran@999 | 15597 convertir un dépôt Mercurial via un protocole comme <literal moreinfo="none">ssh</literal> |
belaran@999 | 15598 ou <literal moreinfo="none">http</literal> peut être des milliers de fois plus long |
belaran@999 | 15599 que ce dont le système d'exploitation est en fait capable de faire, |
belaran@999 | 15600 à cause des latence réseau. Ceci peut rendre la conception de cette |
belaran@999 | 15601 combinaison parfaite très douloureuse.</para> |
belaran@999 | 15602 |
belaran@999 | 15603 <para id="x_70c">La commande <ulink url="http://svn.collab.net/repos/svn/trunk/notes/svnsync.txt"><command moreinfo="none">svnsync</command></ulink> |
belaran@999 | 15604 peut grandement améliorer la vitesse de conversion d'un dépôt |
belaran@999 | 15605 Subversion. Il s'agit d'un programme de miroir de dépôt Subversion |
belaran@999 | 15606 en lecture seule. L'idée est de créer un miroir local d'une |
belaran@999 | 15607 arborescence Subversion, puis de convertir ce miroir en dépôt |
belaran@999 | 15608 Mercurial.</para> |
belaran@999 | 15609 |
belaran@999 | 15610 <para id="x_70d">Supposez que nous voulions convertir le dépôt |
belaran@999 | 15611 Subversion du populaire projet Memcached en une arborescence Mercurial. |
belaran@999 | 15612 Tout d'abord, nous créons un dépôt Subversion local.</para> |
belaran@999 | 15613 |
belaran@999 | 15614 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnadmin create memcached-mirror</userinput></screen> |
belaran@999 | 15615 |
belaran@999 | 15616 <para id="x_70e">Puis, nous allons mettre en place un <quote>hook</quote> Subversion |
belaran@999 | 15617 dont <command moreinfo="none">svnsync</command> a besoin.</para> |
belaran@999 | 15618 |
belaran@999 | 15619 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">echo '#!/bin/sh' > memcached-mirror/hooks/pre-revprop-change</userinput> |
belaran@999 | 15620 <prompt moreinfo="none">$</prompt> <userinput moreinfo="none">chmod +x memcached-mirror/hooks/pre-revprop-change</userinput></screen> |
belaran@999 | 15621 |
belaran@999 | 15622 <para id="x_70f">Nous initialisons ensuite <command moreinfo="none">svnsync</command> dans ce |
belaran@999 | 15623 dépôt.</para> |
belaran@999 | 15624 |
belaran@999 | 15625 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync --init file://`pwd`/memcached-mirror \ |
belaran@999 | 15626 http://code.sixapart.com/svn/memcached</userinput></screen> |
belaran@999 | 15627 |
belaran@999 | 15628 <para id="x_710">La prochaine étape est de commencer le processus de |
belaran@999 | 15629 mirroring de <command moreinfo="none">svnsync</command>.</para> |
belaran@999 | 15630 |
belaran@999 | 15631 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">svnsync sync file://`pwd`/memcached-mirror</userinput></screen> |
belaran@999 | 15632 |
belaran@999 | 15633 <para id="x_711">Enfin, nous importons l'historique de notre dépôt |
belaran@999 | 15634 local Subversion dans Mercurial.</para> |
belaran@999 | 15635 |
belaran@999 | 15636 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg convert memcached-mirror</userinput></screen> |
belaran@999 | 15637 |
belaran@999 | 15638 <para id="x_712">Nous pouvons utiliser ce processus de manière |
belaran@999 | 15639 incrémentale, si le dépôt Subversion est toujours en activité. |
belaran@999 | 15640 Il suffit d'exécuter de nouveau <command moreinfo="none">svnsync</command> pour |
belaran@999 | 15641 récupérer les récentes modifications dans notre miroir, puis <command moreinfo="none">hg |
belaran@999 | 15642 convert</command> |
belaran@999 | 15643 les importe dans notre arborescence Mercurial.</para> |
belaran@999 | 15644 |
belaran@999 | 15645 <para id="x_713">Il y a deux avantages à utiliser un import à deux |
belaran@999 | 15646 étages comme avec <command moreinfo="none">svnsync</command>. Le premier |
belaran@999 | 15647 est qu'il utilise du code de synchronisation réseau de Subversion |
belaran@999 | 15648 plus efficace que la commande <command moreinfo="none">hg convert</command>, |
belaran@999 | 15649 et donc transfère moins de données par le réseau. Le deuxième |
belaran@999 | 15650 est que l'import depuis un dépôt Subversion local est si rapide que |
belaran@999 | 15651 vous pouvez peaufiner et réitérer les paramètres de conversion de |
belaran@999 | 15652 ce dernier sans souffrir de la qualité de la connexion réseau.</para> |
belaran@999 | 15653 </sect2> |
belaran@999 | 15654 </sect1> |
belaran@999 | 15655 |
belaran@999 | 15656 <sect1> |
belaran@999 | 15657 <title>Migrer depuis Subversion</title> |
belaran@999 | 15658 |
belaran@999 | 15659 <para id="x_6f8">Subversion est le système de gestion de versions |
belaran@999 | 15660 open source le plus populaire aujourd'hui. Bien qu'il y ait des |
belaran@999 | 15661 différences entre Mercurial et Subversion, faire la transition de |
belaran@999 | 15662 l'un à l'autre n'est pas très difficile. Les deux disposent en effet |
belaran@999 | 15663 de jeux de commandes similaires et d'interfaces similaires.</para> |
belaran@999 | 15664 |
belaran@999 | 15665 <sect2> |
belaran@999 | 15666 <title>Différences philosophiques</title> |
belaran@999 | 15667 |
belaran@999 | 15668 <para id="x_6f9">La différence fondamentale entre Subversion et |
belaran@999 | 15669 Mercurial est bien évidement que Subversion est centralisé, alors |
belaran@999 | 15670 que Mercurial est distribué. Puisque que Mercurial enregistre tout |
belaran@999 | 15671 l'historique d'un projet sur votre disque dur local, il n'a besoin |
belaran@999 | 15672 d'effectuer des accès au réseau que lorsque vous voulez |
belaran@999 | 15673 explicitement communiquer avec un autre dépôt. Subversion, par contre, |
belaran@999 | 15674 ne conserve que peu d'informations localement, et le client |
belaran@999 | 15675 doit donc communiquer avec le serveur central pour la |
belaran@999 | 15676 plupart des opérations communes.</para> |
belaran@999 | 15677 |
belaran@999 | 15678 <para id="x_6fa">Subversion s'en tire plus ou moins bien sans notion |
belaran@999 | 15679 de branche réellement bien définie : quelle portion de l'espace de nommage |
belaran@999 | 15680 du serveur est une branche est une simple question de convention, le |
belaran@999 | 15681 logiciel n'imposant rien à ce sujet. Mercurial considère |
belaran@999 | 15682 un dépôt comme un élément de la gestion des branches.</para> |
belaran@999 | 15683 |
belaran@999 | 15684 <sect3> |
belaran@999 | 15685 <title>Portée des commandes</title> |
belaran@999 | 15686 |
belaran@999 | 15687 <para id="x_6fb">Puisque que Subversion ne sait pas réellement |
belaran@999 | 15688 quelle partie de son espace de nommage est en fait une branche, il |
belaran@999 | 15689 traite la plupart des commandes comme des requêtes à exécuter sur le |
belaran@999 | 15690 répertoire où vous vous situez, et ses sous répertoires. Par exemple, |
belaran@999 | 15691 si vous exécutez <command moreinfo="none">svn log</command>, vous verrez l'historique |
belaran@999 | 15692 de la partie de l'arborescence où vous vous situez, et non de la |
belaran@999 | 15693 hiérarchie entière.</para> |
belaran@999 | 15694 |
belaran@999 | 15695 <para id="x_6fc">Les commandes de Mercurial ont un comportement |
belaran@999 | 15696 différent : toutes les commandes s'appliquent à l'ensemble de l'arborescence |
belaran@999 | 15697 du dépôt. Exécutez la commande <command moreinfo="none">hg log</command> et elle vous |
belaran@999 | 15698 donnera l'historique de l'ensemble de l'arborescence, quel que soit le |
belaran@999 | 15699 sous-répertoire où vous vous situez. Si |
belaran@999 | 15700 vous souhaitez obtenir l'historique d'un répertoire ou seulement d'un |
belaran@999 | 15701 fichier, ajouter simplement le nom de celui-ci à la commande, par |
belaran@999 | 15702 exemple <command moreinfo="none">hg log src</command>.</para> |
belaran@999 | 15703 |
belaran@999 | 15704 <para id="x_6fd">De ma propre expérience, cette différence dans leur |
belaran@999 | 15705 comportement par défaut est probablement ce qui risque de vous |
belaran@999 | 15706 surprendre le plus si vous passez régulièrement d'un outil à l'autre.</para> |
belaran@999 | 15707 </sect3> |
belaran@999 | 15708 |
belaran@999 | 15709 <sect3> |
belaran@999 | 15710 <title>Opération multi utilisateur et sécurité</title> |
belaran@999 | 15711 |
belaran@999 | 15712 <para id="x_6fe">Avec Subversion, il est normal (bien que légèrement |
belaran@999 | 15713 désapprouvé) que différentes personnes collaborent sur une seule |
belaran@999 | 15714 branche. Si Alice et Bob travaillent ensemble, et Alice ajoute ses |
belaran@999 | 15715 modifications à leur branche partagée, Bob doit alors mettre à jour |
belaran@999 | 15716 sa vue de la branche avant de pouvoir appliquer un commit. |
belaran@999 | 15717 Puisqu'il n'a, à ce moment, pas effectué de commit |
belaran@999 | 15718 des modifications qu'il a faites, il se peut qu'il ne corrompe |
belaran@999 | 15719 ou ne perde |
belaran@999 | 15720 ses modifications pendant ou après la mise à jour.</para> |
belaran@999 | 15721 |
belaran@999 | 15722 <para id="x_6ff">Mercurial encourage, à l'inverse, un modèle |
belaran@999 | 15723 "commit-puis-merge". Avant de récupérer des modifications depuis le |
belaran@999 | 15724 serveur, ou avant d'y envoyer les siennes, Bob enregistre ses |
belaran@999 | 15725 modifications de manière locale en appliquant un commit. C'est à dire |
belaran@999 | 15726 que si Alice avait envoyé ses modifications sur le serveur avant |
belaran@999 | 15727 que Bob n'envoie les siennes, ce dernier ne pourra le faire |
belaran@999 | 15728 qu'après avoir récupéré et fusionné celles d'Alice avec les siennes. |
belaran@999 | 15729 Si Bob fait alors une |
belaran@999 | 15730 erreur lors de la fusion, il pourra toujours restaurer sa version, pour |
belaran@999 | 15731 laquelle il avait appliqué le commit.</para> |
belaran@999 | 15732 |
belaran@999 | 15733 <para id="x_700">Il est important de souligner qu'il s'agit de la |
belaran@999 | 15734 manière habituelle de travailler avec ces outils. Subversion propose |
belaran@999 | 15735 une manière plus sûre de "travailler-dans-votre-propre-branche", mais elle |
belaran@999 | 15736 est assez complexe pour que, en pratique, elle ne soit que rarement utilisé. |
belaran@999 | 15737 Mercurial propose de son côté un mode un peu moins sûr, permettant de |
belaran@999 | 15738 récupérer des modifications par dessus des modifications non |
belaran@999 | 15739 committées, qui reste toutefois très peu répandu.</para> |
belaran@999 | 15740 </sect3> |
belaran@999 | 15741 |
belaran@999 | 15742 <sect3> |
belaran@999 | 15743 <title>Publication vs changement locaux</title> |
belaran@999 | 15744 |
belaran@999 | 15745 <para id="x_701">Une commande Subversion <command moreinfo="none">svn |
belaran@999 | 15746 commit</command> publie immédiatement les modifications sur le |
belaran@999 | 15747 serveur, où elles peuvent être vu par n'importe qui doté d'un privilège |
belaran@999 | 15748 de lecture.</para> |
belaran@999 | 15749 |
belaran@999 | 15750 <para id="x_702">Avec Mercurial, les modifications sont toujours d'abord |
belaran@999 | 15751 enregistrées localement, et doivent être par la suite transférés par |
belaran@999 | 15752 la commande <command moreinfo="none">hg push</command>.</para> |
belaran@999 | 15753 |
belaran@999 | 15754 <para id="x_703">Chaque approche a ses avantages et ses inconvénients. |
belaran@999 | 15755 Le modèle Subversion implique que les modifications soient publiées, et |
belaran@999 | 15756 donc disponibles immédiatement. D'un autre coté, cela implique aussi |
belaran@999 | 15757 que, pour pouvoir utiliser le logiciel normalement, un utilisateur doit |
belaran@999 | 15758 avoir les droits d'écriture dans le dépôt, et ce privilège n'est pas concédé |
belaran@999 | 15759 facilement par la plupart des projets Open Source.</para> |
belaran@999 | 15760 |
belaran@999 | 15761 <para id="x_704">L'approche de Mercurial permet à quiconque de faire |
belaran@999 | 15762 un clone du dépôt et d'y ajouter ses modifications sans jamais avoir |
belaran@999 | 15763 besoin de la permission de quiconque, et l'on peut même publier ses |
belaran@999 | 15764 modifications et continuer à participer comme on le désire. Toutefois, la |
belaran@999 | 15765 distinction entre les commits et le transfert de ces derniers présente |
belaran@999 | 15766 le risque que quelqu'un applique ses modifications par un commit local |
belaran@999 | 15767 sur son portable et parte se promener pendant quelques jours en ayant |
belaran@999 | 15768 oublié de les transférer, ce qui peut, dans certains rares cas, |
belaran@999 | 15769 bloquer temporairement ses collaborateurs.</para> |
belaran@999 | 15770 </sect3> |
belaran@999 | 15771 </sect2> |
belaran@999 | 15772 |
belaran@999 | 15773 <sect2> |
belaran@999 | 15774 <title>Références des commandes</title> |
belaran@999 | 15775 |
belaran@999 | 15776 <table> |
belaran@999 | 15777 <title>Commandes Subversion et leurs équivalents Mercurial</title> |
belaran@999 | 15778 <tgroup cols="3"> |
belaran@999 | 15779 <thead> |
belaran@999 | 15780 <row> |
belaran@999 | 15781 <entry>Subversion</entry> |
belaran@999 | 15782 <entry>Mercurial</entry> |
belaran@999 | 15783 <entry>Notes</entry> |
belaran@999 | 15784 </row> |
belaran@999 | 15785 </thead> |
belaran@999 | 15786 <tbody> |
belaran@999 | 15787 <row> |
belaran@999 | 15788 <entry><command moreinfo="none">svn add</command></entry> |
belaran@999 | 15789 <entry><command moreinfo="none">hg add</command></entry> |
belaran@999 | 15790 <entry/> |
belaran@999 | 15791 </row> |
belaran@999 | 15792 <row> |
belaran@999 | 15793 <entry><command moreinfo="none">svn blame</command></entry> |
belaran@999 | 15794 <entry><command moreinfo="none">hg annotate</command></entry> |
belaran@999 | 15795 <entry/> |
belaran@999 | 15796 </row> |
belaran@999 | 15797 <row> |
belaran@999 | 15798 <entry><command moreinfo="none">svn cat</command></entry> |
belaran@999 | 15799 <entry><command moreinfo="none">hg cat</command></entry> |
belaran@999 | 15800 <entry/> |
belaran@999 | 15801 </row> |
belaran@999 | 15802 <row> |
belaran@999 | 15803 <entry><command moreinfo="none">svn checkout</command></entry> |
belaran@999 | 15804 <entry><command moreinfo="none">hg clone</command></entry> |
belaran@999 | 15805 <entry/> |
belaran@999 | 15806 </row> |
belaran@999 | 15807 <row> |
belaran@999 | 15808 <entry><command moreinfo="none">svn cleanup</command></entry> |
belaran@999 | 15809 <entry>n/a</entry> |
belaran@999 | 15810 <entry>Aucun nettoyage nécessaire.</entry> |
belaran@999 | 15811 </row> |
belaran@999 | 15812 <row> |
belaran@999 | 15813 <entry><command moreinfo="none">svn commit</command></entry> |
belaran@999 | 15814 <entry><command moreinfo="none">hg commit</command>; <command moreinfo="none">hg |
belaran@999 | 15815 push</command></entry> |
belaran@999 | 15816 <entry><command moreinfo="none">hg push</command> publie les modifications |
belaran@999 | 15817 après un commit.</entry> |
belaran@999 | 15818 </row> |
belaran@999 | 15819 <row> |
belaran@999 | 15820 <entry><command moreinfo="none">svn copy</command></entry> |
belaran@999 | 15821 <entry><command moreinfo="none">hg clone</command></entry> |
belaran@999 | 15822 <entry>Pour créer une nouvelle branche</entry> |
belaran@999 | 15823 </row> |
belaran@999 | 15824 <row> |
belaran@999 | 15825 <entry><command moreinfo="none">svn copy</command></entry> |
belaran@999 | 15826 <entry><command moreinfo="none">hg copy</command></entry> |
belaran@999 | 15827 <entry>Pour copier des fichiers ou des répertoires</entry> |
belaran@999 | 15828 </row> |
belaran@999 | 15829 <row> |
belaran@999 | 15830 <entry><command moreinfo="none">svn delete</command> (<command moreinfo="none">svn |
belaran@999 | 15831 remove</command>)</entry> |
belaran@999 | 15832 <entry><command moreinfo="none">hg remove</command></entry> |
belaran@999 | 15833 <entry/> |
belaran@999 | 15834 </row> |
belaran@999 | 15835 <row> |
belaran@999 | 15836 <entry><command moreinfo="none">svn diff</command></entry> |
belaran@999 | 15837 <entry><command moreinfo="none">hg diff</command></entry> |
belaran@999 | 15838 <entry/> |
belaran@999 | 15839 </row> |
belaran@999 | 15840 <row> |
belaran@999 | 15841 <entry><command moreinfo="none">svn export</command></entry> |
belaran@999 | 15842 <entry><command moreinfo="none">hg archive</command></entry> |
belaran@999 | 15843 <entry/> |
belaran@999 | 15844 </row> |
belaran@999 | 15845 <row> |
belaran@999 | 15846 <entry><command moreinfo="none">svn help</command></entry> |
belaran@999 | 15847 <entry><command moreinfo="none">hg help</command></entry> |
belaran@999 | 15848 <entry/> |
belaran@999 | 15849 </row> |
belaran@999 | 15850 <row> |
belaran@999 | 15851 <entry><command moreinfo="none">svn import</command></entry> |
belaran@999 | 15852 <entry><command moreinfo="none">hg addremove</command>; <command moreinfo="none">hg |
belaran@999 | 15853 commit</command></entry> |
belaran@999 | 15854 <entry/> |
belaran@999 | 15855 </row> |
belaran@999 | 15856 <row> |
belaran@999 | 15857 <entry><command moreinfo="none">svn info</command></entry> |
belaran@999 | 15858 <entry><command moreinfo="none">hg parents</command></entry> |
belaran@999 | 15859 <entry>Affiche la version sur la base de laquelle on travaille</entry> |
belaran@999 | 15860 </row> |
belaran@999 | 15861 <row> |
belaran@999 | 15862 <entry><command moreinfo="none">svn info</command></entry> |
belaran@999 | 15863 <entry><command moreinfo="none">hg showconfig |
belaran@999 | 15864 paths.default</command></entry> |
belaran@999 | 15865 <entry>Affiche de quelle URL est extrait ce dépôt</entry> |
belaran@999 | 15866 </row> |
belaran@999 | 15867 <row> |
belaran@999 | 15868 <entry><command moreinfo="none">svn list</command></entry> |
belaran@999 | 15869 <entry><command moreinfo="none">hg manifest</command></entry> |
belaran@999 | 15870 <entry/> |
belaran@999 | 15871 </row> |
belaran@999 | 15872 <row> |
belaran@999 | 15873 <entry><command moreinfo="none">svn log</command></entry> |
belaran@999 | 15874 <entry><command moreinfo="none">hg log</command></entry> |
belaran@999 | 15875 <entry/> |
belaran@999 | 15876 </row> |
belaran@999 | 15877 <row> |
belaran@999 | 15878 <entry><command moreinfo="none">svn merge</command></entry> |
belaran@999 | 15879 <entry><command moreinfo="none">hg merge</command></entry> |
belaran@999 | 15880 <entry/> |
belaran@999 | 15881 </row> |
belaran@999 | 15882 <row> |
belaran@999 | 15883 <entry><command moreinfo="none">svn mkdir</command></entry> |
belaran@999 | 15884 <entry>n/a</entry> |
belaran@999 | 15885 <entry>Mercurial ne versionne pas les répertoires</entry> |
belaran@999 | 15886 </row> |
belaran@999 | 15887 <row> |
belaran@999 | 15888 <entry><command moreinfo="none">svn move</command> (<command moreinfo="none">svn |
belaran@999 | 15889 rename</command>)</entry> |
belaran@999 | 15890 <entry><command moreinfo="none">hg rename</command></entry> |
belaran@999 | 15891 <entry/> |
belaran@999 | 15892 </row> |
belaran@999 | 15893 <row> |
belaran@999 | 15894 <entry><command moreinfo="none">svn resolved</command></entry> |
belaran@999 | 15895 <entry><command moreinfo="none">hg resolve -m</command></entry> |
belaran@999 | 15896 <entry/> |
belaran@999 | 15897 </row> |
belaran@999 | 15898 <row> |
belaran@999 | 15899 <entry><command moreinfo="none">svn revert</command></entry> |
belaran@999 | 15900 <entry><command moreinfo="none">hg revert</command></entry> |
belaran@999 | 15901 <entry/> |
belaran@999 | 15902 </row> |
belaran@999 | 15903 <row> |
belaran@999 | 15904 <entry><command moreinfo="none">svn status</command></entry> |
belaran@999 | 15905 <entry><command moreinfo="none">hg status</command></entry> |
belaran@999 | 15906 <entry/> |
belaran@999 | 15907 </row> |
belaran@999 | 15908 <row> |
belaran@999 | 15909 <entry><command moreinfo="none">svn update</command></entry> |
belaran@999 | 15910 <entry><command moreinfo="none">hg pull -u</command></entry> |
belaran@999 | 15911 <entry/> |
belaran@999 | 15912 </row> |
belaran@999 | 15913 </tbody> |
belaran@999 | 15914 </tgroup> |
belaran@999 | 15915 </table> |
belaran@999 | 15916 </sect2> |
belaran@999 | 15917 </sect1> |
belaran@999 | 15918 |
belaran@999 | 15919 <sect1> |
belaran@999 | 15920 <title>Conseils utiles pour les débutants</title> |
belaran@999 | 15921 |
belaran@999 | 15922 <para id="x_705">Avec la plupart des gestionnaire de versions, afficher |
belaran@999 | 15923 un diff associé à une révision peut être assez douloureux. Par exemple, |
belaran@999 | 15924 avec Subversion, pour voir ce qui a été modifiée dans la révision 104654, |
belaran@999 | 15925 vous devez saisir <command moreinfo="none">svn diff -r104653:104654</command>. Mercurial |
belaran@999 | 15926 élimine le besoin de saisir l'identifiant d'une révision deux fois dans |
belaran@999 | 15927 ce cas classique. Pour un simple diff, <command moreinfo="none">hg |
belaran@999 | 15928 export 104654</command> suffit. Pour obtenir une entrée du journal suivie d'un diff, |
belaran@999 | 15929 <command moreinfo="none">hg log -r104654 -p</command>.</para> |
belaran@999 | 15930 |
belaran@999 | 15931 <para id="x_706">Quand vous exécutez la commande <command moreinfo="none">hg status</command> |
belaran@999 | 15932 sans aucun argument, elle affiche l'état de l'ensemble de l'arborescence, |
belaran@999 | 15933 avec des chemins relatifs partant de la racine du dépôt. Ceci rend |
belaran@999 | 15934 difficile de copier un nom de fichier depuis la sortie de la commande |
belaran@999 | 15935 <command moreinfo="none">hg status</command> dans une autre ligne de commande. Si vous |
belaran@999 | 15936 fournissez un fichier ou un répertoire à la commande <command moreinfo="none">hg |
belaran@999 | 15937 status</command>, elle va afficher les chemins relatif depuis votre |
belaran@999 | 15938 répertoire courant à la place. Ainsi, pour avoir un état sur l'ensemble |
belaran@999 | 15939 de l'arborescence à l'aide de <command moreinfo="none">hg status</command>, avec des |
belaran@999 | 15940 chemins relatifs à votre répertoire courant, et non la racine du dépôt, |
belaran@999 | 15941 ajoutez la sortie de <command moreinfo="none">hg root</command> à la commande |
belaran@999 | 15942 <command moreinfo="none">hg status</command>. Vous pouvez le faire aisément sur un |
belaran@999 | 15943 système Unix ainsi :</para> |
belaran@999 | 15944 |
belaran@999 | 15945 <screen format="linespecific"><prompt moreinfo="none">$</prompt> <userinput moreinfo="none">hg status `hg root`</userinput></screen> |
belaran@999 | 15946 </sect1> |
belaran@999 | 15947 </appendix> |
belaran@999 | 15948 |
belaran@999 | 15949 <!-- |
belaran@999 | 15950 local variables: |
belaran@999 | 15951 sgml-parent-document: ("00book.xml" "book" "appendix") |
belaran@999 | 15952 end: |
belaran@999 | 15953 --> |
belaran@999 | 15954 |
belaran@999 | 15955 <!-- BEGIN appB --> |
belaran@999 | 15956 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 15957 |
belaran@999 | 15958 <appendix id="chap:mqref"> |
belaran@999 | 15959 <?dbhtml filename="mercurial-queues-reference.html"?> |
belaran@999 | 15960 <title>Mercurial Queues reference</title> |
belaran@999 | 15961 |
belaran@999 | 15962 <sect1 id="sec:mqref:cmdref"> |
belaran@999 | 15963 <title>MQ command reference</title> |
belaran@999 | 15964 |
belaran@999 | 15965 <para id="x_5e8">For an overview of the commands provided by MQ, use the |
belaran@999 | 15966 command <command role="hg-cmd" moreinfo="none">hg help mq</command>.</para> |
belaran@999 | 15967 |
belaran@999 | 15968 <sect2> |
belaran@999 | 15969 <title><command role="hg-ext-mq" moreinfo="none">qapplied</command>—print |
belaran@999 | 15970 applied patches</title> |
belaran@999 | 15971 |
belaran@999 | 15972 <para id="x_5e9">The <command role="hg-ext-mq" moreinfo="none">qapplied</command> command |
belaran@999 | 15973 prints the current stack of applied patches. Patches are |
belaran@999 | 15974 printed in oldest-to-newest order, so the last patch in the |
belaran@999 | 15975 list is the <quote>top</quote> patch.</para> |
belaran@999 | 15976 |
belaran@999 | 15977 </sect2> |
belaran@999 | 15978 <sect2> |
belaran@999 | 15979 <title><command role="hg-ext-mq" moreinfo="none">qcommit</command>—commit |
belaran@999 | 15980 changes in the queue repository</title> |
belaran@999 | 15981 |
belaran@999 | 15982 <para id="x_5ea">The <command role="hg-ext-mq" moreinfo="none">qcommit</command> command |
belaran@999 | 15983 commits any outstanding changes in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> |
belaran@999 | 15984 repository. This command only works if the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> |
belaran@999 | 15985 directory is a repository, i.e. you created the directory |
belaran@999 | 15986 using <command role="hg-cmd" moreinfo="none">hg qinit <option role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or |
belaran@999 | 15987 ran <command role="hg-cmd" moreinfo="none">hg init</command> in the directory |
belaran@999 | 15988 after running <command role="hg-ext-mq" moreinfo="none">qinit</command>.</para> |
belaran@999 | 15989 |
belaran@999 | 15990 <para id="x_5eb">This command is shorthand for <command role="hg-cmd" moreinfo="none">hg |
belaran@999 | 15991 commit --cwd .hg/patches</command>.</para> |
belaran@999 | 15992 </sect2> |
belaran@999 | 15993 <sect2> |
belaran@999 | 15994 <title><command role="hg-ext-mq" moreinfo="none">qdelete</command>—delete a patch |
belaran@999 | 15995 from the <filename role="special" moreinfo="none">series</filename> |
belaran@999 | 15996 file</title> |
belaran@999 | 15997 |
belaran@999 | 15998 <para id="x_5ec">The <command role="hg-ext-mq" moreinfo="none">qdelete</command> command |
belaran@999 | 15999 removes the entry for a patch from the <filename role="special" moreinfo="none">series</filename> file in the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> |
belaran@999 | 16000 directory. It does not pop the patch if the patch is already |
belaran@999 | 16001 applied. By default, it does not delete the patch file; use |
belaran@999 | 16002 the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option |
belaran@999 | 16003 to do that.</para> |
belaran@999 | 16004 |
belaran@999 | 16005 <para id="x_5ed">Options:</para> |
belaran@999 | 16006 <itemizedlist> |
belaran@999 | 16007 <listitem><para id="x_5ee"><option role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the |
belaran@999 | 16008 patch file.</para> |
belaran@999 | 16009 </listitem></itemizedlist> |
belaran@999 | 16010 |
belaran@999 | 16011 </sect2> |
belaran@999 | 16012 <sect2> |
belaran@999 | 16013 <title><command role="hg-ext-mq" moreinfo="none">qdiff</command>—print a |
belaran@999 | 16014 diff of the topmost applied patch</title> |
belaran@999 | 16015 |
belaran@999 | 16016 <para id="x_5ef">The <command role="hg-ext-mq" moreinfo="none">qdiff</command> command |
belaran@999 | 16017 prints a diff of the topmost applied patch. It is equivalent |
belaran@999 | 16018 to <command role="hg-cmd" moreinfo="none">hg diff -r-2:-1</command>.</para> |
belaran@999 | 16019 |
belaran@999 | 16020 </sect2> |
belaran@999 | 16021 <sect2> |
belaran@999 | 16022 <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—move |
belaran@999 | 16023 applied patches into repository history</title> |
belaran@999 | 16024 |
belaran@999 | 16025 <para id="x_72d">The <command moreinfo="none">hg qfinish</command> command converts the |
belaran@999 | 16026 specified applied patches into permanent changes by moving |
belaran@999 | 16027 them out of MQ's control so that they will be treated as |
belaran@999 | 16028 normal repository history.</para> |
belaran@999 | 16029 </sect2> |
belaran@999 | 16030 |
belaran@999 | 16031 <sect2> |
belaran@999 | 16032 <title><command role="hg-ext-mq" moreinfo="none">qfold</command>—merge |
belaran@999 | 16033 (<quote>fold</quote>) several patches into one</title> |
belaran@999 | 16034 |
belaran@999 | 16035 <para id="x_5f0">The <command role="hg-ext-mq" moreinfo="none">qfold</command> command |
belaran@999 | 16036 merges multiple patches into the topmost applied patch, so |
belaran@999 | 16037 that the topmost applied patch makes the union of all of the |
belaran@999 | 16038 changes in the patches in question.</para> |
belaran@999 | 16039 |
belaran@999 | 16040 <para id="x_5f1">The patches to fold must not be applied; <command role="hg-ext-mq" moreinfo="none">qfold</command> will exit with an error if |
belaran@999 | 16041 any is. The order in which patches are folded is significant; |
belaran@999 | 16042 <command role="hg-cmd" moreinfo="none">hg qfold a b</command> means |
belaran@999 | 16043 <quote>apply the current topmost patch, followed by |
belaran@999 | 16044 <literal moreinfo="none">a</literal>, followed by |
belaran@999 | 16045 <literal moreinfo="none">b</literal></quote>.</para> |
belaran@999 | 16046 |
belaran@999 | 16047 <para id="x_5f2">The comments from the folded patches are appended to the |
belaran@999 | 16048 comments of the destination patch, with each block of comments |
belaran@999 | 16049 separated by three asterisk |
belaran@999 | 16050 (<quote><literal moreinfo="none">*</literal></quote>) characters. Use the |
belaran@999 | 16051 <option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to |
belaran@999 | 16052 edit the commit message for the combined patch/changeset after |
belaran@999 | 16053 the folding has completed.</para> |
belaran@999 | 16054 |
belaran@999 | 16055 <para id="x_5f3">Options:</para> |
belaran@999 | 16056 <itemizedlist> |
belaran@999 | 16057 <listitem><para id="x_5f4"><option role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the |
belaran@999 | 16058 commit message and patch description for the newly folded |
belaran@999 | 16059 patch.</para> |
belaran@999 | 16060 </listitem> |
belaran@999 | 16061 <listitem><para id="x_5f5"><option role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the |
belaran@999 | 16062 contents of the given file as the new commit message and |
belaran@999 | 16063 patch description for the folded patch.</para> |
belaran@999 | 16064 </listitem> |
belaran@999 | 16065 <listitem><para id="x_5f6"><option role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the |
belaran@999 | 16066 given text as the new commit message and patch description |
belaran@999 | 16067 for the folded patch.</para> |
belaran@999 | 16068 </listitem></itemizedlist> |
belaran@999 | 16069 |
belaran@999 | 16070 </sect2> |
belaran@999 | 16071 <sect2> |
belaran@999 | 16072 <title><command role="hg-ext-mq" moreinfo="none">qheader</command>—display the |
belaran@999 | 16073 header/description of a patch</title> |
belaran@999 | 16074 |
belaran@999 | 16075 <para id="x_5f7">The <command role="hg-ext-mq" moreinfo="none">qheader</command> command |
belaran@999 | 16076 prints the header, or description, of a patch. By default, it |
belaran@999 | 16077 prints the header of the topmost applied patch. Given an |
belaran@999 | 16078 argument, it prints the header of the named patch.</para> |
belaran@999 | 16079 |
belaran@999 | 16080 </sect2> |
belaran@999 | 16081 <sect2> |
belaran@999 | 16082 <title><command role="hg-ext-mq" moreinfo="none">qimport</command>—import |
belaran@999 | 16083 a third-party patch into the queue</title> |
belaran@999 | 16084 |
belaran@999 | 16085 <para id="x_5f8">The <command role="hg-ext-mq" moreinfo="none">qimport</command> command |
belaran@999 | 16086 adds an entry for an external patch to the <filename role="special" moreinfo="none">series</filename> file, and copies the patch |
belaran@999 | 16087 into the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory. It adds |
belaran@999 | 16088 the entry immediately after the topmost applied patch, but |
belaran@999 | 16089 does not push the patch.</para> |
belaran@999 | 16090 |
belaran@999 | 16091 <para id="x_5f9">If the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a |
belaran@999 | 16092 repository, <command role="hg-ext-mq" moreinfo="none">qimport</command> |
belaran@999 | 16093 automatically does an <command role="hg-cmd" moreinfo="none">hg add</command> |
belaran@999 | 16094 of the imported patch.</para> |
belaran@999 | 16095 |
belaran@999 | 16096 </sect2> |
belaran@999 | 16097 <sect2> |
belaran@999 | 16098 <title><command role="hg-ext-mq" moreinfo="none">qinit</command>—prepare |
belaran@999 | 16099 a repository to work with MQ</title> |
belaran@999 | 16100 |
belaran@999 | 16101 <para id="x_5fa">The <command role="hg-ext-mq" moreinfo="none">qinit</command> command |
belaran@999 | 16102 prepares a repository to work with MQ. It creates a directory |
belaran@999 | 16103 called <filename role="special" class="directory" moreinfo="none">.hg/patches</filename>.</para> |
belaran@999 | 16104 |
belaran@999 | 16105 <para id="x_5fb">Options:</para> |
belaran@999 | 16106 <itemizedlist> |
belaran@999 | 16107 <listitem><para id="x_5fc"><option role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create |
belaran@999 | 16108 <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> as a repository |
belaran@999 | 16109 in its own right. Also creates a <filename role="special" moreinfo="none">.hgignore</filename> file that will |
belaran@999 | 16110 ignore the <filename role="special" moreinfo="none">status</filename> |
belaran@999 | 16111 file.</para> |
belaran@999 | 16112 </listitem></itemizedlist> |
belaran@999 | 16113 |
belaran@999 | 16114 <para id="x_5fd">When the <filename role="special" class="directory" moreinfo="none">.hg/patches</filename> directory is a |
belaran@999 | 16115 repository, the <command role="hg-ext-mq" moreinfo="none">qimport</command> |
belaran@999 | 16116 and <command role="hg-ext-mq" moreinfo="none">qnew</command> commands |
belaran@999 | 16117 automatically <command role="hg-cmd" moreinfo="none">hg add</command> new |
belaran@999 | 16118 patches.</para> |
belaran@999 | 16119 |
belaran@999 | 16120 </sect2> |
belaran@999 | 16121 <sect2> |
belaran@999 | 16122 <title><command role="hg-ext-mq" moreinfo="none">qnew</command>—create a |
belaran@999 | 16123 new patch</title> |
belaran@999 | 16124 |
belaran@999 | 16125 <para id="x_5fe">The <command role="hg-ext-mq" moreinfo="none">qnew</command> command |
belaran@999 | 16126 creates a new patch. It takes one mandatory argument, the |
belaran@999 | 16127 name to use for the patch file. The newly created patch is |
belaran@999 | 16128 created empty by default. It is added to the <filename role="special" moreinfo="none">series</filename> file after the current |
belaran@999 | 16129 topmost applied patch, and is immediately pushed on top of |
belaran@999 | 16130 that patch.</para> |
belaran@999 | 16131 |
belaran@999 | 16132 <para id="x_5ff">If <command role="hg-ext-mq" moreinfo="none">qnew</command> finds modified |
belaran@999 | 16133 files in the working directory, it will refuse to create a new |
belaran@999 | 16134 patch unless the <option role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used |
belaran@999 | 16135 (see below). This behavior allows you to <command role="hg-ext-mq" moreinfo="none">qrefresh</command> your topmost applied |
belaran@999 | 16136 patch before you apply a new patch on top of it.</para> |
belaran@999 | 16137 |
belaran@999 | 16138 <para id="x_600">Options:</para> |
belaran@999 | 16139 <itemizedlist> |
belaran@999 | 16140 <listitem><para id="x_601"><option role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new |
belaran@999 | 16141 patch if the contents of the working directory are |
belaran@999 | 16142 modified. Any outstanding modifications are added to the |
belaran@999 | 16143 newly created patch, so after this command completes, the |
belaran@999 | 16144 working directory will no longer be modified.</para> |
belaran@999 | 16145 </listitem> |
belaran@999 | 16146 <listitem><para id="x_602"><option role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given |
belaran@999 | 16147 text as the commit message. This text will be stored at |
belaran@999 | 16148 the beginning of the patch file, before the patch |
belaran@999 | 16149 data.</para> |
belaran@999 | 16150 </listitem></itemizedlist> |
belaran@999 | 16151 |
belaran@999 | 16152 </sect2> |
belaran@999 | 16153 <sect2> |
belaran@999 | 16154 <title><command role="hg-ext-mq" moreinfo="none">qnext</command>—print |
belaran@999 | 16155 the name of the next patch</title> |
belaran@999 | 16156 |
belaran@999 | 16157 <para id="x_603">The <command role="hg-ext-mq" moreinfo="none">qnext</command> command |
belaran@999 | 16158 prints the name name of the next patch in the <filename role="special" moreinfo="none">series</filename> file after the topmost |
belaran@999 | 16159 applied patch. This patch will become the topmost applied |
belaran@999 | 16160 patch if you run <command role="hg-ext-mq" moreinfo="none">qpush</command>.</para> |
belaran@999 | 16161 |
belaran@999 | 16162 </sect2> |
belaran@999 | 16163 <sect2> |
belaran@999 | 16164 <title><command role="hg-ext-mq" moreinfo="none">qpop</command>—pop |
belaran@999 | 16165 patches off the stack</title> |
belaran@999 | 16166 |
belaran@999 | 16167 <para id="x_604">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command |
belaran@999 | 16168 removes applied patches from the top of the stack of applied |
belaran@999 | 16169 patches. By default, it removes only one patch.</para> |
belaran@999 | 16170 |
belaran@999 | 16171 <para id="x_605">This command removes the changesets that represent the |
belaran@999 | 16172 popped patches from the repository, and updates the working |
belaran@999 | 16173 directory to undo the effects of the patches.</para> |
belaran@999 | 16174 |
belaran@999 | 16175 <para id="x_606">This command takes an optional argument, which it uses as |
belaran@999 | 16176 the name or index of the patch to pop to. If given a name, it |
belaran@999 | 16177 will pop patches until the named patch is the topmost applied |
belaran@999 | 16178 patch. If given a number, <command role="hg-ext-mq" moreinfo="none">qpop</command> treats the number as an |
belaran@999 | 16179 index into the entries in the series file, counting from zero |
belaran@999 | 16180 (empty lines and lines containing only comments do not count). |
belaran@999 | 16181 It pops patches until the patch identified by the given index |
belaran@999 | 16182 is the topmost applied patch.</para> |
belaran@999 | 16183 |
belaran@999 | 16184 <para id="x_607">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command does |
belaran@999 | 16185 not read or write patches or the <filename role="special" moreinfo="none">series</filename> file. It is thus safe to |
belaran@999 | 16186 <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch that you have |
belaran@999 | 16187 removed from the <filename role="special" moreinfo="none">series</filename> |
belaran@999 | 16188 file, or a patch that you have renamed or deleted entirely. |
belaran@999 | 16189 In the latter two cases, use the name of the patch as it was |
belaran@999 | 16190 when you applied it.</para> |
belaran@999 | 16191 |
belaran@999 | 16192 <para id="x_608">By default, the <command role="hg-ext-mq" moreinfo="none">qpop</command> |
belaran@999 | 16193 command will not pop any patches if the working directory has |
belaran@999 | 16194 been modified. You can override this behavior using the |
belaran@999 | 16195 <option role="hg-ext-mq-cmd-qpop-opt">-f</option> option, |
belaran@999 | 16196 which reverts all modifications in the working |
belaran@999 | 16197 directory.</para> |
belaran@999 | 16198 |
belaran@999 | 16199 <para id="x_609">Options:</para> |
belaran@999 | 16200 <itemizedlist> |
belaran@999 | 16201 <listitem><para id="x_60a"><option role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all |
belaran@999 | 16202 applied patches. This returns the repository to its state |
belaran@999 | 16203 before you applied any patches.</para> |
belaran@999 | 16204 </listitem> |
belaran@999 | 16205 <listitem><para id="x_60b"><option role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly |
belaran@999 | 16206 revert any modifications to the working directory when |
belaran@999 | 16207 popping.</para> |
belaran@999 | 16208 </listitem> |
belaran@999 | 16209 <listitem><para id="x_60c"><option role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch |
belaran@999 | 16210 from the named queue.</para> |
belaran@999 | 16211 </listitem></itemizedlist> |
belaran@999 | 16212 |
belaran@999 | 16213 <para id="x_60d">The <command role="hg-ext-mq" moreinfo="none">qpop</command> command |
belaran@999 | 16214 removes one line from the end of the <filename role="special" moreinfo="none">status</filename> file for each patch that it |
belaran@999 | 16215 pops.</para> |
belaran@999 | 16216 |
belaran@999 | 16217 </sect2> |
belaran@999 | 16218 <sect2> |
belaran@999 | 16219 <title><command role="hg-ext-mq" moreinfo="none">qprev</command>—print |
belaran@999 | 16220 the name of the previous patch</title> |
belaran@999 | 16221 |
belaran@999 | 16222 <para id="x_60e">The <command role="hg-ext-mq" moreinfo="none">qprev</command> command |
belaran@999 | 16223 prints the name of the patch in the <filename role="special" moreinfo="none">series</filename> file that comes before the |
belaran@999 | 16224 topmost applied patch. This will become the topmost applied |
belaran@999 | 16225 patch if you run <command role="hg-ext-mq" moreinfo="none">qpop</command>.</para> |
belaran@999 | 16226 |
belaran@999 | 16227 </sect2> |
belaran@999 | 16228 <sect2 id="sec:mqref:cmd:qpush"> |
belaran@999 | 16229 <title><command role="hg-ext-mq" moreinfo="none">qpush</command>—push |
belaran@999 | 16230 patches onto the stack</title> |
belaran@999 | 16231 |
belaran@999 | 16232 <para id="x_60f">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command adds |
belaran@999 | 16233 patches onto the applied stack. By default, it adds only one |
belaran@999 | 16234 patch.</para> |
belaran@999 | 16235 |
belaran@999 | 16236 <para id="x_610">This command creates a new changeset to represent each |
belaran@999 | 16237 applied patch, and updates the working directory to apply the |
belaran@999 | 16238 effects of the patches.</para> |
belaran@999 | 16239 |
belaran@999 | 16240 <para id="x_611">The default data used when creating a changeset are as |
belaran@999 | 16241 follows:</para> |
belaran@999 | 16242 <itemizedlist> |
belaran@999 | 16243 <listitem><para id="x_612">The commit date and time zone are the current |
belaran@999 | 16244 date and time zone. Because these data are used to |
belaran@999 | 16245 compute the identity of a changeset, this means that if |
belaran@999 | 16246 you <command role="hg-ext-mq" moreinfo="none">qpop</command> a patch and |
belaran@999 | 16247 <command role="hg-ext-mq" moreinfo="none">qpush</command> it again, the |
belaran@999 | 16248 changeset that you push will have a different identity |
belaran@999 | 16249 than the changeset you popped.</para> |
belaran@999 | 16250 </listitem> |
belaran@999 | 16251 <listitem><para id="x_613">The author is the same as the default used by |
belaran@999 | 16252 the <command role="hg-cmd" moreinfo="none">hg commit</command> |
belaran@999 | 16253 command.</para> |
belaran@999 | 16254 </listitem> |
belaran@999 | 16255 <listitem><para id="x_614">The commit message is any text from the patch |
belaran@999 | 16256 file that comes before the first diff header. If there is |
belaran@999 | 16257 no such text, a default commit message is used that |
belaran@999 | 16258 identifies the name of the patch.</para> |
belaran@999 | 16259 </listitem></itemizedlist> |
belaran@999 | 16260 <para id="x_615">If a patch contains a Mercurial patch header, |
belaran@999 | 16261 the information in the patch header overrides these |
belaran@999 | 16262 defaults.</para> |
belaran@999 | 16263 |
belaran@999 | 16264 <para id="x_616">Options:</para> |
belaran@999 | 16265 <itemizedlist> |
belaran@999 | 16266 <listitem><para id="x_617"><option role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all |
belaran@999 | 16267 unapplied patches from the <filename role="special" moreinfo="none">series</filename> file until there are |
belaran@999 | 16268 none left to push.</para> |
belaran@999 | 16269 </listitem> |
belaran@999 | 16270 <listitem><para id="x_618"><option role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name |
belaran@999 | 16271 of the patch to the end of the commit message.</para> |
belaran@999 | 16272 </listitem> |
belaran@999 | 16273 <listitem><para id="x_619"><option role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch |
belaran@999 | 16274 fails to apply cleanly, use the entry for the patch in |
belaran@999 | 16275 another saved queue to compute the parameters for a |
belaran@999 | 16276 three-way merge, and perform a three-way merge using the |
belaran@999 | 16277 normal Mercurial merge machinery. Use the resolution of |
belaran@999 | 16278 the merge as the new patch content.</para> |
belaran@999 | 16279 </listitem> |
belaran@999 | 16280 <listitem><para id="x_61a"><option role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the |
belaran@999 | 16281 named queue if merging while pushing.</para> |
belaran@999 | 16282 </listitem></itemizedlist> |
belaran@999 | 16283 |
belaran@999 | 16284 <para id="x_61b">The <command role="hg-ext-mq" moreinfo="none">qpush</command> command |
belaran@999 | 16285 reads, but does not modify, the <filename role="special" moreinfo="none">series</filename> file. It appends one line |
belaran@999 | 16286 to the <command role="hg-cmd" moreinfo="none">hg status</command> file for |
belaran@999 | 16287 each patch that it pushes.</para> |
belaran@999 | 16288 |
belaran@999 | 16289 </sect2> |
belaran@999 | 16290 <sect2> |
belaran@999 | 16291 <title><command role="hg-ext-mq" moreinfo="none">qrefresh</command>—update the |
belaran@999 | 16292 topmost applied patch</title> |
belaran@999 | 16293 |
belaran@999 | 16294 <para id="x_61c">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command |
belaran@999 | 16295 updates the topmost applied patch. It modifies the patch, |
belaran@999 | 16296 removes the old changeset that represented the patch, and |
belaran@999 | 16297 creates a new changeset to represent the modified |
belaran@999 | 16298 patch.</para> |
belaran@999 | 16299 |
belaran@999 | 16300 <para id="x_61d">The <command role="hg-ext-mq" moreinfo="none">qrefresh</command> command |
belaran@999 | 16301 looks for the following modifications:</para> |
belaran@999 | 16302 <itemizedlist> |
belaran@999 | 16303 <listitem><para id="x_61e">Changes to the commit message, i.e. the text |
belaran@999 | 16304 before the first diff header in the patch file, are |
belaran@999 | 16305 reflected in the new changeset that represents the |
belaran@999 | 16306 patch.</para> |
belaran@999 | 16307 </listitem> |
belaran@999 | 16308 <listitem><para id="x_61f">Modifications to tracked files in the working |
belaran@999 | 16309 directory are added to the patch.</para> |
belaran@999 | 16310 </listitem> |
belaran@999 | 16311 <listitem><para id="x_620">Changes to the files tracked using <command role="hg-cmd" moreinfo="none">hg add</command>, <command role="hg-cmd" moreinfo="none">hg copy</command>, <command role="hg-cmd" moreinfo="none">hg remove</command>, or <command role="hg-cmd" moreinfo="none">hg rename</command>. Added files and copy |
belaran@999 | 16312 and rename destinations are added to the patch, while |
belaran@999 | 16313 removed files and rename sources are removed.</para> |
belaran@999 | 16314 </listitem></itemizedlist> |
belaran@999 | 16315 |
belaran@999 | 16316 <para id="x_621">Even if <command role="hg-ext-mq" moreinfo="none">qrefresh</command> |
belaran@999 | 16317 detects no changes, it still recreates the changeset that |
belaran@999 | 16318 represents the patch. This causes the identity of the |
belaran@999 | 16319 changeset to differ from the previous changeset that |
belaran@999 | 16320 identified the patch.</para> |
belaran@999 | 16321 |
belaran@999 | 16322 <para id="x_622">Options:</para> |
belaran@999 | 16323 <itemizedlist> |
belaran@999 | 16324 <listitem><para id="x_623"><option role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify |
belaran@999 | 16325 the commit and patch description, using the preferred text |
belaran@999 | 16326 editor.</para> |
belaran@999 | 16327 </listitem> |
belaran@999 | 16328 <listitem><para id="x_624"><option role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify |
belaran@999 | 16329 the commit message and patch description, using the given |
belaran@999 | 16330 text.</para> |
belaran@999 | 16331 </listitem> |
belaran@999 | 16332 <listitem><para id="x_625"><option role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify |
belaran@999 | 16333 the commit message and patch description, using text from |
belaran@999 | 16334 the given file.</para> |
belaran@999 | 16335 </listitem></itemizedlist> |
belaran@999 | 16336 |
belaran@999 | 16337 </sect2> |
belaran@999 | 16338 <sect2> |
belaran@999 | 16339 <title><command role="hg-ext-mq" moreinfo="none">qrename</command>—rename |
belaran@999 | 16340 a patch</title> |
belaran@999 | 16341 |
belaran@999 | 16342 <para id="x_626">The <command role="hg-ext-mq" moreinfo="none">qrename</command> command |
belaran@999 | 16343 renames a patch, and changes the entry for the patch in the |
belaran@999 | 16344 <filename role="special" moreinfo="none">series</filename> file.</para> |
belaran@999 | 16345 |
belaran@999 | 16346 <para id="x_627">With a single argument, <command role="hg-ext-mq" moreinfo="none">qrename</command> renames the topmost |
belaran@999 | 16347 applied patch. With two arguments, it renames its first |
belaran@999 | 16348 argument to its second.</para> |
belaran@999 | 16349 |
belaran@999 | 16350 </sect2> |
belaran@999 | 16351 <sect2> |
belaran@999 | 16352 <title><command role="hg-ext-mq" moreinfo="none">qseries</command>—print |
belaran@999 | 16353 the entire patch series</title> |
belaran@999 | 16354 |
belaran@999 | 16355 <para id="x_62a">The <command role="hg-ext-mq" moreinfo="none">qseries</command> command |
belaran@999 | 16356 prints the entire patch series from the <filename role="special" moreinfo="none">series</filename> file. It prints only patch |
belaran@999 | 16357 names, not empty lines or comments. It prints in order from |
belaran@999 | 16358 first to be applied to last.</para> |
belaran@999 | 16359 |
belaran@999 | 16360 </sect2> |
belaran@999 | 16361 <sect2> |
belaran@999 | 16362 <title><command role="hg-ext-mq" moreinfo="none">qtop</command>—print the |
belaran@999 | 16363 name of the current patch</title> |
belaran@999 | 16364 |
belaran@999 | 16365 <para id="x_62b">The <command role="hg-ext-mq" moreinfo="none">qtop</command> prints the |
belaran@999 | 16366 name of the topmost currently applied patch.</para> |
belaran@999 | 16367 |
belaran@999 | 16368 </sect2> |
belaran@999 | 16369 <sect2> |
belaran@999 | 16370 <title><command role="hg-ext-mq" moreinfo="none">qunapplied</command>—print patches |
belaran@999 | 16371 not yet applied</title> |
belaran@999 | 16372 |
belaran@999 | 16373 <para id="x_62c">The <command role="hg-ext-mq" moreinfo="none">qunapplied</command> command |
belaran@999 | 16374 prints the names of patches from the <filename role="special" moreinfo="none">series</filename> file that are not yet |
belaran@999 | 16375 applied. It prints them in order from the next patch that |
belaran@999 | 16376 will be pushed to the last.</para> |
belaran@999 | 16377 |
belaran@999 | 16378 </sect2> |
belaran@999 | 16379 <sect2> |
belaran@999 | 16380 <title><command role="hg-cmd" moreinfo="none">hg strip</command>—remove a |
belaran@999 | 16381 revision and descendants</title> |
belaran@999 | 16382 |
belaran@999 | 16383 <para id="x_62d">The <command role="hg-cmd" moreinfo="none">hg strip</command> command |
belaran@999 | 16384 removes a revision, and all of its descendants, from the |
belaran@999 | 16385 repository. It undoes the effects of the removed revisions |
belaran@999 | 16386 from the repository, and updates the working directory to the |
belaran@999 | 16387 first parent of the removed revision.</para> |
belaran@999 | 16388 |
belaran@999 | 16389 <para id="x_62e">The <command role="hg-cmd" moreinfo="none">hg strip</command> command |
belaran@999 | 16390 saves a backup of the removed changesets in a bundle, so that |
belaran@999 | 16391 they can be reapplied if removed in error.</para> |
belaran@999 | 16392 |
belaran@999 | 16393 <para id="x_62f">Options:</para> |
belaran@999 | 16394 <itemizedlist> |
belaran@999 | 16395 <listitem><para id="x_630"><option role="hg-opt-strip">-b</option>: Save |
belaran@999 | 16396 unrelated changesets that are intermixed with the stripped |
belaran@999 | 16397 changesets in the backup bundle.</para> |
belaran@999 | 16398 </listitem> |
belaran@999 | 16399 <listitem><para id="x_631"><option role="hg-opt-strip">-f</option>: If a |
belaran@999 | 16400 branch has multiple heads, remove all heads.</para> |
belaran@999 | 16401 </listitem> |
belaran@999 | 16402 <listitem><para id="x_632"><option role="hg-opt-strip">-n</option>: Do |
belaran@999 | 16403 not save a backup bundle.</para> |
belaran@999 | 16404 </listitem></itemizedlist> |
belaran@999 | 16405 |
belaran@999 | 16406 </sect2> |
belaran@999 | 16407 </sect1> |
belaran@999 | 16408 <sect1> |
belaran@999 | 16409 <title>MQ file reference</title> |
belaran@999 | 16410 |
belaran@999 | 16411 <sect2> |
belaran@999 | 16412 <title>The <filename role="special" moreinfo="none">series</filename> |
belaran@999 | 16413 file</title> |
belaran@999 | 16414 |
belaran@999 | 16415 <para id="x_633">The <filename role="special" moreinfo="none">series</filename> file |
belaran@999 | 16416 contains a list of the names of all patches that MQ can apply. |
belaran@999 | 16417 It is represented as a list of names, with one name saved per |
belaran@999 | 16418 line. Leading and trailing white space in each line are |
belaran@999 | 16419 ignored.</para> |
belaran@999 | 16420 |
belaran@999 | 16421 <para id="x_634">Lines may contain comments. A comment begins with the |
belaran@999 | 16422 <quote><literal moreinfo="none">#</literal></quote> character, and extends to |
belaran@999 | 16423 the end of the line. Empty lines, and lines that contain only |
belaran@999 | 16424 comments, are ignored.</para> |
belaran@999 | 16425 |
belaran@999 | 16426 <para id="x_635">You will often need to edit the <filename role="special" moreinfo="none">series</filename> file by hand, hence the |
belaran@999 | 16427 support for comments and empty lines noted above. For |
belaran@999 | 16428 example, you can comment out a patch temporarily, and <command role="hg-ext-mq" moreinfo="none">qpush</command> will skip over that patch |
belaran@999 | 16429 when applying patches. You can also change the order in which |
belaran@999 | 16430 patches are applied by reordering their entries in the |
belaran@999 | 16431 <filename role="special" moreinfo="none">series</filename> file.</para> |
belaran@999 | 16432 |
belaran@999 | 16433 <para id="x_636">Placing the <filename role="special" moreinfo="none">series</filename> |
belaran@999 | 16434 file under revision control is also supported; it is a good |
belaran@999 | 16435 idea to place all of the patches that it refers to under |
belaran@999 | 16436 revision control, as well. If you create a patch directory |
belaran@999 | 16437 using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> |
belaran@999 | 16438 option to <command role="hg-ext-mq" moreinfo="none">qinit</command>, this will |
belaran@999 | 16439 be done for you automatically.</para> |
belaran@999 | 16440 |
belaran@999 | 16441 </sect2> |
belaran@999 | 16442 <sect2> |
belaran@999 | 16443 <title>The <filename role="special" moreinfo="none">status</filename> |
belaran@999 | 16444 file</title> |
belaran@999 | 16445 |
belaran@999 | 16446 <para id="x_637">The <filename role="special" moreinfo="none">status</filename> file |
belaran@999 | 16447 contains the names and changeset hashes of all patches that MQ |
belaran@999 | 16448 currently has applied. Unlike the <filename role="special" moreinfo="none">series</filename> file, this file is not |
belaran@999 | 16449 intended for editing. You should not place this file under |
belaran@999 | 16450 revision control, or modify it in any way. It is used by MQ |
belaran@999 | 16451 strictly for internal book-keeping.</para> |
belaran@999 | 16452 |
belaran@999 | 16453 </sect2> |
belaran@999 | 16454 </sect1> |
belaran@999 | 16455 </appendix> |
belaran@999 | 16456 |
belaran@999 | 16457 <!-- |
belaran@999 | 16458 local variables: |
belaran@999 | 16459 sgml-parent-document: ("00book.xml" "book" "appendix") |
belaran@999 | 16460 end: |
belaran@999 | 16461 --> |
belaran@999 | 16462 |
belaran@999 | 16463 <!-- BEGIN appC --> |
belaran@999 | 16464 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 16465 |
belaran@999 | 16466 <appendix id="chap:srcinstall"> |
belaran@999 | 16467 <?dbhtml filename="installing-mercurial-from-source.html"?> |
belaran@999 | 16468 <title>Installer Mercurial à partir des sources</title> |
belaran@999 | 16469 |
belaran@999 | 16470 <sect1 id="sec:srcinstall:unixlike"> |
belaran@999 | 16471 <title>Pour un système Unix ou similaire</title> |
belaran@999 | 16472 |
belaran@999 | 16473 <para id="x_5e0">Si vous utilisez un système Unix ou similaire, pour lequel |
belaran@999 | 16474 une version récente de Python (2.3 ou plus) est disponible, l'installation |
belaran@999 | 16475 de Mercurial à partir des sources est simple.</para> |
belaran@999 | 16476 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 16477 <listitem><para id="x_5e1">Téléchargez un paquet récent depuis <ulink url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para> |
belaran@999 | 16478 </listitem> |
belaran@999 | 16479 <listitem><para id="x_5e2">Extrayez le paquet : </para> |
belaran@999 | 16480 <programlisting format="linespecific">gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting> |
belaran@999 | 16481 </listitem> |
belaran@999 | 16482 <listitem><para id="x_5e3">Allez dans le répertoires où les sources ont |
belaran@999 | 16483 été extraites et exécutez le script d'installation. Ce dernier compilera |
belaran@999 | 16484 Mercurial et l'installera dans votre répertoire utilisateur.</para> |
belaran@999 | 16485 <programlisting format="linespecific">cd mercurial-MYVERSION |
belaran@999 | 16486 python setup.py install --force --home=$HOME</programlisting> |
belaran@999 | 16487 </listitem> |
belaran@999 | 16488 </orderedlist> |
belaran@999 | 16489 <para id="x_5e4">Lorsque l'installation est terminée, Mercurial se |
belaran@999 | 16490 trouvera dans le répertoire <literal moreinfo="none">bin</literal> de votre répertoire |
belaran@999 | 16491 utilisateur. |
belaran@999 | 16492 N'oubliez pas de vérifier que ce répertoire se trouve dans la liste |
belaran@999 | 16493 des répertoires où votre shell recherche les exécutables.</para> |
belaran@999 | 16494 |
belaran@999 | 16495 <para id="x_5e5">Vous devrez vraisemblablement définir la variable |
belaran@999 | 16496 d'environnement <envar>PYTHONPATH</envar> de manière à ce que |
belaran@999 | 16497 l'exécutable de Mercurial puisse trouver le reste des paquets logiciels. |
belaran@999 | 16498 Par exemple, sur mon ordinateur portable, je dois le définir ainsi: |
belaran@999 | 16499 <literal moreinfo="none">/home/bos/lib/python</literal>. Le chemin exact à utiliser |
belaran@999 | 16500 dépendra de la manière dont Python aura été construit pour votre |
belaran@999 | 16501 système. Il ne devrait pas être difficile de le trouver. En cas de |
belaran@999 | 16502 doute, lisez le texte généré lors de l'installation ci-dessus, et |
belaran@999 | 16503 recherchez l'emplacement où le contenu du répertoire |
belaran@999 | 16504 <literal moreinfo="none">mercurial</literal> a été installé.</para> |
belaran@999 | 16505 |
belaran@999 | 16506 </sect1> |
belaran@999 | 16507 <sect1> |
belaran@999 | 16508 <title>Pour Windows</title> |
belaran@999 | 16509 |
belaran@999 | 16510 <para id="x_5e6">Construire et installer Mercurial sous Windows nécessite |
belaran@999 | 16511 des outils logiciels divers, une certaine connaissance technique et une |
belaran@999 | 16512 bonne dose de patience. Je vous <emphasis>déconseille fortement</emphasis> |
belaran@999 | 16513 de tenter de le faire si vous êtes un <quote>simple utilisateur</quote>. |
belaran@999 | 16514 A moins que vous n'ayez l'intention de "hacker" Mercurial, je vous |
belaran@999 | 16515 suggère d'avoir recours à un paquet d'installation de la version binaire.</para> |
belaran@999 | 16516 |
belaran@999 | 16517 <para id="x_5e7">Si vous avez vraiment l'intention de construire |
belaran@999 | 16518 Mercurial à partir des sources sous Windows, suivez les indications pour |
belaran@999 | 16519 ce <quote>chemin laborieux</quote> sur le wiki de Mercurial : <ulink url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>, |
belaran@999 | 16520 et préparez vous à un travail épineux.</para> |
belaran@999 | 16521 |
belaran@999 | 16522 </sect1> |
belaran@999 | 16523 </appendix> |
belaran@999 | 16524 |
belaran@999 | 16525 <!-- |
belaran@999 | 16526 local variables: |
belaran@999 | 16527 sgml-parent-document: ("00book.xml" "book" "appendix") |
belaran@999 | 16528 end: |
belaran@999 | 16529 --> |
belaran@999 | 16530 |
belaran@999 | 16531 <!-- BEGIN appD --> |
belaran@999 | 16532 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> |
belaran@999 | 16533 |
belaran@999 | 16534 <appendix id="cha:opl"> |
belaran@999 | 16535 <?dbhtml filename="open-publication-license.html"?> |
belaran@999 | 16536 <title>Open Publication License</title> |
belaran@999 | 16537 |
belaran@999 | 16538 <para id="x_638">Version 1.0, 8 June 1999</para> |
belaran@999 | 16539 |
belaran@999 | 16540 <sect1> |
belaran@999 | 16541 <title>Requirements on both unmodified and modified |
belaran@999 | 16542 versions</title> |
belaran@999 | 16543 |
belaran@999 | 16544 <para id="x_639">The Open Publication works may be reproduced and distributed |
belaran@999 | 16545 in whole or in part, in any medium physical or electronic, |
belaran@999 | 16546 provided that the terms of this license are adhered to, and that |
belaran@999 | 16547 this license or an incorporation of it by reference (with any |
belaran@999 | 16548 options elected by the author(s) and/or publisher) is displayed |
belaran@999 | 16549 in the reproduction.</para> |
belaran@999 | 16550 |
belaran@999 | 16551 <para id="x_63a">Proper form for an incorporation by reference is as |
belaran@999 | 16552 follows:</para> |
belaran@999 | 16553 |
belaran@999 | 16554 <blockquote> |
belaran@999 | 16555 <para id="x_63b"> Copyright (c) <emphasis>year</emphasis> by |
belaran@999 | 16556 <emphasis>author's name or designee</emphasis>. This material |
belaran@999 | 16557 may be distributed only subject to the terms and conditions |
belaran@999 | 16558 set forth in the Open Publication License, |
belaran@999 | 16559 v<emphasis>x.y</emphasis> or later (the latest version is |
belaran@999 | 16560 presently available at <ulink url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para> |
belaran@999 | 16561 </blockquote> |
belaran@999 | 16562 |
belaran@999 | 16563 <para id="x_63c">The reference must be immediately followed with any options |
belaran@999 | 16564 elected by the author(s) and/or publisher of the document (see |
belaran@999 | 16565 <xref linkend="sec:opl:options"/>).</para> |
belaran@999 | 16566 |
belaran@999 | 16567 <para id="x_63d">Commercial redistribution of Open Publication-licensed |
belaran@999 | 16568 material is permitted.</para> |
belaran@999 | 16569 |
belaran@999 | 16570 <para id="x_63e">Any publication in standard (paper) book form shall require |
belaran@999 | 16571 the citation of the original publisher and author. The publisher |
belaran@999 | 16572 and author's names shall appear on all outer surfaces of the |
belaran@999 | 16573 book. On all outer surfaces of the book the original publisher's |
belaran@999 | 16574 name shall be as large as the title of the work and cited as |
belaran@999 | 16575 possessive with respect to the title.</para> |
belaran@999 | 16576 |
belaran@999 | 16577 </sect1> |
belaran@999 | 16578 <sect1> |
belaran@999 | 16579 <title>Copyright</title> |
belaran@999 | 16580 |
belaran@999 | 16581 <para id="x_63f">The copyright to each Open Publication is owned by its |
belaran@999 | 16582 author(s) or designee.</para> |
belaran@999 | 16583 |
belaran@999 | 16584 </sect1> |
belaran@999 | 16585 <sect1> |
belaran@999 | 16586 <title>Scope of license</title> |
belaran@999 | 16587 |
belaran@999 | 16588 <para id="x_640">The following license terms apply to all Open Publication |
belaran@999 | 16589 works, unless otherwise explicitly stated in the |
belaran@999 | 16590 document.</para> |
belaran@999 | 16591 |
belaran@999 | 16592 <para id="x_641">Mere aggregation of Open Publication works or a portion of |
belaran@999 | 16593 an Open Publication work with other works or programs on the |
belaran@999 | 16594 same media shall not cause this license to apply to those other |
belaran@999 | 16595 works. The aggregate work shall contain a notice specifying the |
belaran@999 | 16596 inclusion of the Open Publication material and appropriate |
belaran@999 | 16597 copyright notice.</para> |
belaran@999 | 16598 |
belaran@999 | 16599 <para id="x_642"><emphasis role="bold">Severability</emphasis>. If any part |
belaran@999 | 16600 of this license is found to be unenforceable in any |
belaran@999 | 16601 jurisdiction, the remaining portions of the license remain in |
belaran@999 | 16602 force.</para> |
belaran@999 | 16603 |
belaran@999 | 16604 <para id="x_643"><emphasis role="bold">No warranty</emphasis>. Open |
belaran@999 | 16605 Publication works are licensed and provided <quote>as is</quote> |
belaran@999 | 16606 without warranty of any kind, express or implied, including, but |
belaran@999 | 16607 not limited to, the implied warranties of merchantability and |
belaran@999 | 16608 fitness for a particular purpose or a warranty of |
belaran@999 | 16609 non-infringement.</para> |
belaran@999 | 16610 |
belaran@999 | 16611 </sect1> |
belaran@999 | 16612 <sect1> |
belaran@999 | 16613 <title>Requirements on modified works</title> |
belaran@999 | 16614 |
belaran@999 | 16615 <para id="x_644">All modified versions of documents covered by this license, |
belaran@999 | 16616 including translations, anthologies, compilations and partial |
belaran@999 | 16617 documents, must meet the following requirements:</para> |
belaran@999 | 16618 |
belaran@999 | 16619 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 16620 <listitem><para id="x_645">The modified version must be labeled as |
belaran@999 | 16621 such.</para> |
belaran@999 | 16622 </listitem> |
belaran@999 | 16623 <listitem><para id="x_646">The person making the modifications must be |
belaran@999 | 16624 identified and the modifications dated.</para> |
belaran@999 | 16625 </listitem> |
belaran@999 | 16626 <listitem><para id="x_647">Acknowledgement of the original author and |
belaran@999 | 16627 publisher if applicable must be retained according to normal |
belaran@999 | 16628 academic citation practices.</para> |
belaran@999 | 16629 </listitem> |
belaran@999 | 16630 <listitem><para id="x_648">The location of the original unmodified document |
belaran@999 | 16631 must be identified.</para> |
belaran@999 | 16632 </listitem> |
belaran@999 | 16633 <listitem><para id="x_649">The original author's (or authors') name(s) may |
belaran@999 | 16634 not be used to assert or imply endorsement of the resulting |
belaran@999 | 16635 document without the original author's (or authors') |
belaran@999 | 16636 permission.</para> |
belaran@999 | 16637 </listitem></orderedlist> |
belaran@999 | 16638 |
belaran@999 | 16639 </sect1> |
belaran@999 | 16640 <sect1> |
belaran@999 | 16641 <title>Good-practice recommendations</title> |
belaran@999 | 16642 |
belaran@999 | 16643 <para id="x_64a">In addition to the requirements of this license, it is |
belaran@999 | 16644 requested from and strongly recommended of redistributors |
belaran@999 | 16645 that:</para> |
belaran@999 | 16646 |
belaran@999 | 16647 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 16648 <listitem><para id="x_64b">If you are distributing Open Publication works |
belaran@999 | 16649 on hardcopy or CD-ROM, you provide email notification to the |
belaran@999 | 16650 authors of your intent to redistribute at least thirty days |
belaran@999 | 16651 before your manuscript or media freeze, to give the authors |
belaran@999 | 16652 time to provide updated documents. This notification should |
belaran@999 | 16653 describe modifications, if any, made to the document.</para> |
belaran@999 | 16654 </listitem> |
belaran@999 | 16655 <listitem><para id="x_64c">All substantive modifications (including |
belaran@999 | 16656 deletions) be either clearly marked up in the document or |
belaran@999 | 16657 else described in an attachment to the document.</para> |
belaran@999 | 16658 </listitem> |
belaran@999 | 16659 <listitem><para id="x_64d">Finally, while it is not mandatory under this |
belaran@999 | 16660 license, it is considered good form to offer a free copy of |
belaran@999 | 16661 any hardcopy and CD-ROM expression of an Open |
belaran@999 | 16662 Publication-licensed work to its author(s).</para> |
belaran@999 | 16663 </listitem></orderedlist> |
belaran@999 | 16664 |
belaran@999 | 16665 </sect1> |
belaran@999 | 16666 <sect1 id="sec:opl:options"> |
belaran@999 | 16667 <title>License options</title> |
belaran@999 | 16668 |
belaran@999 | 16669 <para id="x_64e">The author(s) and/or publisher of an Open |
belaran@999 | 16670 Publication-licensed document may elect certain options by |
belaran@999 | 16671 appending language to the reference to or copy of the license. |
belaran@999 | 16672 These options are considered part of the license instance and |
belaran@999 | 16673 must be included with the license (or its incorporation by |
belaran@999 | 16674 reference) in derived works.</para> |
belaran@999 | 16675 |
belaran@999 | 16676 <orderedlist inheritnum="ignore" continuation="restarts"> |
belaran@999 | 16677 <listitem><para id="x_64f">To prohibit distribution of substantively |
belaran@999 | 16678 modified versions without the explicit permission of the |
belaran@999 | 16679 author(s). <quote>Substantive modification</quote> is |
belaran@999 | 16680 defined as a change to the semantic content of the document, |
belaran@999 | 16681 and excludes mere changes in format or typographical |
belaran@999 | 16682 corrections.</para> |
belaran@999 | 16683 </listitem> |
belaran@999 | 16684 <listitem><para id="x_650"> To accomplish this, add the phrase |
belaran@999 | 16685 <quote>Distribution of substantively modified versions of |
belaran@999 | 16686 this document is prohibited without the explicit |
belaran@999 | 16687 permission of the copyright holder.</quote> to the license |
belaran@999 | 16688 reference or copy.</para> |
belaran@999 | 16689 </listitem> |
belaran@999 | 16690 <listitem><para id="x_651">To prohibit any publication of this work or |
belaran@999 | 16691 derivative works in whole or in part in standard (paper) |
belaran@999 | 16692 book form for commercial purposes is prohibited unless prior |
belaran@999 | 16693 permission is obtained from the copyright holder.</para> |
belaran@999 | 16694 </listitem> |
belaran@999 | 16695 <listitem><para id="x_652">To accomplish this, add the phrase |
belaran@999 | 16696 <quote>Distribution of the work or derivative of the work in |
belaran@999 | 16697 any standard (paper) book form is prohibited unless prior |
belaran@999 | 16698 permission is obtained from the copyright holder.</quote> |
belaran@999 | 16699 to the license reference or copy.</para> |
belaran@999 | 16700 </listitem></orderedlist> |
belaran@999 | 16701 |
belaran@999 | 16702 </sect1> |
belaran@999 | 16703 </appendix> |
belaran@999 | 16704 |
belaran@999 | 16705 <!-- |
belaran@999 | 16706 local variables: |
belaran@999 | 16707 sgml-parent-document: ("00book.xml" "book" "appendix") |
belaran@999 | 16708 end: |
belaran@999 | 16709 --> |
belaran@999 | 16710 |
belaran@999 | 16711 </book> |