Subject: Re: git cvsimport branches not consistent with CVS branches

From: [email-masked] (Brian Downing)
Date: Sun, 8 Jul 2007 00:45:20 -0500

On Sun, Jul 08, 2007 at 10:45:10AM +1000, Gordon Heydon wrote:
> After some investigation I found that git cvsimport was not importing 
> branches 100% correctly with CVS.
> 
> Git and CVS do branching very differently in that CVS this is done at 
> the file level (like everything else) and git does it repository wide.
> 
> So if I have a CVS repository with the files a, b and c and I branch b 
> with a `cvs tab -b BRANCH test` on the branch test I will just have the 
> file b.
> 
> If I do a git cvsimport on the test branch there will actually be the 
> files a, b and c
> 
> What I think needs to happen is that when git cvsimport created the 
> branch in the git repository it needs to delete all files from the 
> branch that were not branched.

I've been vaguely working on Yet Another CVS Importer (an incremental
one; both git-cvsimport (thanks to cvsps) and tailor take about ten
minutes and a gigabyte of RAM to figure out that nothing has to happen
with my repository.  I think I can do better than that).

In thinking about this case, I think I've decided that you want an
option on what to do here.  For some repositories you're not going to
care about having extra files with the tag, and would greatly prefer
that to having to create a branch for each and every tag (assuming you
can arrange to have the correct files present otherwise; this isn't
always possible.)

For other cases, you really only want to get the subset of the files
that are tagged.  For this, I think the best arrangement would be to
make your branch, then make a commit that only deletes the files that
are not present in the CVS branch, as you said.  Then immediately make
an empty commit to the mainline (wherever you branched from) merging
from the deletion commit.  Then proceed to commit normally to the
branch.  This way, if a user chooses to merge from the branch in Git,
it won't try to delete a bunch of files in the target branch.  (I'm
having a hard time coming up with a situation where you'd want that
behavior assuming the missing files were never tagged in CVS.  A sane
usage pattern would be to tag the whole repository then "cvs rm" the
files you don't want otherwise...)

A fun third case is when a file in CVS doesn't have a branch tag,
but then you go and "cvs add" a file with the same name in a branch.
What CVS does then is to place the branch tag off the current HEAD.
I /think/ you can detect this situation by noticing that the date of
the HEAD revision and the date of the "file was created on branch ..."
revision are exactly the same.  You really need to detect this case,
because when this happens there is no real parent relationship between
the branch and the branch point.  Since CVS has that "wait for a second
to tick" delay at the end this might even be safe.  Sigh.

Don't get me started about the abomination that is vendor branches.

I /hate/ CVS.

-bcd