Autogenerated HTML docs for v1.3.2-g8c24
[git.git] / cvs-migration.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
2     "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
3 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
4 <head>\r
5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
6 <meta name="generator" content="AsciiDoc 7.0.1" />\r
7 <style type="text/css">\r
8 /* Debug borders */\r
9 p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {\r
10 /*\r
11   border: 1px solid red;\r
12 */\r
13 }\r
14 \r
15 body {\r
16   margin: 1em 5% 1em 5%;\r
17 }\r
18 \r
19 a { color: blue; }\r
20 a:visited { color: fuchsia; }\r
21 \r
22 em {\r
23   font-style: italic;\r
24 }\r
25 \r
26 strong {\r
27   font-weight: bold;\r
28 }\r
29 \r
30 tt {\r
31   color: navy;\r
32 }\r
33 \r
34 h1, h2, h3, h4, h5, h6 {\r
35   color: #527bbd;\r
36   font-family: sans-serif;\r
37   margin-top: 1.2em;\r
38   margin-bottom: 0.5em;\r
39   line-height: 1.3;\r
40 }\r
41 \r
42 h1 {\r
43   border-bottom: 2px solid silver;\r
44 }\r
45 h2 {\r
46   border-bottom: 2px solid silver;\r
47   padding-top: 0.5em;\r
48 }\r
49 \r
50 div.sectionbody {\r
51   font-family: serif;\r
52   margin-left: 0;\r
53 }\r
54 \r
55 hr {\r
56   border: 1px solid silver;\r
57 }\r
58 \r
59 p {\r
60   margin-top: 0.5em;\r
61   margin-bottom: 0.5em;\r
62 }\r
63 \r
64 pre {\r
65   padding: 0;\r
66   margin: 0;\r
67 }\r
68 \r
69 span#author {\r
70   color: #527bbd;\r
71   font-family: sans-serif;\r
72   font-weight: bold;\r
73   font-size: 1.2em;\r
74 }\r
75 span#email {\r
76 }\r
77 span#revision {\r
78   font-family: sans-serif;\r
79 }\r
80 \r
81 div#footer {\r
82   font-family: sans-serif;\r
83   font-size: small;\r
84   border-top: 2px solid silver;\r
85   padding-top: 0.5em;\r
86   margin-top: 4.0em;\r
87 }\r
88 div#footer-text {\r
89   float: left;\r
90   padding-bottom: 0.5em;\r
91 }\r
92 div#footer-badges {\r
93   float: right;\r
94   padding-bottom: 0.5em;\r
95 }\r
96 \r
97 div#preamble,\r
98 div.tableblock, div.imageblock, div.exampleblock, div.verseblock,\r
99 div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
100 div.admonitionblock {\r
101   margin-right: 10%;\r
102   margin-top: 1.5em;\r
103   margin-bottom: 1.5em;\r
104 }\r
105 div.admonitionblock {\r
106   margin-top: 2.5em;\r
107   margin-bottom: 2.5em;\r
108 }\r
109 \r
110 div.content { /* Block element content. */\r
111   padding: 0;\r
112 }\r
113 \r
114 /* Block element titles. */\r
115 div.title, caption.title {\r
116   font-family: sans-serif;\r
117   font-weight: bold;\r
118   text-align: left;\r
119   margin-top: 1.0em;\r
120   margin-bottom: 0.5em;\r
121 }\r
122 div.title + * {\r
123   margin-top: 0;\r
124 }\r
125 \r
126 td div.title:first-child {\r
127   margin-top: 0.0em;\r
128 }\r
129 div.content div.title:first-child {\r
130   margin-top: 0.0em;\r
131 }\r
132 div.content + div.title {\r
133   margin-top: 0.0em;\r
134 }\r
135 \r
136 div.sidebarblock > div.content {\r
137   background: #ffffee;\r
138   border: 1px solid silver;\r
139   padding: 0.5em;\r
140 }\r
141 \r
142 div.listingblock > div.content {\r
143   border: 1px solid silver;\r
144   background: #f4f4f4;\r
145   padding: 0.5em;\r
146 }\r
147 \r
148 div.quoteblock > div.content {\r
149   padding-left: 2.0em;\r
150 }\r
151 div.quoteblock .attribution {\r
152   text-align: right;\r
153 }\r
154 \r
155 div.admonitionblock .icon {\r
156   vertical-align: top;\r
157   font-size: 1.1em;\r
158   font-weight: bold;\r
159   text-decoration: underline;\r
160   color: #527bbd;\r
161   padding-right: 0.5em;\r
162 }\r
163 div.admonitionblock td.content {\r
164   padding-left: 0.5em;\r
165   border-left: 2px solid silver;\r
166 }\r
167 \r
168 div.exampleblock > div.content {\r
169   border-left: 2px solid silver;\r
170   padding: 0.5em;\r
171 }\r
172 \r
173 div.verseblock div.content {\r
174   white-space: pre;\r
175 }\r
176 \r
177 div.imageblock div.content { padding-left: 0; }\r
178 div.imageblock img { border: 1px solid silver; }\r
179 span.image img { border-style: none; }\r
180 \r
181 dl {\r
182   margin-top: 0.8em;\r
183   margin-bottom: 0.8em;\r
184 }\r
185 dt {\r
186   margin-top: 0.5em;\r
187   margin-bottom: 0;\r
188   font-style: italic;\r
189 }\r
190 dd > *:first-child {\r
191   margin-top: 0;\r
192 }\r
193 \r
194 ul, ol {\r
195     list-style-position: outside;\r
196 }\r
197 ol.olist2 {\r
198   list-style-type: lower-alpha;\r
199 }\r
200 \r
201 div.tableblock > table {\r
202   border-color: #527bbd;\r
203   border-width: 3px;\r
204 }\r
205 thead {\r
206   font-family: sans-serif;\r
207   font-weight: bold;\r
208 }\r
209 tfoot {\r
210   font-weight: bold;\r
211 }\r
212 \r
213 div.hlist {\r
214   margin-top: 0.8em;\r
215   margin-bottom: 0.8em;\r
216 }\r
217 td.hlist1 {\r
218   vertical-align: top;\r
219   font-style: italic;\r
220   padding-right: 0.8em;\r
221 }\r
222 td.hlist2 {\r
223   vertical-align: top;\r
224 }\r
225 \r
226 @media print {\r
227   div#footer-badges { display: none; }\r
228 }\r
229 /* Workarounds for IE6's broken and incomplete CSS2. */\r
230 \r
231 div.sidebar-content {\r
232   background: #ffffee;\r
233   border: 1px solid silver;\r
234   padding: 0.5em;\r
235 }\r
236 div.sidebar-title, div.image-title {\r
237   font-family: sans-serif;\r
238   font-weight: bold;\r
239   margin-top: 0.0em;\r
240   margin-bottom: 0.5em;\r
241 }\r
242 \r
243 div.listingblock div.content {\r
244   border: 1px solid silver;\r
245   background: #f4f4f4;\r
246   padding: 0.5em;\r
247 }\r
248 \r
249 div.quoteblock-content {\r
250   padding-left: 2.0em;\r
251 }\r
252 \r
253 div.exampleblock-content {\r
254   border-left: 2px solid silver;\r
255   padding-left: 0.5em;\r
256 }\r
257 </style>\r
258 <title>git for CVS users</title>\r
259 </head>\r
260 <body>\r
261 <div id="header">\r
262 <h1>git for CVS users</h1>\r
263 </div>\r
264 <div id="preamble">\r
265 <div class="sectionbody">\r
266 <p>So you're a CVS user. That's ok, it's a treatable condition.  The job of\r
267 this document is to put you on the road to recovery, by helping you\r
268 convert an existing cvs repository to git, and by showing you how to use a\r
269 git repository in a cvs-like fashion.</p>\r
270 <p>Some basic familiarity with git is required.  This\r
271 <a href="tutorial.html">tutorial introduction to git</a> should be sufficient.</p>\r
272 <p>First, note some ways that git differs from CVS:</p>\r
273 <ul>\r
274 <li>\r
275 <p>\r
276 Commits are atomic and project-wide, not per-file as in CVS.\r
277 </p>\r
278 </li>\r
279 <li>\r
280 <p>\r
281 Offline work is supported: you can make multiple commits locally,\r
282     then submit them when you're ready.\r
283 </p>\r
284 </li>\r
285 <li>\r
286 <p>\r
287 Branching is fast and easy.\r
288 </p>\r
289 </li>\r
290 <li>\r
291 <p>\r
292 Every working tree contains a repository with a full copy of the\r
293     project history, and no repository is inherently more important than\r
294     any other.  However, you can emulate the CVS model by designating a\r
295     single shared repository which people can synchronize with; see below\r
296     for details.\r
297 </p>\r
298 </li>\r
299 </ul>\r
300 </div>\r
301 </div>\r
302 <h2>Importing a CVS archive</h2>\r
303 <div class="sectionbody">\r
304 <p>First, install version 2.1 or higher of cvsps from\r
305 <a href="http://www.cobite.com/cvsps/">http://www.cobite.com/cvsps/</a> and make\r
306 sure it is in your path.  The magic command line is then</p>\r
307 <div class="listingblock">\r
308 <div class="content">\r
309 <pre><tt>$ git cvsimport -v -d &lt;cvsroot&gt; -C &lt;destination&gt; &lt;module&gt;</tt></pre>\r
310 </div></div>\r
311 <p>This puts a git archive of the named CVS module in the directory\r
312 &lt;destination&gt;, which will be created if necessary.  The -v option makes\r
313 the conversion script very chatty.</p>\r
314 <p>The import checks out from CVS every revision of every file.  Reportedly\r
315 cvsimport can average some twenty revisions per second, so for a\r
316 medium-sized project this should not take more than a couple of minutes.\r
317 Larger projects or remote repositories may take longer.</p>\r
318 <p>The main trunk is stored in the git branch named <tt>origin</tt>, and additional\r
319 CVS branches are stored in git branches with the same names.  The most\r
320 recent version of the main trunk is also left checked out on the <tt>master</tt>\r
321 branch, so you can start adding your own changes right away.</p>\r
322 <p>The import is incremental, so if you call it again next month it will\r
323 fetch any CVS updates that have been made in the meantime.  For this to\r
324 work, you must not modify the imported branches; instead, create new\r
325 branches for your own changes, and merge in the imported branches as\r
326 necessary.</p>\r
327 </div>\r
328 <h2>Development Models</h2>\r
329 <div class="sectionbody">\r
330 <p>CVS users are accustomed to giving a group of developers commit access to\r
331 a common repository.  In the next section we'll explain how to do this\r
332 with git.  However, the distributed nature of git allows other development\r
333 models, and you may want to first consider whether one of them might be a\r
334 better fit for your project.</p>\r
335 <p>For example, you can choose a single person to maintain the project's\r
336 primary public repository.  Other developers then clone this repository\r
337 and each work in their own clone.  When they have a series of changes that\r
338 they're happy with, they ask the maintainer to pull from the branch\r
339 containing the changes.  The maintainer reviews their changes and pulls\r
340 them into the primary repository, which other developers pull from as\r
341 necessary to stay coordinated.  The Linux kernel and other projects use\r
342 variants of this model.</p>\r
343 <p>With a small group, developers may just pull changes from each other's\r
344 repositories without the need for a central maintainer.</p>\r
345 </div>\r
346 <h2>Emulating the CVS Development Model</h2>\r
347 <div class="sectionbody">\r
348 <p>Start with an ordinary git working directory containing the project, and\r
349 remove the checked-out files, keeping just the bare .git directory:</p>\r
350 <div class="listingblock">\r
351 <div class="content">\r
352 <pre><tt>$ mv project/.git /pub/repo.git\r
353 $ rm -r project/</tt></pre>\r
354 </div></div>\r
355 <p>Next, give every team member read/write access to this repository.  One\r
356 easy way to do this is to give all the team members ssh access to the\r
357 machine where the repository is hosted.  If you don't want to give them a\r
358 full shell on the machine, there is a restricted shell which only allows\r
359 users to do git pushes and pulls; see <a href="git-shell.html">git-shell(1)</a>.</p>\r
360 <p>Put all the committers should in the same group, and make the repository\r
361 writable by that group:</p>\r
362 <div class="listingblock">\r
363 <div class="content">\r
364 <pre><tt>$ chgrp -R $group repo.git\r
365 $ find repo.git -mindepth 1 -type d |xargs chmod ug+rwx,g+s\r
366 $ GIT_DIR=repo.git git repo-config core.sharedrepository true</tt></pre>\r
367 </div></div>\r
368 <p>Make sure committers have a umask of at most 027, so that the directories\r
369 they create are writable and searchable by other group members.</p>\r
370 <p>Suppose this repository is now set up in /pub/repo.git on the host\r
371 foo.com.  Then as an individual commiter you can clone the shared\r
372 repository:</p>\r
373 <div class="listingblock">\r
374 <div class="content">\r
375 <pre><tt>$ git clone foo.com:/pub/repo.git/ my-project\r
376 $ cd my-project</tt></pre>\r
377 </div></div>\r
378 <p>and hack away.  The equivalent of <tt>cvs update</tt> is</p>\r
379 <div class="listingblock">\r
380 <div class="content">\r
381 <pre><tt>$ git pull origin</tt></pre>\r
382 </div></div>\r
383 <p>which merges in any work that others might have done since the clone\r
384 operation.</p>\r
385 <div class="admonitionblock">\r
386 <table><tr>\r
387 <td class="icon">\r
388 <div class="title">Note</div>\r
389 </td>\r
390 <td class="content">\r
391 <p>The first <tt>git clone</tt> places the following in the\r
392 <tt>my-project/.git/remotes/origin</tt> file, and that's why the previous step\r
393 and the next step both work.</p>\r
394 <div class="listingblock">\r
395 <div class="content">\r
396 <pre><tt>URL: foo.com:/pub/project.git/ my-project\r
397 Pull: master:origin</tt></pre>\r
398 </div></div>\r
399 </td>\r
400 </tr></table>\r
401 </div>\r
402 <p>You can update the shared repository with your changes using:</p>\r
403 <div class="listingblock">\r
404 <div class="content">\r
405 <pre><tt>$ git push origin master</tt></pre>\r
406 </div></div>\r
407 <p>If someone else has updated the repository more recently, <tt>git push</tt>, like\r
408 <tt>cvs commit</tt>, will complain, in which case you must pull any changes\r
409 before attempting the push again.</p>\r
410 <p>In the <tt>git push</tt> command above we specify the name of the remote branch\r
411 to update (<tt>master</tt>).  If we leave that out, <tt>git push</tt> tries to update\r
412 any branches in the remote repository that have the same name as a branch\r
413 in the local repository.  So the last <tt>push</tt> can be done with either of:</p>\r
414 <div class="listingblock">\r
415 <div class="content">\r
416 <pre><tt>$ git push origin\r
417 $ git push repo.shared.xz:/pub/scm/project.git/</tt></pre>\r
418 </div></div>\r
419 <p>as long as the shared repository does not have any branches\r
420 other than <tt>master</tt>.</p>\r
421 <div class="admonitionblock">\r
422 <table><tr>\r
423 <td class="icon">\r
424 <div class="title">Note</div>\r
425 </td>\r
426 <td class="content">\r
427 <p>Because of this behaviour, if the shared repository and the developer's\r
428 repository both have branches named <tt>origin</tt>, then a push like the above\r
429 attempts to update the <tt>origin</tt> branch in the shared repository from the\r
430 developer's <tt>origin</tt> branch.  The results may be unexpected, so it's\r
431 usually best to remove any branch named <tt>origin</tt> from the shared\r
432 repository.</p>\r
433 </td>\r
434 </tr></table>\r
435 </div>\r
436 </div>\r
437 <h2>Advanced Shared Repository Management</h2>\r
438 <div class="sectionbody">\r
439 <p>Git allows you to specify scripts called "hooks" to be run at certain\r
440 points.  You can use these, for example, to send all commits to the shared\r
441 repository to a mailing list.  See <a href="hooks.txt">Hooks used by git</a>.</p>\r
442 <p>You can enforce finer grained permissions using update hooks.  See\r
443 <a href="howto/update-hook-example.txt">Controlling access to branches using\r
444 update hooks</a>.</p>\r
445 </div>\r
446 <h2>CVS annotate</h2>\r
447 <div class="sectionbody">\r
448 <p>So, something has gone wrong, and you don't know whom to blame, and\r
449 you're an ex-CVS user and used to do "cvs annotate" to see who caused\r
450 the breakage. You're looking for the "git annotate", and it's just\r
451 claiming not to find such a script. You're annoyed.</p>\r
452 <p>Yes, that's right.  Core git doesn't do "annotate", although it's\r
453 technically possible, and there are at least two specialized scripts out\r
454 there that can be used to get equivalent information (see the git\r
455 mailing list archives for details).</p>\r
456 <p>git has a couple of alternatives, though, that you may find sufficient\r
457 or even superior depending on your use.  One is called "git-whatchanged"\r
458 (for obvious reasons) and the other one is called "pickaxe" ("a tool for\r
459 the software archaeologist").</p>\r
460 <p>The "git-whatchanged" script is a truly trivial script that can give you\r
461 a good overview of what has changed in a file or a directory (or an\r
462 arbitrary list of files or directories).  The "pickaxe" support is an\r
463 additional layer that can be used to further specify exactly what you're\r
464 looking for, if you already know the specific area that changed.</p>\r
465 <p>Let's step back a bit and think about the reason why you would\r
466 want to do "cvs annotate a-file.c" to begin with.</p>\r
467 <p>You would use "cvs annotate" on a file when you have trouble\r
468 with a function (or even a single "if" statement in a function)\r
469 that happens to be defined in the file, which does not do what\r
470 you want it to do.  And you would want to find out why it was\r
471 written that way, because you are about to modify it to suit\r
472 your needs, and at the same time you do not want to break its\r
473 current callers.  For that, you are trying to find out why the\r
474 original author did things that way in the original context.</p>\r
475 <p>Many times, it may be enough to see the commit log messages of\r
476 commits that touch the file in question, possibly along with the\r
477 patches themselves, like this:</p>\r
478 <div class="literalblock">\r
479 <div class="content">\r
480 <pre><tt>$ git-whatchanged -p a-file.c</tt></pre>\r
481 </div></div>\r
482 <p>This will show log messages and patches for each commit that\r
483 touches a-file.</p>\r
484 <p>This, however, may not be very useful when this file has many\r
485 modifications that are not related to the piece of code you are\r
486 interested in.  You would see many log messages and patches that\r
487 do not have anything to do with the piece of code you are\r
488 interested in.  As an example, assuming that you have this piece\r
489 of code that you are interested in in the HEAD version:</p>\r
490 <div class="literalblock">\r
491 <div class="content">\r
492 <pre><tt>if (frotz) {\r
493         nitfol();\r
494 }</tt></pre>\r
495 </div></div>\r
496 <p>you would use git-rev-list and git-diff-tree like this:</p>\r
497 <div class="literalblock">\r
498 <div class="content">\r
499 <pre><tt>$ git-rev-list HEAD |\r
500   git-diff-tree --stdin -v -p -S'if (frotz) {\r
501         nitfol();\r
502 }'</tt></pre>\r
503 </div></div>\r
504 <p>We have already talked about the "--stdin" form of git-diff-tree\r
505 command that reads the list of commits and compares each commit\r
506 with its parents (otherwise you should go back and read the tutorial).\r
507 The git-whatchanged command internally runs\r
508 the equivalent of the above command, and can be used like this:</p>\r
509 <div class="literalblock">\r
510 <div class="content">\r
511 <pre><tt>$ git-whatchanged -p -S'if (frotz) {\r
512         nitfol();\r
513 }'</tt></pre>\r
514 </div></div>\r
515 <p>When the -S option is used, git-diff-tree command outputs\r
516 differences between two commits only if one tree has the\r
517 specified string in a file and the corresponding file in the\r
518 other tree does not.  The above example looks for a commit that\r
519 has the "if" statement in it in a file, but its parent commit\r
520 does not have it in the same shape in the corresponding file (or\r
521 the other way around, where the parent has it and the commit\r
522 does not), and the differences between them are shown, along\r
523 with the commit message (thanks to the -v flag).  It does not\r
524 show anything for commits that do not touch this "if" statement.</p>\r
525 <p>Also, in the original context, the same statement might have\r
526 appeared at first in a different file and later the file was\r
527 renamed to "a-file.c".  CVS annotate would not help you to go\r
528 back across such a rename, but git would still help you in such\r
529 a situation.  For that, you can give the -C flag to\r
530 git-diff-tree, like this:</p>\r
531 <div class="literalblock">\r
532 <div class="content">\r
533 <pre><tt>$ git-whatchanged -p -C -S'if (frotz) {\r
534         nitfol();\r
535 }'</tt></pre>\r
536 </div></div>\r
537 <p>When the -C flag is used, file renames and copies are followed.\r
538 So if the "if" statement in question happens to be in "a-file.c"\r
539 in the current HEAD commit, even if the file was originally\r
540 called "o-file.c" and then renamed in an earlier commit, or if\r
541 the file was created by copying an existing "o-file.c" in an\r
542 earlier commit, you will not lose track.  If the "if" statement\r
543 did not change across such a rename or copy, then the commit that\r
544 does rename or copy would not show in the output, and if the\r
545 "if" statement was modified while the file was still called\r
546 "o-file.c", it would find the commit that changed the statement\r
547 when it was in "o-file.c".</p>\r
548 <div class="admonitionblock">\r
549 <table><tr>\r
550 <td class="icon">\r
551 <div class="title">Note</div>\r
552 </td>\r
553 <td class="content">The current version of "git-diff-tree -C" is not eager\r
554   enough to find copies, and it will miss the fact that a-file.c\r
555   was created by copying o-file.c unless o-file.c was somehow\r
556   changed in the same commit.</td>\r
557 </tr></table>\r
558 </div>\r
559 <p>You can use the &#8212;pickaxe-all flag in addition to the -S flag.\r
560 This causes the differences from all the files contained in\r
561 those two commits, not just the differences between the files\r
562 that contain this changed "if" statement:</p>\r
563 <div class="literalblock">\r
564 <div class="content">\r
565 <pre><tt>$ git-whatchanged -p -C -S'if (frotz) {\r
566         nitfol();\r
567 }' --pickaxe-all</tt></pre>\r
568 </div></div>\r
569 <div class="admonitionblock">\r
570 <table><tr>\r
571 <td class="icon">\r
572 <div class="title">Note</div>\r
573 </td>\r
574 <td class="content">This option is called "&#8212;pickaxe-all" because -S\r
575   option is internally called "pickaxe", a tool for software\r
576   archaeologists.</td>\r
577 </tr></table>\r
578 </div>\r
579 </div>\r
580 <div id="footer">\r
581 <div id="footer-text">\r
582 Last updated 30-Jan-2006 23:10:24 PDT\r
583 </div>\r
584 </div>\r
585 </body>\r
586 </html>\r