Migración de código a un nuevo repositorio, manteniendo el historial de commits de GIT
GIT es una herramienta de control de versiones bastante extendida en el mundo de los desarrolladores de software. Según el portal Expanded Rammings (https://expandedramblings.com/index.php/github-statistics/) Github -la plataforma de administración de código fuente y alojamiento- tiene actualmente alrededor de 73 millones de usuarios activos (cifras actualizadas al 27 de noviembre de 2021). Esta popularidad se puede explicar principalmente por su uso intuitivo y el poder de versionar y administrar el código fuente a través de sucursales para un repositorio determinado.
Gestionar el código fuente de forma aislada, de forma incremental y ampliamente colaborativa (múltiples usuarios enriqueciendo la base de código, trabajando simultáneamente en nuevas funciones) de forma sencilla y objetiva es lo que me anima a, sin dudarlo, iniciar mis proyectos de software (en cualquier caso ).port) por un git init.
Los repositorios en GIT se pueden gestionar de dos formas:
· monorepo (mono-repository): un único repositorio que agrega múltiples proyectos, dispuestos de forma modular en un único marco de control de versión (por ejemplo: project_a_backend, project_a_front_end, project_b_backend, project_b_frontend); ilustrando:
· multirepo (multi-repository): como su nombre lo dice, es la representación de múltiples proyectos en múltiples repositorios (por ejemplo: project_a_backend repository, project_a_frontend repository, project_b_backend repository, project_b_frontend repository); ilustrando:
Al principio, puede parecer que esta información no tiene mucho sentido, pero tranquilos, ¡no está aquí de gratis!
Problema
En uno de mis retos en el mercado laboral, la empresa para la que trabajaba gestionaba sus proyectos en un monorepo. En cierto punto de los productos contenidos en el monorepo, la gestión de esta forma dejó de tener sentido –debido al crecimiento del código fuente, los múltiples lenguajes de programación en un mismo repositorio y los desacoplamientos que se estaban produciendo por desdoblamiento en reglas de negocio– .
Dicho esto, la solución más sencilla y tentadora sería crear un nuevo repositorio, copiar las fuentes de cada uno de los proyectos monorepo a su correspondencia en el multirepo y, listo, problema resuelto. ¿Y si te dijera que la respuesta es NO?
Eh... pero ¿por qué no sería esta la solución? Si todo el código fuente está allí... ¿significa eso que no es suficiente simplemente ejecutar el emocionante git init y enviar la confirmación inicial del proyecto? ¿Qué puede salir mal?
Bueno, inicialmente nada. Pero digamos que en un momento dado en uno de estos nuevos repositorios necesitaba consultar el historial de modificaciones de un archivo en específico y al consultar el historial, sorpresa: la única modificación del archivo es la confirmación inicial del proyecto. Sin antecedentes, todo perdido en la migración. ¿Y ahora?
Claramente este no fue el camino adoptado por mí, porque bajo ninguna circunstancia podía perder la “trayectoria del proyecto” contenida en la historia. A continuación, demostraré cómo resolví este problema
Solución
Por razones de confidencialidad no podré demostrar el proyecto real, migrado en esa situación. Para dilucidar el caso de estudio, creé dos repositorios hipotéticos: el monorepo (que centraliza los proyectos project_a_backend y project_a_frontend) y el multirepos (referido a la migración de project_a_backend y project_a_frontend). El ejercicio aquí consistirá en migrar project_a_backend y project_a_frontend fuera del monorepo, manteniendo exclusivamente los archivos que pertenecen a cada proyecto, así como su historial de confirmación.
Al iniciar, la estructura del repositorio monorepo es la siguiente:
Con el siguiente histórico de commits:
El resultado esperado después de dividir el monorepo debe ser:
· Para la migración del project_a_backend a su propio repositorio, este nuevo repositorio solo debe tener los commits “Creación del project_a_backend” y “Edición del source_code_backend” y un commit adicional referente a la división del monorepo en multirepos.
· Para la migración del project_a_frontend a su propio repositorio, este nuevo repositorio solo debe tener los commits “Creación del project_a_frontend” y “Edición del source_code_frontend” y un commit adicional referente a la división del monorepo en multirepos.
Para lograr este resultado, vayamos paso a paso:
Antes de iniciar el proceso de migración, crea una copia del proyecto monorepo y cámbiale el nombre a monorepo_tmp. Una vez hecho esto, instala git-filter-repo (en MacOS se puede instalar a través de brew ejecutando brew install git-filter-repo).
En el directorio del proyecto monorepo_tmp (copia del monorepo):
1. Ejecuta: git remote rm origin para remover el origen del repositorio temporal.
2. Ahora ejecuta: git filter-repo --path project_a_backend --tag-rename '':project_a_backend –force para filtrar los commits asociados al proyecto _a_ backend.
3. Mueve los archivos y directorios resultados del filtro aplicado para la raíz del repositorio monorepo_tmp.
4. Crea un commit para registrar las modificaciones.
· git add .
· git commit -am "División de monorepo en multirepos - proyecto_a_backend".
5. Navega hasta el directorio proyecto_a_backend.
6. Ejecuta: git remote add monorepo_tmp ~/Development/revelo/workspace/monorepo_tmp
7. Ejectuta: git pull monorepo_tmp master --allow-unrelated-histories
8. Ejecuta: git remote rm monorepo_tmp.
9. Verifica el historial de commits del nuevo repositorio con el git log.
El resultado debe ser:
Y la estructura project_a_backend debería verse así:
Haciendo lo mismo para project_a_frontend (teniendo cuidado de hacer las sustituciones necesarias en los pasos 2 y en la segunda viñeta del paso 4), el resultado debería ser:
Y la estructura project_a_frontend debería verse así:
Conclusión
Migrar el proyecto copiando y pegando el código fuente de un repositorio a otro es prácticamente un delito contra el patrimonio de una corporación, se trata de matar toda la evolución del producto hasta el momento de la migración.
Sin importar el tamaño de una empresa, cuando se trata de código fuente es importante que mantengamos el historial de GIT commits en una eventual migración de repositorio. Después de todo, es a través de este historial que podemos seguir la evolución del producto, comprender algunas de las decisiones tomadas en el proyecto, así como el seguimiento de la evolución de las reglas de negocio aplicadas a dicho producto.
Revelo Content Network da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.