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 cvsimport
para 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 -A
opció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-cvsimport
para 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 master
rama que debería reflejar el HEAD de CVS (con la excepción de que, git cvsimport
por defecto, ignora los últimos 10 minutos de confirmaciones para evitar atrapar una confirmación que está a medio terminar). Luego puede usar git log
y 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 cvsimport
pá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 cvsimport
debería ser mucho más rápida que la primera invocación. Sin embargo, lo hace cvs rlog
en 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:
- 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
cvsimport
que volverá a tomar una eternidad.
- Asegúrese de estar en su
master
rama 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 master
cuando 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 cvsexportcommit
comando 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 cvs
cliente 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 master
y 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-merge
para obtener una descripción de una combinación de avance rápido), por lo que debe usar el--no-ff
opció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 -w
opció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 master
esté 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 cvsimport
anterior).
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 clone
configura 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.