**We only offer limited read-only support for CVS for projects previously using it on the Classic SourceForge system, with commit access no longer available since November 2017. **
We recommend that projects upgrade to a more modern SCM, like Subversion, rather than using CVS.
CVS has limitations that newer SCM solutions have been designed to overcome.
Backups of a CVS repository may be made using rsync.
Example (replace PROJECTNAME with the UNIX group name of your project):
rsync -av rsync://PROJECTNAME.cvs.sourceforge.net/cvsroot/PROJECTNAME/\* cvs
Some CVS projects may wish to convert to Subversion, aka SVN, since it is most similar to CVS and also has the ability to checkout just a subdirectory of your new repository. Other people may want to choose Git, which is more distributed but has a steeper learning curve (note that each Git repo you create is always checked out in full).
The first step in the conversion is to use the project admin page on sourceforge.net to create an empty repository in the style of your choosing (Subversion, Git, etc.).
Note: if your CVS repo is still visible in your menus, it will be occupying the "code" path (aka "mount point") in all the browse/checkout URLs, so your new repository will need to use a different mount name. You can avoid this issue by first using the "Delete Everything" menu item in the menubar (unlock the menu and use the cog next to CVS). Even though the menu says "Everything", for the legacy CVS data the delete action only deletes the mount point, freeing up the use of the "code" path in the site URLs (it doesn't affect accessing the CVS data in any way). The choice is yours if you want to go ahead and hide CVS on the menu-bar early, or use an alternate name (e.g. "code2") for the conversion. We document how to rename this path later in this document, but it does involve manually copying and deleting your repo to do that.
Start by making a backup copy of your CVS data. See the backup instructions above.
Checkout the new (empty) svn or git repo so that you can populate it and push it back to the server when you’re done
If you choose to use cvs2svn to convert your repository, you have the choice of converting the entire cvs area or (with the use of a config file) converting a single section of the cvs data at a time (to divide things into several new repos). To convert the whole thing, you can run command similar to this:
cvs2svn --tmpdir ~/cvs2svn-tmp --existing-svnrepos --retain-conflicting-attic-files \
--encoding=utf8 --encoding=latin1 --fallback-encoding=ascii \
-s /home/svn/p/PROJECT/code /home/classic/cvs/PROJECT
Run the above command into a non-existing directory without the --existing-svnrepos option (so get rid of that option in the above command and change the /home/svn/... path to a local path on your computer that you want cvs2svn to create). Once the conversion is done, you can contact us for assistance importing into your project.
Run “cvs2svn --help” for a summary of the available options. The web has more detailed documentation: http://www.mcs.anl.gov/~jacob/cvs2svn/cvs2svn.html
For more intricate conversion options, including converting just a part of the CVS repo into the new repo, you’ll need to create a config file. The documentation above covers that and more. Keep in mind that Subversion allows you to checkout just a portion of a repository, so if you convert all of your CVS data into one SVN repo, you will still be able to checkout any subdirectory in the repo that you want -- there will be just one "log" of changes, though, which some projects prefer.
Once the import finishes running, go to the web page for your SVN repo. It may say "The metadata for this repository is missing. To fix, please try a refresh." Click the "Refresh Repository" link in the repo's admin drop-down for it to detect & process all the new commits (look for the blue triangle in the sidebar). If your repository is very large, this may take some time. The repo is usable immediately for svn checkouts & checkins, even while the web view is processing the commits.
Some folks prefer to use cvs2git, and some prefer to use "git cvsimport". I believe that cvs2git does a better job, so we'll discuss that one first. Also note in the following commands that you'll want to change the FIXME to a username to use for synthesized commits, change the PROJECT path to be based on your project name, and the "code.git" dir might be named differently, depending on your git mount point). First get a backup copy of your CVS repo (see above). Then run:
mkdir cvs2git-tmp
cd cvs2git-tmp
cvs2git --blobfile=blob.dat --dumpfile=dump.dat \
--username=FIXME --default-eol=native \
--encoding=utf8 --encoding=latin1 --fallback-encoding=ascii \
/path/to/cvs/backup
git checkout ssh://git.code.sf.net/p/PROJECT/code new_git
cat blob.dat dump.dat | git --git-dir=new_git/.git fast-import
cd new_git
git checkout
git push origin --mirror
cd ..
mv new_git /a/better/path/for/your/new_git
rm blob.dat dump.dat
At that point, you should be able to check out your git using the standard git checkout instructions on the website.
If you need more info, visit the cvs2git documentation page.
A simple way to convert your repo to Git is to use the “git cvsimport” command. For the best conversion result, it helps to create an author.txt mapping file that has the mapping of usernames to the extra user information that Git includes. The file should contain lines that look like this:
username = User Name username@users.sourceforge.net
The following command can provide you with a list of all the author usernames:
for vfile in `find /home/classic/cvs/PROJECT -name '*,v'`; do
rlog $vfile | sed -nr 's/^date:.* author: ([^;]+).*/\1/p'
done | sort -u >~/cvs-author-names
Be sure to verify the resulting list -- you’ll probably want to at least remove “root”. You can then turn that list of names into an authors.txt file like this:
for uname in `cat ~/cvs-author-names`; do
json=`curl https://sourceforge.net/rest/u/$uname/profile`
fname=`echo "$json" | sed -nr 's/\{"username": "[^"]+", "name": "([^"]+)".*/\1/p'`
echo "$uname = $fname <$uname@users.sourceforge.net>"
done >~/authors.txt
Be sure to scan the resulting ~/authors.txt file for missing Full Names and make any other changes you want.
Because the cvsimport command wants to create locks inside the read-only CVS dirs, you’ll need to create a copy of your repo for the conversion. If you’re using our interactive shell service you can do a copy like this (note the trailing slashes):
rsync -aiv /home/classic/cvs/PROJECT/ ~/cvs/
Also, note that the new git dir must not exist yet (you’ll push the result into the project’s “bare” repo later).
So, to do the conversion you can run this:
rm -rf ~/new-git
git cvsimport -v -a -k -d ~/cvs -C ~/new-git -A ~/authors.txt MODULE
The MODULE name is one of your top-level CVS directories. It is very often the same name as the project name.
When that is done you can review the repo’s commits (“git log”), tags (“git tag”), and branches (“git branch -a”) and make any needed tweaks before making it public (e.g. removing unneeded tags and/or branches).
When you’re all set, we need to push the resulting git repo to the shared “origin”. The “new-git” directory contains a working tree, while the directories under /home/git are all “bare” format (without a working tree). To publish the result you can use one of the following “git push” commands.
You can then do a checkout from the home of your git repo (see the normal instructions on your project’s git info page) and verify that all is well.
Don’t forget to remove ~/new-git and ~/cvs dirs once you are done with them.
You’ll want to setup the right origin in your new-git dir and then push (note that you typically omit the trailing “.git” from the “code.git” dir):
git remote add origin ssh://USER@git.code.sf.net/p/PROJECT/code
git config branch.master.remote origin
git config branch.master.merge refs/heads/master
git push origin --mirror
That sets up your new git dir to be associated with the remote git repo, just as if you had done a clone. On subsequent pushes, you won’t need to specify the "origin" or "--mirror" part of the push, since git will know the association between the remote and local branches.
See also: https://git-scm.com/docs/gitcvs-migration
After you push your changes, the web view of the repository may take some time to process the commits if your repo is very large. While it does that, the repo is still usable for git checkouts and commits.
If you did not do so earlier, you should now use the site's admin pages to "Delete" the CVS repository. Note that this deletion just removes the CVS entry in the site's menus (unlike other repository deletion actions), and your access to the CVS data will still be available (read-only) in the future if you need it.