cvs2svn FAQ

How-to:

  1. How can I convert my CVS repository one module at a time?
  2. How can I convert part of a CVS repository?
  3. How can I convert separate projects in my CVS repository into a single Subversion repository?
  4. How can I convert project foo so that trunk/tags/branches are inside of foo?

Problems:

  1. I get an error "A CVS repository cannot contain both repo/path/file.txt,v and repo/path/Attic/file.txt,v". What can I do?
  2. Using cvs2svn 1.3.x, I get an error "The command '['co', '-q', '-x,v', '-p1.1', '-kk', '/home/cvsroot/myfile,v']' failed" in pass 8.

How-to:

How can I convert my CVS repository one module at a time?

If you need to convert certain CVS modules (in one large repository) to Subversion now and other modules later, you may want to convert your repository one module at a time. This situation is typically encountered in large organizations where each project has a separate lifecycle and schedule, and a one-step conversion process is not practical.

First you have to decide whether you want to put your converted projects into a single Subversion repositories or multiple ones. This decision mostly depends on the degree of coupling between the projects and is beyond the scope of this FAQ. See the Subversion book for a discussion of repository organization.

If you decide to convert your projects into separate Subversion repositories, then please follow the instructions in How can I convert part of a CVS repository? once for each repository.

If you decide to put more than one CVS project into a single Subversion repository, then please follow the instructions in How can I convert separate projects in my CVS repository into a single Subversion repository?.

How can I convert part of a CVS repository?

This is easy: simply run cvs2svn normally, passing it the path of the project subdirectory within the CVS repository. Since cvs2svn ignores any files outside of the path it is given, other projects within the CVS repository will be excluded from the conversion.

Example: You have a CVS repository at path /path/cvsrepo with projects in subdirectories /path/cvsrepo/foo and /path/cvsrepo/bar, and you want to create a new Subversion repository at /path/foo-svn that includes only the foo project:

    $ cvs2svn -s /path/foo-svn /path/cvsrepo/foo

How can I convert separate projects in my CVS repository into a single Subversion repository?

To convert multiple projects from a single CVS repository into a single Subversion repository, then you have to use cvs2svn once for each project, storing the output into a "dumpfile". Then you use svnadmin to load each dumpfile, one after the other, into a project directory created within the Subversion repository.

NOTE: importing projects one at a time into a single Subversion repository will likely break date-based range commands (e.g. svn diff -r {2002-02-17:2002-03-18}) since Subversion does a binary search through the repository to look for dates. While this is not the end of the world, it can be a minor inconvenience.

Example:

  1. If the svn repository doesn't already exist, create it:
          svnadmin create /path/to/svnrepos
        
  2. Remember to Make a backup before starting. Never run cvs2svn on a live CVS repository--always work on a copy of your repository.
  3. Run cvs2svn against one of the modules you want converted:
          # Copy the CVS modules into a temporary cvs repository.
          # This is not absolutely necessary, but it's for safety's sake.
          $ mkdir ~/newcvsrepo
          $ mkdir ~/newcvsrepo/CVSROOT # needed by cvs2svn --use-cvs
          $ cp -r /oldcvsrepo/projectA ~/newcvsrepo
    
          # Create a dumpfile containing the new CVS repository contents
          $ mkdir ~/svndump; cd ~/svndump
          $ cvs2svn --dump-only ~/newcvsrepo/projectA
        
  4. Import the dump into the Subversion repository:
          # Make a directory for the project.
          $ svn mkdir file:///path/to/svnrepos/projectA -m "Added projectA directory."
    
          # Use "svnadmin load" to load the dumpfile.
          $ cd ~/svndump
          $ svnadmin --parent-dir projectA load /path/to/svnrepos < cvs2svn-dump
        
  5. Repeat steps 3 and 4 for each module you want to convert.

How can I convert project foo so that trunk/tags/branches are inside of foo?

Given a CVS repository with the layout:

  /project_a
  /project_b

cvs2svn will produce a Subversion repository with the following layout:

   trunk/
      project_a/
         ...
      project_b/
         ...
   tags/
      ...
   branches/
      ...

However, you may want your Subversion repository to be laid out like this:

   project_a/
      trunk/
         ...
      branches/
         ...
      tags/
         ...
   project_b/
      trunk/
         ...
      branches/
         ...
      tags/
         ...

Currently, cvs2svn does not support converting a repository in this manner (see Issue #86 for details), however, there is a workaround. You can convert your repository one project (or module) at a time and load the individual dumpfiles into your Subversion repository using svnadmin with the --parent-dir switch. See the answer to How can I convert my CVS repository one module at a time? for details.


Problems:

I get an error "A CVS repository cannot contain both repo/path/file.txt,v and repo/path/Attic/file.txt,v". What can I do?

Background: Normally, if you have a file called path/file.txt in your project, CVS stores its history in a file called repo/path/file.txt,v. But if file.txt is deleted on the main line of development, CVS moves its history file to a special Attic subdirectory: repo/path/Attic/file.txt,v. (If the file is recreated, then it is moved back out of the Attic subdirectory.) Your repository should never contain both of these files at the same time.

This cvs2svn error message thus indicates a mild form of corruption in your CVS repository. The file has two conflicting histories, and even CVS does not know the correct history of path/file.txt. The corruption was probably created by using tools other than CVS to backup or manipulate the files in your repository. With a little work you can learn more about the two histories by viewing each of the file.txt,v files in a text editor.

There are four straightforward approaches to fixing the repository corruption, but each has potential disadvantages. Remember to make a backup before starting. Never run cvs2svn on a live CVS repository--always work on a copy of your repository.

  1. Remove the Attic version of the file and restart the conversion. Sometimes it represents an old version of the file that was deleted long ago, and it won't be missed. But this completely discards one of the file's histories, probably causing file.txt to be missing in older historical revisions. (For what it's worth, this is probably how CVS would behave in this situation.)
          # You did make a backup, right?
          $ rm repo/path/Attic/file.txt,v
        
  2. Remove the non-Attic version of the file and restart the conversion. This might be appropriate if the non-Attic version has less important content than the Attic version. But this completely discards one of the file's histories, probably causing file.txt to be missing in recent historical revisions.
          # You did make a backup, right?
          $ rm repo/path/file.txt,v
        
  3. Rename the Attic version of the file and restart the conversion. This avoids losing history, but it changes the name of the Attic version of the file to file-from-Attic.txt whenever it appeared, and might thereby cause revisions to be broken.
          # You did make a backup, right?
          $ mv repo/path/Attic/file.txt,v repo/path/Attic/file-from-Attic.txt,v
        
  4. Rename the non-Attic version of the file and restart the conversion. This avoids losing history, but it changes the name of the non-Attic version of the file to file-not-from-Attic.txt whenever it appeared, and might thereby cause revisions to be broken.
          # You did make a backup, right?
          $ mv repo/path/file.txt,v repo/path/file-not-from-Attic.txt,v
        

If you run cvs2svn on a case-insensitive operating system, it is possible to get this error even if the filename of the file in Attic has different case than the one out of the Attic. This could happen, for example, if the CVS repository was served from a case-sensitive operating system at some time. A workaround for this problem is to copy the CVS repository to a case-sensitive operating system and convert it there.

Using cvs2svn 1.3.x, I get an error "The command '['co', '-q', '-x,v', '-p1.1', '-kk', '/home/cvsroot/myfile,v']' failed" in pass 8.

By default, cvs2svn uses the "co" program from RCS to read the contents of files in your archive. (See the requirements section of the documentation.) The solution to this problem is either to install RCS, or to ensure that CVS is installed and use cvs2svn's --use-cvs option.