How to convert a CVS repo to GIT using cvs-fast-export?
Mia Lopez
As another attempt, I'm trying to convert a CVS repository to GIT. cvs-fast-export was recommended. The only problem is, I have no idea how to actually do so. I have it built, but how do I call it? There's tons of flags explained here but that's more confusing than it is helping.
Is there a short explanation somewhere of the actual process of conversion?
The repository is remote, and I normally go in via SSH. I'm not sure if the folder structure of this project is normal. Here's roughly what it looks like:
(on the remote server)/somefolder/cvs/anotherfolder/
Contains: CVSROOT repo-I-want-to-clone-name
repo-I-want-to-clone-name contains an
Attic, and all the source code files with,vafter them. (No CVSROOT)CVSROOT contains an
Attic, cleanlog.sh, cvsignore, checkoutlist, checkoutlist,v, editinfo, editinfo,v, commmitinfo, loginfo, taginfo, etc. (No source-code like files here)
3 Answers
You need to have a local copy of the CVS repository directory (containing all the RCS ,v files with history logs). If you have SSH access, use it to download the files via sftp/rsync/tar. If you only have a pserver URL, you need to use something like cvssuck to generate a local repository. In case the repository is hosted at SourceForge, you can download the whole thing using rsync.
Once you have the RCS files, feed a list of the filenames to cvs-fast-export, and it will output a repository in the intermediate "Git fast-export" format
cd ~/cvsfiles
find . -name '*,v' | cvs-fast-export [some options] > ~/converted.feNote: Make sure to include any Attic directories, as they contain files which existed in old commits but were eventually "deleted".
(Besides that, however, there are no additional metadata files needed – each ,v file is completely self-contained, as it uses the same single-file history format as RCS does. The job of cvs-fast-export is to mingle those individual file histories into multi-file commits somehow.)
You can then make edits to the dump using reposurgeon (e.g. assign authors, squash split commits), and finally import it into Git using:
git init ~/result
cd ~/result
git fast-import < ~/converted.feThe import will generate branches and commits, and will update the working-tree index, but apparently doesn't extract the working-tree files themselves: use git reset --hard or git checkout -f to do that.
(In theory, the same "fast-export" dump can also be imported by various other SCMs such as Mercurial, Plastic, or Bzr.)
9Here is how I converted and verified my CVS repository named repos to using cvs-fast-export on Ubuntu 18.04.
Perform the conversion
First, create a "fast export" file from CVS:
sudo apt install cvs-fast-export
cd repos/ # The CVS repository
find . | cvs-fast-export -kb > ../repos.feImport the fast export file to Git:
cd ..
git init repos.git
cd repos.git
git fast-import < ../repos.fegit fast-import creates a bare Git repo, so check out the working files:
git checkout -fVerify the conversion
Create a CVS working copy with keywords not expanded:
cd .. # Directory in which you started
export CVSROOT=$PWD/repos
mkdir checkout-cvs
cd checkout-cvs
cvs co -kb `(cd ../repos; ls | grep -v CVSROOT)`Recursively prune empty directories, which do not appear in the Git version:
find . -type d | sort -r | xargs rmdirThe above gives an error for every non-empty directory, but that's fine.
Compare the CVS latest version to the Git latest version:
cd ..
diff -r checkout-cvs repos.git Here is an effective tool I just used for a long delayed migration: