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>
|