tortoise - Adaptación de svn: uso externo para pasar a Mercurial
svn merge branch to trunk (1)
Tenemos en un entorno corporativo una estructura de repositorio svn que se ve así:
root
libs
shared_lib1
shared_lib2
private_lib
public_code
private_code
donde public_code es un repositorio externo que es de código abierto y donde personas ajenas a la empresa tienen acceso de lectura-escritura. shared_lib1 y shared_lib2 también son repositorios externos compartidos con un grupo diferente de programadores de otra compañía. Soy el mantenedor y puedo hacer básicamente lo que sea técnicamente mejor, los usuarios externos tendrán que adaptarse.
Ahora me pregunto cuál es la mejor manera de pasar de esta estructura a un repositorio mercurial.
1) Podría simular de cerca la configuración anterior usando subrepositorios mercuriales. O
2) Podría hacer un gran repositorio para nosotros y tres nuevos repositorios más pequeños y separados para los socios externos (básicamente, bifurcar proyectos) e intercambiar conjuntos de cambios entre el grande y los diferentes.
Con la configuración 1) en svn, la bifurcación es una pesadilla porque, por política, siempre debo ramificar public_code, shared_lib1 y shared_lib2 cuando ramifico la raíz. Para esto tengo que llamar a la rama svn cuatro veces y modificar las propiedades svn: externals a mano tres veces. ¿Puedo ramificar fácilmente el repositorio principal en mercurial y obtener automáticamente nuevas sucursales para todos los sub-repositorios?
Cuando configuro 2), el sistema de archivos será diferente entre repositorios. Por ejemplo, tendré public_code / Makefile en el repositorio "root" pero el archivo será solo "Makefile" en el repositorio "public_code". ¿Mercurial podrá sincronizar los cambios entre los repos? ¿Cómo podría ser el flujo de trabajo?
Con la configuración 1) en SVN, la bifurcación es una pesadilla porque, por política, siempre debo ramificar
public_code
,shared_lib1
yshared_lib2
cuandoshared_lib2
root
. Para esto tengo que llamar a lasvn branch
cuatro veces y modificarsvn:externals
propiedadessvn:externals
mano tres veces. ¿Puedo ramificar fácilmente el repositorio principal en Mercurial y obtener automáticamente nuevas sucursales para todos los sub-repositorios?
No, los subrepositorios no funcionan así. Las ramas con nombre en el repositorio de nivel superior no se propagarán a los subrepositorios automáticamente. Si shared_lib1
una rama 1.x
en su código, entonces no está claro que shared_lib1
también debe tener la rama 1.x
De hecho, probablemente no debería ramificarse al mismo tiempo las ramas de código de nivel superior, especialmente si la biblioteca está siendo utilizada por varios proyectos de nivel superior diferentes.
Cuando configuro 2), el sistema de archivos será diferente entre repositorios. Por ejemplo, tendré
public_code/Makefile
en laroot
repositorio pero el archivo será soloMakefile
en el repopublic_code
. ¿Mercurial podrá sincronizar los cambios entre los repos? ¿Cómo podría ser el flujo de trabajo?
No, no puedes empujar y tirar entre los repositorios si los creas así. Solo puede hacer push / pull entre repositorios cuando se originan en el mismo repositorio "madre". Aquí parece que creará tres repositorios no relacionados.
En una situación como esta, debe evaluar cuidadosamente por qué tiene svn:externals
en Subversion y cómo se correlacionan con los subrepositorios de Mercurial . No son un reemplazo 1-1 para svn:externals
. También debería buscar soporte de herramienta para subrepos, tanto en Mercurial como en su hosting de Mercurial, su sistema de compilación continua, etc. Escribí parte del código de retapo de Mercurial y, a partir de Mercurial 2.0, todavía hay algunos bordes afilados aquí y allá.
En pocas palabras, lo que los subrepositorios te dan es un acoplamiento muy estrecho entre los subsistemas. Normalmente, esto es algo que hay que evitar :-) Hacemos todo lo posible para que nuestros sistemas de software se acoplen holgadamente ya que eso nos da flexibilidad.
El caso de uso principal para los subrepositorios es un "repositorio de compilación" donde rastrea las versiones precisas de los componentes que utilizó en una compilación determinada. No puede pedirle a Mercurial que rastree la punta de una rama determinada en un subrepo, siempre rastreará un conjunto de cambios dado en un repositorio dado. Esto es lo que hace posible volver a crear un proceso de pago determinado más adelante: el archivo .hgsubstate
rastrea los conjuntos de cambios precisos que se extrajeron en cada subrepo.
Por lo tanto, si su repositorio root
no se usa para el desarrollo, sino solo para la creación de versiones, los subrepositorios pueden funcionar de maravilla para usted. El flujo de trabajo será algo así como
$ cd root
$ cd libs/shared_lib1
$ hg pull
$ hg update 2.0
$ cd ../..
$ make test && hg commit -m "Updated to sharedlib1 2.0"
$ hg tag 2.3
A continuación, libera la versión 2.3 de su software y Mercurial sabe que depende de la versión 2.0 de shared_lib1
. Harás esto de vez en cuando cuando las personas responsables de los subcomponentes te digan que tienen un nuevo lanzamiento listo para ti. ¡Su servidor CI por supuesto puede hacerlo todas las noches para ver si los componentes funcionan juntos!
Los supositorios funcionan menos bien si los desarrolladores están trabajando directamente en la root
y si hacen cambios en los subcomponentes como parte de su trabajo en la root
. Eso es una indicación de un acoplamiento demasiado apretado entre los componentes: si el código principal depende de un conjunto de cambios exacto de un subcomponente, entonces el subcomponente debería estar directamente en el código principal. Además, hg commit
en el repositorio de nivel superior se repetirá y usará el mismo mensaje de confirmación en los subrepos cuando ui.commitsubrepos=True
. (El valor predeterminado fue cambiado a False
en Mercurial 2.0.) Esto a menudo no se desea y cuando tiene sentido, entonces el subrepo se acopla muy estrechamente y debe ser parte del repositorio de nivel superior.
Entonces, para resumir: use subrepos si root
es un "repositorio de compilación". De lo contrario, debe alinear los componentes en el repositorio de nivel superior, o debe acoplar las piezas juntas de forma más flexible mediante el uso de algo como Maven o similar para administrar las dependencias. Estas herramientas normalmente le permitirán decir "por favor, la última versión de root
y todas sus dependencias" y luego podrá hacer una versión formal cuando esté satisfecho con las pruebas. Estas compilaciones de "instantáneas" no se pueden reproducir con precisión, pero tampoco es necesario, solo las versiones finales necesitan un seguimiento de dependencias estricto y preciso.