¿Cómo exportar el historial de revisiones de mercurial o git a cvs?

100

Voy a trabajar con otras personas en el código de un proyecto que usa cvs. Queremos usar un vcs distribuido para hacer nuestro trabajo y cuando terminemos o tal vez de vez en cuando queremos enviar nuestro código y todo nuestro historial de revisiones a cvs. No tenemos acceso de escritura al repositorio cvs del proyecto, por lo que no podemos confirmar con mucha frecuencia. ¿Qué herramienta podemos utilizar para exportar nuestro historial de revisiones a CVS? Actualmente estábamos pensando en usar git o mercurial, pero podríamos usar otro vcs distribuido si pudiera facilitar la exportación.

tatsuhirosatou
fuente
Cuando dice "CVS distribuido", creo que se refiere a "VCS distribuido" o "DVCS", que significa "sistema de control de versiones distribuido".
Patrick McElhaney
Me refiero a un sistema de control de versiones distribuido.
tatsuhirosatou

Respuestas:

237

Afortunadamente para aquellos de nosotros que todavía estamos obligados a usar CVS, git proporciona herramientas bastante buenas para hacer exactamente lo que desea hacer. Mis sugerencias (y lo que hacemos aquí en $ work):

Creación del clon inicial

Úselo git cvsimportpara clonar el historial de revisiones de CVS en un repositorio de git. Utilizo la siguiente invocación:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout

La -Aopción es opcional pero ayuda a que el historial de revisión que se importa desde CVS se vea más parecido a un git (consulte man git-cvsimportpara obtener más información sobre cómo está configurado).

Dependiendo del tamaño y el historial del repositorio de CVS, esta primera importación tomará MUCHO tiempo. Puede agregar una -v al comando anterior si desea tener la tranquilidad de saber que algo está sucediendo.

Una vez que se complete este proceso, tendrá una masterrama que debería reflejar el HEAD de CVS (con la excepción de que, git cvsimportpor defecto, ignora los últimos 10 minutos de confirmaciones para evitar atrapar una confirmación que está a medio terminar). Luego puede usar git logy amigos para examinar todo el historial del repositorio como si hubiera estado usando git desde el principio.

Ajustes de configuración

Hay algunos ajustes de configuración que facilitarán las importaciones incrementales de CVS (así como las exportaciones) en el futuro. Estos no están documentados en la git cvsimportpágina del manual, así que supongo que podrían cambiar sin previo aviso, pero FWIW:

% git config cvsimport.module cvs_module_to_checkout
% git config cvsimport.r cvs
% git config cvsimport.d $CVSROOT

Todas estas opciones se pueden especificar en la línea de comandos para que pueda omitir este paso con seguridad.

Importaciones incrementales

La siguiente git cvsimportdebería ser mucho más rápida que la primera invocación. Sin embargo, lo hace cvs rlogen todos los directorios (incluso en aquellos que solo tienen archivos Attic), por lo que aún puede tomar unos minutos. Si ha especificado las configuraciones sugeridas arriba, todo lo que necesita hacer es ejecutar:

% git cvsimport

Si no ha configurado sus configuraciones para especificar los valores predeterminados, deberá especificarlos en la línea de comando:

% git cvsimport -r cvs -d $CVSROOT cvs_module_to_checkout

De cualquier manera, dos cosas a tener en cuenta:

  1. Asegúrate de estar en el directorio raíz de tu repositorio de git. Si se encuentra en otro lugar, intentará hacer una nueva versión cvsimportque volverá a tomar una eternidad.
  2. Asegúrese de estar en su masterrama para que los cambios se puedan fusionar (o volver a basar) en sus ramas locales / temáticas.

Haciendo cambios locales

En la práctica, recomiendo siempre hacer cambios en las ramas y fusionarlos mastercuando esté listo para exportar esos cambios al repositorio de CVS. Puede usar cualquier flujo de trabajo que desee en sus ramas (fusión, rebase, aplastamiento, etc.) pero, por supuesto, se aplican las reglas de rebase estándar: no rebase si alguien más ha estado basando sus cambios en su rama.

Exportación de cambios a CVS

El git cvsexportcommitcomando le permite exportar una única confirmación al servidor CVS. Puede especificar un único ID de confirmación (o cualquier cosa que describa una confirmación específica como se define en man git-rev-parse). Luego se genera una diferencia, se aplica a un pago de CVS y luego (opcionalmente) se confirma a CVS usando el cvscliente real . Puede exportar cada micro compromiso en las ramas de su tema, pero generalmente me gusta crear un compromiso de fusión en una actualización mastery exportar ese compromiso de fusión único a CVS. Cuando exporta una confirmación de fusión, debe decirle a git qué padre de confirmación debe usar para generar la diferencia. Además, esto no funcionará si su combinación fue un avance rápido (consulte la sección "CÓMO FUNCIONA LA FUSIÓN" de man git-mergepara obtener una descripción de una combinación de avance rápido), por lo que debe usar el--no-ffopción al realizar la combinación. He aquí un ejemplo:

# on master
% git merge --no-ff --log -m "Optional commit message here" topic/branch/name
% git cvsexportcommit -w /path/to/cvs/checkout -u -p -c ORIG_HEAD HEAD

Puede ver lo que significa cada una de esas opciones en la página de manual de git-cvsexportcommit . Tienes la opción de configurar la -wopción en tu configuración de git:

% git config cvsexportcommit.cvsdir /path/to/cvs/checkout

Si el parche falla por cualquier motivo, mi experiencia es que (desafortunadamente) probablemente será mejor que copie los archivos modificados manualmente y se comprometa con el cliente cvs. Sin embargo, esto no debería suceder si se asegura de que masteresté actualizado con CVS antes de fusionar la rama de su tema.

Si la confirmación falla por cualquier motivo (problemas de red / permisos, etc.), puede llevar el comando impreso a su terminal al final de la salida del error y ejecutarlo en su directorio de trabajo CVS. Por lo general, se parece a esto:

% cvs commit -F .msg file1 file2 file3 etc

La próxima vez que haga un git cvsimport(esperando al menos 10 minutos) debería ver el parche de su confirmación exportada reimportada a su repositorio local. Tendrán diferentes ID de confirmación, ya que la confirmación de CVS tendrá una marca de tiempo diferente y posiblemente un nombre de confirmación diferente (dependiendo de si configuró un archivo de autores en su inicial cvsimportanterior).

Clonando su clon de CVS

Si tiene más de una persona que necesita hacer el cvsimport, sería más eficiente tener un único repositorio de git que realiza cvsimport y tener todos los demás repositorios creados como un clon. Esto funciona perfectamente y el repositorio clonado puede realizar cvsexportcommits tal como se describió anteriormente. Sin embargo, hay una advertencia. Debido a la forma en que las confirmaciones de CVS regresan con diferentes ID de confirmación (como se describe arriba), no desea que su rama clonada rastree el repositorio central de git. De forma predeterminada, así es como git cloneconfigura su repositorio, pero esto se soluciona fácilmente:

% git clone [CENTRAL_REPO_HERE]
% cd [NEW_GIT_REPO_DIR_HERE]
% git config --unset branch.master.remote
% git config --unset branch.master.merge

Una vez que haya eliminado estas configuraciones, tendrá que decir explícitamente dónde y de qué extraer cuando desee extraer nuevas confirmaciones del repositorio central:

% git pull origin master

En general, he encontrado que este flujo de trabajo es bastante manejable y la "mejor alternativa" al migrar completamente a git no es práctica.

Brian Phillips
fuente
3
Gracias. Esto me ha ayudado enormemente, especialmente el consejo sobre el uso de una combinación no rápida para agrupar los cambios de CVS en una única confirmación.
skiphoppy
8
Para el registro, la opción -A que sugiere usar para git-cvsimport se menciona en la página de manual como "no recomendada ... si tiene la intención de exportar los cambios nuevamente a CVS más tarde con git-cvsexportcommit (1)". En mi caso, me gusta la forma en que los autores salen como están.
skiphoppy
2
Gracias por los consejos. Una cosa útil que he hecho es agregar "cvs =! Git cvsimport -k -a" debajo de [alias] en mi .gitconfig. Esto hace que "git cvs" sea DTRT (desde la parte superior del árbol).
bstpierre
1
Si no está git cvsimporten Debian, intenteapt-get install git-cvs
Tino
5
Mac OSX mavricks carece por completo de cvs y parece que git cvsimport depende de cvs. Initialized empty Git repository in /Users/gus/projects/foo/foobar/.git/ Can't exec "cvsps": No such file or directory at /Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git-cvsimport line 777. Could not start cvsps: No such file or directory git cvsimport: fatal: cvsps reported errorPor lo tanto, lamentablemente, esto no evita la ausencia de CVS :(
Gus
22

No debe confiar ciegamente en cvsimport y verificar si el árbol importado coincide con el del repositorio de CVS. Hice esto compartiendo el nuevo proyecto usando el complemento de eclipse CVS y descubrí que había inconsistencias.

Dos confirmaciones que se realizaron en menos de un minuto con el mismo mensaje de confirmación (para revertir un archivo eliminado por error) se agruparon en una gran confirmación, lo que resultó en un archivo faltante del árbol.

Pude resolver este problema modificando el parámetro 'fuzz' a menos de un minuto.

ejemplo:

% git cvsimport -d $CVSROOT -C dir_to_create -r cvs -k \
  -A /path/to/authors/file cvs_module_to_checkout -z 15

conclusión: revise su árbol después de importar

shil88
fuente
3

Además de la respuesta de Brian Phillips: también hay git-cvsserver que funciona como un servidor CVS pero en realidad accede al repositorio de git ... pero tiene algunas limitaciones.

Jakub Narębski
fuente