subversion

Migrar un repositorio de subversión a uno de git

Migrar un repositorio de subversión a uno de git

Introducción

En este artículo vamos a explicar como migrar un repositorio de código que tenemos en subversion a un repositorio git conservando el historial de commits que tenga originalmente.

Proceso

Requisitos

Si no tenemos instalado git, lo instalamos:

>> sudo apt-get install git git-svn

Y configuramos un usuario y email (que nos servirá para que los repositorios remotos nos reconozcan):

>> git config --global user.name TU_USUARIO
>> git config --global user.email TU_EMAIL

Instalamos svn2git que es un programa que nos convertirá un repositorio de subversion a uno en formato git.

>> sudo apt-get install rubygems
>> sudo gem install svn2git

Migración

Antes de realizar la migración, tendremos que mapear los usuarios de subversion con los de git. Para ello tendremos que crear un fichero de texto en el que le diremos para cada usuario de subversion el usuario de git al que se le atribuirá sus acciones. El formato de este fichero de texto es el siguiente:

USUARIO_SUBVERSION = USUARIO_GIT <EMAIL_USUARIO_GIT>

Hacemos el fichero con los mapeos que deseemos (por ejemplo en authors.txt).

Una vez tenemos todo lo necesario, procederemos creando un repositorio local vacío y luego importamos el contenido del antiguo repositorio de subversion a través del programa svn2git:

>> git init proyecto.git
>> cd proyecto.git
>> svn2git http://TUDOMINIO/TUPATH/TU_PROYECTO --username TU_USUARIO_EN_SUBVERSION --authors PATH/authors.txt

Una vez tengamos creado el repositorio local de git con nuestro proyecto, si queremos guardarlo en un repositorio online solo tenemos que añadirlo y subirlo.

Por ejemplo: Si queremos subirlo a la rama master de un repositorio online de bitbucket de url https://myuser@bitbucket.org/myuser/myproject.git con el usuario myuser, tendremos que ejecutar los siguiente comandos:

>> git remote add origin https://myuser@bitbucket.org/myuser/myproject.git
>> git push origin master

Problemas

Problema (no author) not defined

Al importar el proyecto de subversión a nuestro repositorio local de git, obtenemos el siguiente error:

>> svn2git http://TUDOMINIO/TUPATH/TUPROYECTO --username intropedro --authors TURUTA/authors.txt
command failed:
2>&1 git svn fetch

Para ver los detalles del error ejecutamos el siguiente comando:

>> git svn fetch
Author: (no author) not defined in TURUTA/authors.txt file

Solución

El problema esta en que hay commits en nuestro repositorio de subvesion que no se hicieron con ningún usuario. Para solucionarlo solo tenemos que añadir la siguiente fila a nuestro archivo de autores:

(no author) = TU_USUARIO_EN_GIT <TU_EMAIL_EN_GIT>
temas: 

Migración de cvs a subversion

Cvs2svn

Introducción

Hace pocos meses que tuve que pasar de usar un servidor de CVS para usar uno de Subversión (este nos proporcionaba más cosas que el primero). En nuestro servidor de cvs tendríamos alrededor de 250 proyectos y la verdad es que me han salido muchos problemas, pero al final se pasó todo. Para la migración estuve mirando por internet y vi que todo el mundo utilizaba un programa llamado cvs2svn. A continuación os explico como hacerlo y la lista de los problemas que me aparecieron y sus soluciones.

Migración

Para importar nuestro repositorio de cvs a subversion (svn) usaremos el programa cvs2svn. Lo tendremos que bajar, descomprimir y ejecutar con los correspondientes parámetros:

>> wget http://cvs2svn.tigris.org/files/documents/1462/44372/cvs2svn-2.2.0.tar.gz
>> gzip -d cvs2svn-2.2.0.tar.gz
>> tar -xvf cvs2svn-2.2.0.tar
>> cd cvs2svn-2.2.0
>> ./cvs2svn --existing-svnrepos --encoding iso8859_15 -s /var/www/html/svn/root ../CVSROOT/miproyecto

Podéis mirar aquí para ver que encodings podemos poner.

Como mi caso, si queréis tener un repositorio multiproyecto tendréis que indicarle a cada proyecto que importéis que las carpetas trunk, branches y tags las meta dentro de una carpeta con el nombre del proyecto. Por ejemplo asi:

>> ./cvs2svn --existing-svnrepos --encoding iso8859_15 --trunk=miproyecto/trunk --branches=miproyecto/branches --tags=miproyecto/tags -s /var/www/html/svn/root ../CVSROOT/miproyecto

Problemas

is not a CVS repository

Al intentar importar una carpeta que contiene un proyecto del cvs nos da el siguiente error:

ERROR: the path '/root/miproyecto' is not a CVS repository, nor a path within a CVS repository. A CVS repository contains a CVSROOT directory within its root directory.

Solucion

Metemos la carpeta del proyecto en una carpeta llamada '''CVSROOT'''. Por ejemplo si nuestro proyecto esta en /root/miproyecto quedaría en /root/'''CVROOT'''/miproyecto.

co: No such file or directory

Al ejecutar el programa cvs2svn con la opción '''--use-rcs''' nos aparece el siguiente error:

ERROR: error executing co: [Errno 2] No such file or directory
Please check that co is installed and in your PATH
(it is a part of the RCS software).

Solución

No tenemos instalado el paquete '''rcs''' que contiene el programa '''co'''. Lo instalamos:

* Para sistemas Debian, Ubuntu, ...

>> sudo aptitude install rcs

* Para sistemas Centos, Redhat, ...

>> sudo yum install rcs

No such file or directory

Al ejecutar la importación de un proyecto del cvs a svn nos aparece el siguiente mensaje de error:

Exception occurred while parsing /projects/cvsroot/miproyecto/prueba/Attic/text.html,v
Traceback (most recent call last):
File "/cvs2svn-2.2.0/cvs2svn", line 31, in ?
main(sys.argv[0], sys.argv[1:])
File "/cvs2svn-2.2.0/cvs2svn_lib/main.py", line 88, in main
pass_manager.run(run_options)
File "/cvs2svn-2.2.0/cvs2svn_lib/pass_manager.py", line 181, in run
the_pass.run(run_options, stats_keeper)
File "/cvs2svn-2.2.0/cvs2svn_lib/passes.py", line 152, in run
cd.process_project(project)
File "/cvs2svn-2.2.0/cvs2svn_lib/collect_data.py", line 1329, in process_project
pdc.process_file(cvs_file)
File "/cvs2svn-2.2.0/cvs2svn_lib/collect_data.py", line 1014, in process_file
cvs2svn_rcsparse.parse(open(cvs_file.filename, 'rb'), fdc)
IOError: [Errno 2] No such file or directory: '/projects/cvsroot/miproyecto/prueba/Attic/text.html,v'

Comprobamos que el fichero existe:

>> ls /projects/cvsroot/miproyecto/prueba/Attic/text.html,v
/projects/cvsroot/miproyecto/prueba/Attic/text.html,v

Solución

Este problema fue muy raro. La carpeta donde almacenaba los proyectos del cvs estaba compartida en otra máquina y la tenia montada donde esta instalado el cvs. Creo que el problema era algo causado por la arquitectura de mi entorno. Al final tuve que copiar la carpeta del proyecto desde el ordenador donde estaba al ordenador donde tenía el servidor de cvs y estaba ejecutando el script de migración. Entonces ejecuté el program

Archivos duplicados, Attic

Al hacer la migración con el programa cvs2svn podemos encontrarnos con un error como este:

'''ERROR''': A CVS repository cannot contain both /repositorio/cvsroot/proyecto/src/file.java,v and /repositorio/cvsroot/proyecto/src/Attic/file.java,v

Solución

Antes de explicar el problema tenemos que saber que las carpetas Attic las usa cvs para guardar ficheros que han sido borrados en nuestro proyecto, para poder recuperarlos en caso necesario. Normalmente si tienes un fichero llamado path/file.txt en tu proyecto, CVS almacena su historia en un fichero llamado repo/path/file.txt,v. Pero si el fichero file.txt es borrado en la rama principal de desarrollo, CVS mueve el fichero de la historia a una subcarpeta especial llamada Attic: repo/path/Attic/file.txt,v. (Si el fichero se vuelve a crear, entonces este es movido fuera del directorio Attic donde estaba ántes.) El repositorio nunca debería contener ambos ficheros al mismo tiempo.

Este mensaje de error indica una leve corrupción en tu repositorio CVS. El archivo que da el problema tiene dos historias en conflicto, e incluso el CVS no sabe cual es la historia correcta. La corrupción probablemente fue creada al usar otras herramientas a parte del CVS para hacer copias de seguridad o manipular los archivos en tu repositorio. Con un poco de trabajo puedes ver las dos historias abriendo los dos ficheros en un editor de texto y así saber cual es el correcto.

Hay 4 maneras de corregir este problema, pero cada una tiene sus desventajas. Recuerda hacer una copia de seguridad antes de empezar. Nunca ejecutes el programa cvs2svn con un repositorio cvs en funcionamiento, trabaja siempre con una copia.

  • Vuelve ha hacer la migración con la opción --retain-conflicting-attic-files.  Esto hace que la verión Attic y no Attic de el fichero sea convertida separadamente almacenando la version Attic en un subdirectorio path/Attic/file.txt. Esto evita la perdida de cualquier historia, pero al moverlo a otro directorio proboca que el historio de revisiones se rompa.
  • Borra la versión Attic del fichero e  intentar otra vez la migración del proyecto. En algunas ocasiones esto representará una vieja versión del fichero que fue borrada hace tiempo. Pero estaremos descartando la historia de uno de los ficheros, probablemente esto causará la perdida de la historia antigua del fichero. Acuerdate de hacer una copia de seguridad del fichero antes de borrarlo.
>> rm /repositorio/cvsroot/proyecto/src/Attic/file.java,v
  • Borrar la versión de fichero no Attic e intentar otra vez la migración del proyecto. Esto puede ser apropiado si el fichero no Attic tiene menos contenido importante que la version Attic. Pero esto descarta una de las dos historias y probablemente causará la perdida de los cambios más recientes del fichero. Antes de borrarlo aseguraos de hacer una copia de seguridad del fichero que borréis.
>> rm /repositorio/cvsroot/proyecto/src/file.java,v
  • Renombrar la versión no Attic de el fichero e intentar otra vez la migración del proyecto. Esto nos evita perder historia, pero cambia el nombre del fichero no Attic.
>> mv /repositorio/cvsroot/proyecto/src/file.java,v /repositorio/cvsroot/proyecto/src/file-not-from-Attic.java,v