Documentation / cvs-migration.txton commit Merge branch 'maint' (2d13b73)
   1git for CVS users
   2=================
   3
   4So you're a CVS user. That's OK, it's a treatable condition.  The job of
   5this document is to put you on the road to recovery, by helping you
   6convert an existing cvs repository to git, and by showing you how to use a
   7git repository in a cvs-like fashion.
   8
   9Some basic familiarity with git is required.  This
  10link:tutorial.html[tutorial introduction to git] should be sufficient.
  11
  12First, note some ways that git differs from CVS:
  13
  14  * Commits are atomic and project-wide, not per-file as in CVS.
  15
  16  * Offline work is supported: you can make multiple commits locally,
  17    then submit them when you're ready.
  18
  19  * Branching is fast and easy.
  20
  21  * Every working tree contains a repository with a full copy of the
  22    project history, and no repository is inherently more important than
  23    any other.  However, you can emulate the CVS model by designating a
  24    single shared repository which people can synchronize with; see below
  25    for details.
  26
  27  * Since every working tree contains a repository, a commit in your
  28    private repository will not publish your changes; it will only create
  29    a revision. You have to "push" your changes to a public repository to
  30    make them visible to others.
  31
  32Importing a CVS archive
  33-----------------------
  34
  35First, install version 2.1 or higher of cvsps from
  36link:http://www.cobite.com/cvsps/[http://www.cobite.com/cvsps/] and make
  37sure it is in your path.  The magic command line is then
  38
  39-------------------------------------------
  40$ git cvsimport -v -d <cvsroot> -C <destination> <module>
  41-------------------------------------------
  42
  43This puts a git archive of the named CVS module in the directory
  44<destination>, which will be created if necessary.  The -v option makes
  45the conversion script very chatty.
  46
  47The import checks out from CVS every revision of every file.  Reportedly
  48cvsimport can average some twenty revisions per second, so for a
  49medium-sized project this should not take more than a couple of minutes.
  50Larger projects or remote repositories may take longer.
  51
  52The main trunk is stored in the git branch named `origin`, and additional
  53CVS branches are stored in git branches with the same names.  The most
  54recent version of the main trunk is also left checked out on the `master`
  55branch, so you can start adding your own changes right away.
  56
  57The import is incremental, so if you call it again next month it will
  58fetch any CVS updates that have been made in the meantime.  For this to
  59work, you must not modify the imported branches; instead, create new
  60branches for your own changes, and merge in the imported branches as
  61necessary.
  62
  63Development Models
  64------------------
  65
  66CVS users are accustomed to giving a group of developers commit access to
  67a common repository.  In the next section we'll explain how to do this
  68with git.  However, the distributed nature of git allows other development
  69models, and you may want to first consider whether one of them might be a
  70better fit for your project.
  71
  72For example, you can choose a single person to maintain the project's
  73primary public repository.  Other developers then clone this repository
  74and each work in their own clone.  When they have a series of changes that
  75they're happy with, they ask the maintainer to pull from the branch
  76containing the changes.  The maintainer reviews their changes and pulls
  77them into the primary repository, which other developers pull from as
  78necessary to stay coordinated.  The Linux kernel and other projects use
  79variants of this model.
  80
  81With a small group, developers may just pull changes from each other's
  82repositories without the need for a central maintainer.
  83
  84Creating a Shared Repository
  85----------------------------
  86
  87Start with an ordinary git working directory containing the project, and
  88remove the checked-out files, keeping just the bare .git directory:
  89
  90------------------------------------------------
  91$ mv project/.git /pub/repo.git
  92$ rm -r project/
  93------------------------------------------------
  94
  95Next, give every team member read/write access to this repository.  One
  96easy way to do this is to give all the team members ssh access to the
  97machine where the repository is hosted.  If you don't want to give them a
  98full shell on the machine, there is a restricted shell which only allows
  99users to do git pushes and pulls; see gitlink:git-shell[1].
 100
 101Put all the committers in the same group, and make the repository
 102writable by that group:
 103
 104------------------------------------------------
 105$ chgrp -R $group repo.git
 106$ find repo.git -mindepth 1 -type d |xargs chmod ug+rwx,g+s
 107$ GIT_DIR=repo.git git repo-config core.sharedrepository true
 108------------------------------------------------
 109
 110Make sure committers have a umask of at most 027, so that the directories
 111they create are writable and searchable by other group members.
 112
 113Performing Development on a Shared Repository
 114---------------------------------------------
 115
 116Suppose a repository is now set up in /pub/repo.git on the host
 117foo.com.  Then as an individual committer you can clone the shared
 118repository:
 119
 120------------------------------------------------
 121$ git clone foo.com:/pub/repo.git/ my-project
 122$ cd my-project
 123------------------------------------------------
 124
 125and hack away.  The equivalent of `cvs update` is
 126
 127------------------------------------------------
 128$ git pull origin
 129------------------------------------------------
 130
 131which merges in any work that others might have done since the clone
 132operation.
 133
 134[NOTE]
 135================================
 136The first `git clone` places the following in the
 137`my-project/.git/remotes/origin` file, and that's why the previous step
 138and the next step both work.
 139------------
 140URL: foo.com:/pub/project.git/ my-project
 141Pull: master:origin
 142------------
 143================================
 144
 145You can update the shared repository with your changes by first commiting
 146your changes, and then using:
 147
 148------------------------------------------------
 149$ git push origin master
 150------------------------------------------------
 151
 152to "push" those commits to the shared repository.  If someone else has
 153updated the repository more recently, `git push`, like `cvs commit`, will
 154complain, in which case you must pull any changes before attempting the
 155push again.
 156
 157In the `git push` command above we specify the name of the remote branch
 158to update (`master`).  If we leave that out, `git push` tries to update
 159any branches in the remote repository that have the same name as a branch
 160in the local repository.  So the last `push` can be done with either of:
 161
 162------------
 163$ git push origin
 164$ git push repo.shared.xz:/pub/scm/project.git/
 165------------
 166
 167as long as the shared repository does not have any branches
 168other than `master`.
 169
 170[NOTE]
 171============
 172Because of this behavior, if the shared repository and the developer's
 173repository both have branches named `origin`, then a push like the above
 174attempts to update the `origin` branch in the shared repository from the
 175developer's `origin` branch.  The results may be unexpected, so it's
 176usually best to remove any branch named `origin` from the shared
 177repository.
 178============
 179
 180Advanced Shared Repository Management
 181-------------------------------------
 182
 183Git allows you to specify scripts called "hooks" to be run at certain
 184points.  You can use these, for example, to send all commits to the shared
 185repository to a mailing list.  See link:hooks.html[Hooks used by git].
 186
 187You can enforce finer grained permissions using update hooks.  See
 188link:howto/update-hook-example.txt[Controlling access to branches using
 189update hooks].
 190
 191CVS annotate
 192------------
 193
 194So, something has gone wrong, and you don't know whom to blame, and
 195you're an ex-CVS user and used to do "cvs annotate" to see who caused
 196the breakage. You're looking for the "git annotate", and it's just
 197claiming not to find such a script. You're annoyed.
 198
 199Yes, that's right.  Core git doesn't do "annotate", although it's
 200technically possible, and there are at least two specialized scripts out
 201there that can be used to get equivalent information (see the git
 202mailing list archives for details). 
 203
 204git has a couple of alternatives, though, that you may find sufficient
 205or even superior depending on your use.  One is called "git-whatchanged"
 206(for obvious reasons) and the other one is called "pickaxe" ("a tool for
 207the software archaeologist"). 
 208
 209The "git-whatchanged" script is a truly trivial script that can give you
 210a good overview of what has changed in a file or a directory (or an
 211arbitrary list of files or directories).  The "pickaxe" support is an
 212additional layer that can be used to further specify exactly what you're
 213looking for, if you already know the specific area that changed.
 214
 215Let's step back a bit and think about the reason why you would
 216want to do "cvs annotate a-file.c" to begin with.
 217
 218You would use "cvs annotate" on a file when you have trouble
 219with a function (or even a single "if" statement in a function)
 220that happens to be defined in the file, which does not do what
 221you want it to do.  And you would want to find out why it was
 222written that way, because you are about to modify it to suit
 223your needs, and at the same time you do not want to break its
 224current callers.  For that, you are trying to find out why the
 225original author did things that way in the original context.
 226
 227Many times, it may be enough to see the commit log messages of
 228commits that touch the file in question, possibly along with the
 229patches themselves, like this:
 230
 231        $ git-whatchanged -p a-file.c
 232
 233This will show log messages and patches for each commit that
 234touches a-file.
 235
 236This, however, may not be very useful when this file has many
 237modifications that are not related to the piece of code you are
 238interested in.  You would see many log messages and patches that
 239do not have anything to do with the piece of code you are
 240interested in.  As an example, assuming that you have this piece
 241of code that you are interested in in the HEAD version:
 242
 243        if (frotz) {
 244                nitfol();
 245        }
 246
 247you would use git-rev-list and git-diff-tree like this:
 248
 249        $ git-rev-list HEAD |
 250          git-diff-tree --stdin -v -p -S'if (frotz) {
 251                nitfol();
 252        }'
 253
 254We have already talked about the "\--stdin" form of git-diff-tree
 255command that reads the list of commits and compares each commit
 256with its parents (otherwise you should go back and read the tutorial).
 257The git-whatchanged command internally runs
 258the equivalent of the above command, and can be used like this:
 259
 260        $ git-whatchanged -p -S'if (frotz) {
 261                nitfol();
 262        }'
 263
 264When the -S option is used, git-diff-tree command outputs
 265differences between two commits only if one tree has the
 266specified string in a file and the corresponding file in the
 267other tree does not.  The above example looks for a commit that
 268has the "if" statement in it in a file, but its parent commit
 269does not have it in the same shape in the corresponding file (or
 270the other way around, where the parent has it and the commit
 271does not), and the differences between them are shown, along
 272with the commit message (thanks to the -v flag).  It does not
 273show anything for commits that do not touch this "if" statement.
 274
 275Also, in the original context, the same statement might have
 276appeared at first in a different file and later the file was
 277renamed to "a-file.c".  CVS annotate would not help you to go
 278back across such a rename, but git would still help you in such
 279a situation.  For that, you can give the -C flag to
 280git-diff-tree, like this:
 281
 282        $ git-whatchanged -p -C -S'if (frotz) {
 283                nitfol();
 284        }'
 285
 286When the -C flag is used, file renames and copies are followed.
 287So if the "if" statement in question happens to be in "a-file.c"
 288in the current HEAD commit, even if the file was originally
 289called "o-file.c" and then renamed in an earlier commit, or if
 290the file was created by copying an existing "o-file.c" in an
 291earlier commit, you will not lose track.  If the "if" statement
 292did not change across such a rename or copy, then the commit that
 293does rename or copy would not show in the output, and if the
 294"if" statement was modified while the file was still called
 295"o-file.c", it would find the commit that changed the statement
 296when it was in "o-file.c".
 297
 298NOTE: The current version of "git-diff-tree -C" is not eager
 299  enough to find copies, and it will miss the fact that a-file.c
 300  was created by copying o-file.c unless o-file.c was somehow
 301  changed in the same commit.
 302
 303You can use the --pickaxe-all flag in addition to the -S flag.
 304This causes the differences from all the files contained in
 305those two commits, not just the differences between the files
 306that contain this changed "if" statement:
 307
 308        $ git-whatchanged -p -C -S'if (frotz) {
 309                nitfol();
 310        }' --pickaxe-all
 311
 312NOTE: This option is called "--pickaxe-all" because -S
 313  option is internally called "pickaxe", a tool for software
 314  archaeologists.