Mercurial > hgbook
comparison en/appA-svn.xml @ 814:e9154b3daa94
Repurpose appendix A.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Sun, 26 Apr 2009 23:16:56 -0700 |
parents | en/appA-cmdref.xml@b338f5490029 |
children | 0ffae4ee4c47 |
comparison
equal
deleted
inserted
replaced
812:6b7818eb3d8e | 814:e9154b3daa94 |
---|---|
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> | |
2 | |
3 <appendix id="svn"> | |
4 <?dbhtml filename="mercurial-for-subversion-users.html"?> | |
5 <title>Migrating to Mercurial</title> | |
6 | |
7 <para>A common way to test the waters with a new revision control | |
8 tool is to experiment with switching an existing project, rather | |
9 than starting a new project from scratch.</para> | |
10 | |
11 <para>In this appendix, we discuss how to import a project's history | |
12 into Mercurial, and what to look out for if you are used to a | |
13 different revision control system.</para> | |
14 | |
15 <sect1> | |
16 <title>Importing history from another system</title> | |
17 | |
18 <para>Mercurial ships with an extension named | |
19 <literal>convert</literal>, which can import project history | |
20 from most popular revision control systems. At the time this | |
21 book was written, it could import history from the following | |
22 systems:</para> | |
23 <itemizedlist> | |
24 <listitem> | |
25 <para>Subversion</para> | |
26 </listitem> | |
27 <listitem> | |
28 <para>CVS</para> | |
29 </listitem> | |
30 <listitem> | |
31 <para>git</para> | |
32 </listitem> | |
33 <listitem> | |
34 <para>Darcs</para> | |
35 </listitem> | |
36 <listitem> | |
37 <para>Bazaar</para> | |
38 </listitem> | |
39 <listitem> | |
40 <para>Monotone</para> | |
41 </listitem> | |
42 <listitem> | |
43 <para>GNU Arch</para> | |
44 </listitem> | |
45 <listitem> | |
46 <para>Mercurial</para> | |
47 </listitem> | |
48 </itemizedlist> | |
49 | |
50 <para>(To see why Mercurial itself is supported as a source, see | |
51 <xref linkend="svn.filemap"/>.)</para> | |
52 | |
53 <para>You can enable the extension in the usual way, by editing | |
54 your <filename>~/.hgrc</filename> file.</para> | |
55 | |
56 <programlisting>[extensions] | |
57 convert =</programlisting> | |
58 | |
59 <para>This will make a <command>hg convert</command> command | |
60 available. The command is easy to use. For instance, this | |
61 command will import the Subversion history for the Nose unit | |
62 testing framework into Mercurial.</para> | |
63 | |
64 <screen><prompt>$</prompt> <userinput>hg convert http://python-nose.googlecode.com/svn/trunk</userinput></screen> | |
65 | |
66 <para>The <literal>convert</literal> extension operates | |
67 incrementally. In other words, after you have run <command>hg | |
68 convert</command> once, running it again will import any new | |
69 revisions committed after the first run began. Incremental | |
70 conversion will only work if you run <command>hg | |
71 convert</command> in the same Mercurial repository that you | |
72 originally used, because the <literal>convert</literal> | |
73 extension saves some private metadata in a | |
74 non-revision-controlled file named | |
75 <filename>.hg/shamap</filename> inside the target | |
76 repository.</para> | |
77 | |
78 <sect2> | |
79 <title>Mapping user names</title> | |
80 | |
81 <para>Some revision control tools save only short usernames with | |
82 commits, and these can be difficult to interpret. The norm | |
83 with Mercurial is to save a committer's name and email | |
84 address, which is much more useful for talking to them after | |
85 the fact.</para> | |
86 | |
87 <para>If you are converting a tree from a revision control | |
88 system that uses short names, you can map those names to | |
89 longer equivalents by passing a <option>--authors</option> | |
90 option to <command>hg convert</command>. This option accepts | |
91 a file name that should contain entries of the following | |
92 form.</para> | |
93 | |
94 <programlisting>arist = Aristotle <aristotle@phil.example.gr> | |
95 soc = Socrates <socrates@phil.example.gr></programlisting> | |
96 | |
97 <para>Whenever <literal>convert</literal> encounters a commit | |
98 with the username <literal>arist</literal> in the source | |
99 repository, it will use the name <literal>Aristotle | |
100 <aristotle@phil.example.gr></literal> in the converted | |
101 Mercurial revision. If no match is found for a name, it is | |
102 used verbatim.</para> | |
103 </sect2> | |
104 | |
105 <sect2 id="svn.filemap"> | |
106 <title>Tidying up the tree</title> | |
107 | |
108 <para>Not all projects have pristine history. There may be a | |
109 directory that should never have been checked in, a file that | |
110 is too big, or a whole hierarchy that needs to be | |
111 refactored.</para> | |
112 | |
113 <para>The <literal>convert</literal> extension supports the idea | |
114 of a <quote>file map</quote> that can reorganize the files and | |
115 directories in a project as it imports the project's history. | |
116 This is useful not only when importing history from other | |
117 revision control systems, but also to prune or refactor a | |
118 Mercurial tree.</para> | |
119 | |
120 <para>To specify a file map, use the <option>--filemap</option> | |
121 option and supply a file name. A file map contains lines of the | |
122 following forms.</para> | |
123 | |
124 <programlisting># This is a comment. | |
125 # Empty lines are ignored. | |
126 | |
127 include path/to/file | |
128 | |
129 exclude path/to/file | |
130 | |
131 rename from/some/path to/some/other/place | |
132 </programlisting> | |
133 | |
134 <para>The <literal>include</literal> directive causes a file, or | |
135 all files under a directory, to be included in the destination | |
136 repository. This also excludes all other files and dirs not | |
137 explicitely included. The <literal>exclude</literal> | |
138 directive causes files or directories to be omitted, and | |
139 others not explicitly mentioned to be included.</para> | |
140 | |
141 <para>To move a file or directory from one location to another, | |
142 use the <literal>rename</literal> directive. If you need to | |
143 move a file or directory from a subdirectory into the root of | |
144 the repository, use <literal>.</literal> as the second | |
145 argument to the <literal>rename</literal> directive.</para> | |
146 </sect2> | |
147 </sect1> | |
148 | |
149 <sect1> | |
150 <title>Migrating from Subversion</title> | |
151 | |
152 <para>Subversion is currently the most popular open source | |
153 revision control system. Although there are many differences | |
154 between Mercurial and Subversion, making the transition from | |
155 Subversion to Mercurial is not particularly difficult. The two | |
156 have similar command sets and generally uniform | |
157 interfaces.</para> | |
158 | |
159 <sect2> | |
160 <title>Philosophical differences</title> | |
161 | |
162 <para>The fundamental difference between Subversion and | |
163 Mercurial is of course that Subversion is centralized, while | |
164 Mercurial is distributed. Since Mercurial stores all of a | |
165 project's history on your local drive, it only needs to | |
166 perform a network access when you want to explicitly | |
167 communicate with another repository. In contrast, Subversion | |
168 stores very little information locally, and the client must | |
169 thus contact its server for many common operations.</para> | |
170 | |
171 <para>Subversion more or less gets away without a well-defined | |
172 notion of a branch: which portion of a server's namespace | |
173 qualifies as a branch is a matter of convention, with the | |
174 software providing no enforcement. Mercurial treats a | |
175 repository as the unit of branch management.</para> | |
176 | |
177 <sect3> | |
178 <title>Scope of commands</title> | |
179 | |
180 <para>Since Subversion doesn't know what parts of its | |
181 namespace are really branches, it treats most commands as | |
182 requests to operate at and below whatever directory you are | |
183 currently visiting. For instance, if you run <command>svn | |
184 log</command>, you'll get the history of whatever part of | |
185 the tree you're looking at, not the tree as a whole.</para> | |
186 | |
187 <para>Mercurial's commands behave differently, by defaulting | |
188 to operating over an entire repository. Run <command>hg | |
189 log</command> and it will tell you the history of the | |
190 entire tree, no matter what part of the working directory | |
191 you're visiting at the time. If you want the history of | |
192 just a particular file or directory, simply supply it by | |
193 name, e.g. <command>hg log src</command>.</para> | |
194 | |
195 <para>From my own experience, this difference in default | |
196 behaviors is probably the most likely to trip you up if you | |
197 have to switch back and forth frequently between the two | |
198 tools.</para> | |
199 </sect3> | |
200 | |
201 <sect3> | |
202 <title>Multi-user operation and safety</title> | |
203 | |
204 <para>With Subversion, it is normal (though slightly frowned | |
205 upon) for multiple people to collaborate in a single branch. | |
206 If Alice and Bob are working together, and Alice commits | |
207 some changes to their shared branch, Bob must update his | |
208 client's view of the branch before he can commit. Since at | |
209 this time he has no permanent record of the changes he has | |
210 made, he can corrupt or lose his modifications during and | |
211 after his update.</para> | |
212 | |
213 <para>Mercurial encourages a commit-then-merge model instead. | |
214 Bob commits his changes locally before pulling changes from, | |
215 or pushing them to, the server that he shares with Alice. | |
216 If Alice pushed her changes before Bob tries to push his, he | |
217 will not be able to push his changes until he pulls hers, | |
218 merges with them, and commits the result of the merge. If | |
219 he makes a mistake during the merge, he still has the option | |
220 of reverting to the commit that recorded his changes.</para> | |
221 | |
222 <para>It is worth emphasizing that these are the common ways | |
223 of working with these tools. Subversion supports a safer | |
224 work-in-your-own-branch model, but it is cumbersome enough | |
225 in practice to not be widely used. Mercurial can support | |
226 the less safe mode of allowing changes to be pulled in and | |
227 merged on top of uncommitted edits, but this is considered | |
228 highly unusual.</para> | |
229 </sect3> | |
230 | |
231 <sect3> | |
232 <title>Published vs local changes</title> | |
233 | |
234 <para>A Subversion <command>svn commit</command> command | |
235 immediately publishes changes to a server, where they can be | |
236 seen by everyone who has read access.</para> | |
237 | |
238 <para>With Mercurial, commits are always local, and must be | |
239 published via a <command>hg push</command> command | |
240 afterwards.</para> | |
241 | |
242 <para>Each approach has its advantages and disadvantages. The | |
243 Subversion model means that changes are published, and hence | |
244 reviewable and usable, immediately. On the other hand, this | |
245 means that a user must have commit access to a repository in | |
246 order to use the software in a normal way, and commit access | |
247 is not lightly given out by most open source | |
248 projects.</para> | |
249 | |
250 <para>The Mercurial approach allows anyone who can clone a | |
251 repository to commit changes without the need for someone | |
252 else's permission, and they can then publish their changes | |
253 and continue to participate however they see fit. The | |
254 distinction between committing and pushing does open up the | |
255 possibility of someone committing changes to their laptop | |
256 and walking away for a few days having forgotten to push | |
257 them, which in rare cases might leave collaborators | |
258 temporarily stuck.</para> | |
259 </sect3> | |
260 </sect2> | |
261 | |
262 <sect2> | |
263 <title>Quick reference</title> | |
264 | |
265 <table> | |
266 <title>Subversion commands and Mercurial equivalents</title> | |
267 <tgroup cols="3"> | |
268 <thead> | |
269 <row> | |
270 <entry>Subversion</entry> | |
271 <entry>Mercurial</entry> | |
272 <entry>Notes</entry> | |
273 </row> | |
274 </thead> | |
275 <tbody> | |
276 <row> | |
277 <entry><command>svn add</command></entry> | |
278 <entry><command>hg add</command></entry> | |
279 <entry></entry> | |
280 </row> | |
281 <row> | |
282 <entry><command>svn blame</command></entry> | |
283 <entry><command>hg annotate</command></entry> | |
284 <entry></entry> | |
285 </row> | |
286 <row> | |
287 <entry><command>svn cat</command></entry> | |
288 <entry><command>hg cat</command></entry> | |
289 <entry></entry> | |
290 </row> | |
291 <row> | |
292 <entry><command>svn checkout</command></entry> | |
293 <entry><command>hg clone</command></entry> | |
294 <entry></entry> | |
295 </row> | |
296 <row> | |
297 <entry><command>svn cleanup</command></entry> | |
298 <entry>n/a</entry> | |
299 <entry>No cleanup needed</entry> | |
300 </row> | |
301 <row> | |
302 <entry><command>svn commit</command></entry> | |
303 <entry><command>hg commit</command>; <command>hg | |
304 push</command></entry> | |
305 <entry><command>hg push</command> publishes after | |
306 commit</entry> | |
307 </row> | |
308 <row> | |
309 <entry><command>svn copy</command></entry> | |
310 <entry><command>hg clone</command></entry> | |
311 <entry>To create a new branch</entry> | |
312 </row> | |
313 <row> | |
314 <entry><command>svn copy</command></entry> | |
315 <entry><command>hg copy</command></entry> | |
316 <entry>To copy files or directories</entry> | |
317 </row> | |
318 <row> | |
319 <entry><command>svn delete</command> (<command>svn | |
320 remove</command>)</entry> | |
321 <entry><command>hg remove</command></entry> | |
322 <entry></entry> | |
323 </row> | |
324 <row> | |
325 <entry><command>svn diff</command></entry> | |
326 <entry><command>hg diff</command></entry> | |
327 <entry></entry> | |
328 </row> | |
329 <row> | |
330 <entry><command>svn export</command></entry> | |
331 <entry><command>hg archive</command></entry> | |
332 <entry></entry> | |
333 </row> | |
334 <row> | |
335 <entry><command>svn help</command></entry> | |
336 <entry><command>hg help</command></entry> | |
337 <entry></entry> | |
338 </row> | |
339 <row> | |
340 <entry><command>svn import</command></entry> | |
341 <entry><command>hg addremove</command>; <command>hg | |
342 commit</command></entry> | |
343 <entry></entry> | |
344 </row> | |
345 <row> | |
346 <entry><command>svn info</command></entry> | |
347 <entry><command>hg parents</command></entry> | |
348 <entry>Shows what revision is checked out</entry> | |
349 </row> | |
350 <row> | |
351 <entry><command>svn info</command></entry> | |
352 <entry><command>hg showconfig | |
353 paths.parent</command></entry> | |
354 <entry>Shows what URL is checked out</entry> | |
355 </row> | |
356 <row> | |
357 <entry><command>svn list</command></entry> | |
358 <entry><command>hg manifest</command></entry> | |
359 <entry></entry> | |
360 </row> | |
361 <row> | |
362 <entry><command>svn log</command></entry> | |
363 <entry><command>hg log</command></entry> | |
364 <entry></entry> | |
365 </row> | |
366 <row> | |
367 <entry><command>svn merge</command></entry> | |
368 <entry><command>hg merge</command></entry> | |
369 <entry></entry> | |
370 </row> | |
371 <row> | |
372 <entry><command>svn mkdir</command></entry> | |
373 <entry>n/a</entry> | |
374 <entry>Mercurial does not track directories</entry> | |
375 </row> | |
376 <row> | |
377 <entry><command>svn move</command> (<command>svn | |
378 rename</command>)</entry> | |
379 <entry><command>hg rename</command></entry> | |
380 <entry></entry> | |
381 </row> | |
382 <row> | |
383 <entry><command>svn resolved</command></entry> | |
384 <entry><command>hg resolve -m</command></entry> | |
385 <entry></entry> | |
386 </row> | |
387 <row> | |
388 <entry><command>svn revert</command></entry> | |
389 <entry><command>hg revert</command></entry> | |
390 <entry></entry> | |
391 </row> | |
392 <row> | |
393 <entry><command>svn status</command></entry> | |
394 <entry><command>hg status</command></entry> | |
395 <entry></entry> | |
396 </row> | |
397 <row> | |
398 <entry><command>svn update</command></entry> | |
399 <entry><command>hg pull -u</command></entry> | |
400 <entry></entry> | |
401 </row> | |
402 </tbody> | |
403 </tgroup> | |
404 </table> | |
405 </sect2> | |
406 </sect1> | |
407 | |
408 <sect1> | |
409 <title>Useful tips for newcomers</title> | |
410 | |
411 <para>Under some revision control systems, printing a diff for a | |
412 single committed revision can be painful. For instance, with | |
413 Subversion, to see what changed in revision 104654, you must | |
414 type <command>svn diff -r104653:104654</command>. Mercurial | |
415 eliminates the need to type the revision ID twice in this common | |
416 case. For a plain diff, <command>hg export 104654</command>. For | |
417 a log message followed by a diff, <command>hg log -r104654 | |
418 -p</command>.</para> | |
419 | |
420 <para>When you run <command>hg status</command> without any | |
421 arguments, it prints the status of the entire tree, with paths | |
422 relative to the root of the repository. This makes it tricky to | |
423 copy a file name from the output of <command>hg status</command> | |
424 into the command line. If you supply a file or directory name | |
425 to <command>hg status</command>, it will print paths relative to | |
426 your current location instead. So to get tree-wide status from | |
427 <command>hg status</command>, with paths that are relative to | |
428 your current directory and not the root of the repository, feed | |
429 the output of <command>hg root</command> into <command>hg | |
430 status</command>. You can easily do this as follows on a | |
431 Unix-like system:</para> | |
432 | |
433 <screen><prompt>$</prompt> <userinput>hg status `hg root`</userinput></screen> | |
434 </sect1> | |
435 </appendix> | |
436 | |
437 <!-- | |
438 local variables: | |
439 sgml-parent-document: ("00book.xml" "book" "appendix") | |
440 end: | |
441 --> |