You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
7.7 KiB
193 lines
7.7 KiB
Git for CVS users |
|
================= |
|
|
|
Ok, so you're a CVS user. That's ok, it's a treatable condition, and the |
|
first step to recovery is admitting you have a problem. The fact that |
|
you are reading this file means that you may be well on that path |
|
already. |
|
|
|
The thing about CVS is that it absolutely sucks as a source control |
|
manager, and you'll thus be happy with almost anything else. Git, |
|
however, may be a bit _too_ different (read: "good") for your taste, and |
|
does a lot of things differently. |
|
|
|
One particular suckage of CVS is very hard to work around: CVS is |
|
basically a tool for tracking _file_ history, while git is a tool for |
|
tracking _project_ history. This sometimes causes problems if you are |
|
used to doign very strange things in CVS, in particular if you're doing |
|
things like making branches of just a subset of the project. Git can't |
|
track that, since git never tracks things on the level of an individual |
|
file, only on the whole project level. |
|
|
|
The good news is that most people don't do that, and in fact most sane |
|
people think it's a bug in CVS that makes it tag (and check in changes) |
|
one file at a time. So most projects you'll ever see will use CVS |
|
_as_if_ it was sane. In which case you'll find it very easy indeed to |
|
move over to Git. |
|
|
|
First off: this is not a git tutorial. See Documentation/tutorial.txt |
|
for how git actually works. This is more of a random collection of |
|
gotcha's and notes on converting from CVS to git. |
|
|
|
Second: CVS has the notion of a "repository" as opposed to the thing |
|
that you're actually working in (your working directory, or your |
|
"checked out tree"). Git does not have that notion at all, and all git |
|
working directories _are_ the repositories. However, you can easily |
|
emulate the CVS model by having one special "global repository", which |
|
people can synchronize with. See details later, but in the meantime |
|
just keep in mind that with git, every checked out working tree will be |
|
a full revision control of its own. |
|
|
|
|
|
Importing a CVS archive |
|
----------------------- |
|
|
|
Ok, you have an old project, and you want to at least give git a chance |
|
to see how it performs. The first thing you want to do (after you've |
|
gone through the git tutorial, and generally familiarized yourself with |
|
how to commit stuff etc in git) is to create a git'ified version of your |
|
CVS archive. |
|
|
|
Happily, that's very easy indeed. Git will do it for you, although git |
|
will need the help of a program called "cvsps": |
|
|
|
http://www.cobite.com/cvsps/ |
|
|
|
which is not actually related to git at all, but which makes CVS usage |
|
look almost sane (ie you almost certainly want to have it even if you |
|
decide to stay with CVS). However, git will want at _least_ version 2.1 |
|
of cvsps (available at the address above), and in fact will currently |
|
refuse to work with anything else. |
|
|
|
Once you've gotten (and installed) cvsps, you may or may not want to get |
|
any more familiar with it, but make sure it is in your path. After that, |
|
the magic command line is |
|
|
|
git cvsimport <cvsroot> <module> |
|
|
|
which will do exactly what you'd think it does: it will create a git |
|
archive of the named CVS module. The new archive will be created in a |
|
subdirectory named <module>. |
|
|
|
It can take some time to actually do the conversion for a large archive, |
|
and the conversion script can be reasonably chatty, but on some not very |
|
scientific tests it averaged about eight revisions per second, so a |
|
medium-sized project should not take more than a couple of minutes. |
|
|
|
|
|
Emulating CVS behaviour |
|
----------------------- |
|
|
|
|
|
FIXME! Talk about setting up several repositories, and pulling and |
|
pushing between them. Talk about merging, and branches. Some of this |
|
needs to be in the tutorial too. |
|
|
|
|
|
|
|
CVS annotate |
|
------------ |
|
|
|
The core GIT itself does not have a "cvs annotate" equivalent. |
|
It has something that you may want to use when you would use |
|
"cvs annotate". |
|
|
|
Let's step back a bit and think about the reason why you would |
|
want to do "cvs annotate a-file.c" to begin with. |
|
|
|
You would use "cvs annotate" on a file when you have trouble |
|
with a function (or even a single "if" statement in a function) |
|
that happens to be defined in the file, which does not do what |
|
you want it to do. And you would want to find out why it was |
|
written that way, because you are about to modify it to suit |
|
your needs, and at the same time you do not want to break its |
|
current callers. For that, you are trying to find out why the |
|
original author did things that way in the original context. |
|
|
|
Many times, it may be enough to see the commit log messages of |
|
commits that touch the file in question, possibly along with the |
|
patches themselves, like this: |
|
|
|
$ git-whatchanged -p a-file.c |
|
|
|
This will show log messages and patches for each commit that |
|
touches a-file. |
|
|
|
This, however, may not be very useful when this file has many |
|
modifications that are not related to the piece of code you are |
|
interested in. You would see many log messages and patches that |
|
do not have anything to do with the piece of code you are |
|
interested in. As an example, assuming that you have this piece |
|
code that you are interested in in the HEAD version: |
|
|
|
if (frotz) { |
|
nitfol(); |
|
} |
|
|
|
you would use git-rev-list and git-diff-tree like this: |
|
|
|
$ git-rev-list HEAD | |
|
git-diff-tree --stdin -v -p -S'if (frotz) { |
|
nitfol(); |
|
}' |
|
|
|
We have already talked about the "--stdin" form of git-diff-tree |
|
command that reads the list of commits and compares each commit |
|
with its parents. The git-whatchanged command internally runs |
|
the equivalent of the above command, and can be used like this: |
|
|
|
$ git-whatchanged -p -S'if (frotz) { |
|
nitfol(); |
|
}' |
|
|
|
When the -S option is used, git-diff-tree command outputs |
|
differences between two commits only if one tree has the |
|
specified string in a file and the corresponding file in the |
|
other tree does not. The above example looks for a commit that |
|
has the "if" statement in it in a file, but its parent commit |
|
does not have it in the same shape in the corresponding file (or |
|
the other way around, where the parent has it and the commit |
|
does not), and the differences between them are shown, along |
|
with the commit message (thanks to the -v flag). It does not |
|
show anything for commits that do not touch this "if" statement. |
|
|
|
Also, in the original context, the same statement might have |
|
appeared at first in a different file and later the file was |
|
renamed to "a-file.c". CVS annotate would not help you to go |
|
back across such a rename, but GIT would still help you in such |
|
a situation. For that, you can give the -C flag to |
|
git-diff-tree, like this: |
|
|
|
$ git-whatchanged -p -C -S'if (frotz) { |
|
nitfol(); |
|
}' |
|
|
|
When the -C flag is used, file renames and copies are followed. |
|
So if the "if" statement in question happens to be in "a-file.c" |
|
in the current HEAD commit, even if the file was originally |
|
called "o-file.c" and then renamed in an earlier commit, or if |
|
the file was created by copying an existing "o-file.c" in an |
|
earlier commit, you will not lose track. If the "if" statement |
|
did not change across such rename or copy, then the commit that |
|
does rename or copy would not show in the output, and if the |
|
"if" statement was modified while the file was still called |
|
"o-file.c", it would find the commit that changed the statement |
|
when it was in "o-file.c". |
|
|
|
[ BTW, the current versions of "git-diff-tree -C" is not eager |
|
enough to find copies, and it will miss the fact that a-file.c |
|
was created by copying o-file.c unless o-file.c was somehow |
|
changed in the same commit.] |
|
|
|
You can use the --pickaxe-all flag in addition to the -S flag. |
|
This causes the differences from all the files contained in |
|
those two commits, not just the differences between the files |
|
that contain this changed "if" statement: |
|
|
|
$ git-whatchanged -p -C -S'if (frotz) { |
|
nitfol(); |
|
}' --pickaxe-all |
|
|
|
[ Side note. This option is called "--pickaxe-all" because -S |
|
option is internally called "pickaxe", a tool for software |
|
archaeologists.]
|
|
|