en Desarrollo, Version control

Git series III – Git flow

Hay muchas formas de trabajar y versionar tu trabajo; de eso estamos completamente conscientes. Sin embargo, en ocasiones necesitamos organizarnos y adoptar un estándar para garantizar que todos los colaboradores hablen una misma lengua franca.

Ante ello, en Klooid decidimos adoptar un Git flow basado en master-development-feature. En entradas anteriores, hemos introducido que manejamos branches para:

  • master
  • development
  • features

Eso ha sido la punta del iceberg y vamos a profundizar cómo trabajar con este Git flow, que puede ayudarte en tus proyectos,

La perspectiva del proyecto

Lo primero es definir la perspectiva del proyecto o de una aplicación. Generalmente, con el enfoque master-development-feature visualizamos el proyecto como si fuera una aplicación base (development) y vamos añadiéndole funcionalidades (features). Es por así decirlo, un diseño bottom-up.

Enfoque de la aplicación con el Git flow propuesto

Al final de nuestro desarrollo, cuando todos los features estén dentro de development, estaremos listos para dar el siguiente paso y decir que nuestra aplicación está lista y se desplegará en master.

Es importante destacar que estos features, development y master representan branches en nuestro repositorio.

¿Cómo se ve un repositorio con este enfoque?

Siempre es importante tener en cuenta el flujo de desarrollo mediante el grafo de nuestro repositorio. Esto nos ayudará a comprender qué sucede dentro de nuestra aplicación.

Ejemplo de un grafo que sigue el git flow. Obtenido de NSC Image Converter

Una aplicación que sigue el git flow, generalmente se ve contínuo con tres líneas de desarrollo paralelas, que corresponden al desarrollo de funcionalidades (feature), el proyecto en pre-producción (development) y el proyecto en producción (master).

Administración y manejo de integración (features)

Asumiendo que el proyecto es colaborativo o al menos hay una persona que es desarrollador y otra que está a cargo del proyecto, se recomienda tener un proceso de revisión de los features antes de integrarlos a la línea de pre-producción. A este proceso de revisión se le denomina code review.

Los branches de features deben SIEMPRE salir de la versión más actualizada de pre-producción, no importa si hay desarrollo paralelo o no. Si un colega logró integrar su funcionalidad antes de que nuestra funcionalidad estuviera lista, esta debe readecuarse a la versión más actualizada mediante un «rebase». Este tema quedará para más adelante.

Mencionado esto, después de haber terminado la funcionalidad y ejecutado todas las pruebas necesarias, la funcionalidad debe integrarse mediante un mecanismo llamado Merge Request, que tenga la intención de hacer merge (o combinar) el feature a la rama de desarrollo.

Para crear un Merge Request, basta ir al sidebar izquierdo de Gitlab y presionar Merge request.

Merge request button en Sidebar

Después de ello, seleccionamos nuestros branches de inicio y destino. Usualmente, el destino es «development»:

Selección de branches en merge request

Posteriormente, describimos el nombre de la integración y comentarios sobre los cambios que realiza dicha integración:

Merge request form

Es usualmente buena práctica no eliminar los branches de feature. Ante ello, es bueno siempre deshabilidar la opción: Delete source branch when merge request is accepted.

Proceso de revisión

Los desarrolladores que revisan el código usualmente dejan comentarios sobre sugerencias o advertencias. Estos se crean en la página principal del merge request:

Ejemplo de sugerencia brindada en un Code Review

El desarrollador de la funcionalidad es el encargado de tomar en cuenta estas recomendaciones y aplicarlas según lo crea necesario. Existen varias guías para solucionar conflictos entre los que hacen la revisión y el desarrollador y son fundamentadas en el Coding Style Guide que se siga en el proyecto.

Cada cambio debe integrarse mediante commits al branch de la funcionalidad y deben volverse a revisar por el comité de revisión, hasta que haya un acuerdo unánime para realizar el merge.

Usualmente, las aprobaciones lucen de la siguiente forma:

Ejemplo de un approval

Cuando el merge request es aprobado, se puede dar click en el botón de merge.

Comenzar una nueva funcionalidad

Después de tener la aprobación sobre una funcionalidad, es necesario volver al branch de development, actualizarlo y sacar un nuevo branch desde la versión más actualizada de develop. Para ello, hacemos un checkout a development, seguido de un pull y un nuevo branch:

git stash
git checkout develop
git pull origin develop
git branch feature/nueva-funcionalidad-2
git checkout feature/nueva-funcionalidad-2
git stash pop

Los comandos git stash y git stash pop son comandos para salvar los cambios realizados y no integrados dentro de la funcionalidad, pero que siguen siguiendo necesarios. El primero sirve para guardar estos cambios dentro de un caché, y el segundo para recuperarlos del caché e reintegrarlos nuevamente.

El git checkout funciona para el cambio de branches, mientras que git branch <new_branch> sirve para crear una nueva rama. El git pull es para descargar los cambios desde Gitlab a nuestro repositorio local.

Ya tenemos integradas todas las funcionalidades – release

Después de haber repetido los pasos anteriores para todas las funcionalidades, es necesario hacer un release. Generalmente, esto es labor del maintainer del repositorio.

Un release consiste en integrar los cambios de pre-producción (o development) a la rama de master. Para ello, solamente es ejecutar un merge a master:

git checkout develop
git pull origin develop
git checkout master
git pull origin master
git merge --no-ff develop
git push origin master

En este caso, se trata de actualizar nuestra versión de development en nuestro repositorio local, igualmente para master. Después, se ejecuta el merge con el comando git merge --no-ff develop seguido de un push para integrar los cambios a master de nuestro repositorio remoto.

Luego, se realiza un release desde Gitlab (sidebar -> Project overview -> Releases), creando un tag.

Ejemplo de release

Los nombres del tag usualmente siguen la convención del semantic versioning. Siempre son creados desde master e incluyen notas sobre los cambios y funcionalidades que incluye.

Resultado de un release

El resultado de un release se muestra arriba, con archivos comprimidos que se entregan en el proyecto.

Ejercicio

Queremos que te entrenes con el siguiente ejercicio para que entiendas la mecánica del git flow:

  1. Crear un branch de develop desde master.
  2. Hacer un push de develop.
  3. Crear un branch feature/my-feature-1 desde develop.
  4. Hacer 5 commits con algún código.
  5. Hacer un push a feature/my-feature-1.
  6. Crear un Merge Request. Invítanos o dile a un amigo que revise tu código mediante Gitlab.
  7. Integra los cambios requeridos y envíalos mediante nuevos commits. Luego de que hagas los commits, recuerda hacer push al branch de feature/my-feature-1.
  8. Después de la aprobación, haga el merge de feature/my-feature-1 a develop.
  9. Repita 3-8 para otro branch feature/my-feature-2.
  10. Haga un release.

Referencias

Quizás pueda interesarte tener algunos enlaces de referencia:

Y un repositorio de ejemplo.

Escribe un comentario

Comentario