Git

Cinco Git Workflows para mejorar nuestros proyectos

En el ámbito del desarrollo de software, es común que los profesionales nos encontremos inmersos en una variedad de flujos de trabajo relacionados con el sistema de control de versiones Git. En el presente artículo, se enfocará en profundidad en los diversos aspectos que ofrecen las metodologías de trabajo contemporáneas. Esto abarcará aspectos tales como la introducción de cambios, la resolución de conflictos, el uso de ramas, entre otros.

Cada equipo de desarrollo tiende a diseñar su propio flujo de trabajo, el cual se adapta según la naturaleza del proyecto, el tamaño de la empresa y las preferencias del equipo, entre otros factores. A medida que el equipo crece, se plantean desafíos adicionales, ya que los conflictos se vuelven más recurrentes, las fechas de lanzamiento pueden requerir ajustes, y las prioridades pueden cambiar de manera inesperada.

La utilización de Git se convierte en el punto de partida fundamental para abordar estas problemáticas, dada su versatilidad para adaptarse a prácticamente cualquier tipo de flujo de trabajo. En este contexto, se presentan cinco tipos de flujos de trabajo Git que pueden ser empleados de manera efectiva en un proyecto determinado.

Git Flow

Es el flujo de trabajo más popular y extendido. Se basa en dos ramas principales con una vida infinita. Para cada tarea que se le asigna a un desarrollador se crea una rama feature en la cual se llevará a cabo la tarea. Una vez que ha finalizado, realizará un pull request (validación) contra develop para que validen el código. Pasamos a detallar las dos ramas principales que se utilizan: Master: Contiene el código de producción. Todo el código de desarrollo, a través del uso de releases, se mergea (fusiona) en esta rama en algún momento. Develop: Contiene código de pre-producción. Cuando un desarrollador finaliza su feature, lo mergea contra esta rama. Durante el ciclo de desarrollo, se usan varios tipos de ramas para dar soporte: Feature: Por cada tarea que se realiza, se crea una nueva rama para trabajar en ella. Esta rama parte de develop. Hotfix: Parte de master. Rama encargada de corregir una incidencia crítica en producción. Releases: Parte de develop. Rama encargada de generar valor al producto o proyecto. Contiene el código que se desplegará, y una vez que se han probado las features integradas en la release, se «mergeará» a la rama master. Pros Fácil de comprender el flujo de ramas. Ideal para productos estables que no requieren de desplegar cambios inmediatamente. Muy recomendable cuando el equipo tiene todo tipo de desarrolladores. El control de las features más la release hace que el código no se deteriore. Perfecto para productos open-source en los que pueden colaborar todo tipo de desarrolladores. Contras No es el más indicado si tu proyecto necesita iterar muy rápido y subir a producción varias veces al día o semana. En caso de que el proyecto utilice varias herramientas de integración continua, la rama develop puede convertirse en una rama redundante de master. El uso de la rama master como rama protegida. Muchas herramientas de automatización usan la rama master por defecto. Gran complejidad en las ramas creadas de hotfix y releases. La integración continua elimina la necesidad de la creación de estas ramas, facilitando el despliegue.»ChatGPT

«Este es el flujo de trabajo más prevalente y ampliamente adoptado en el desarrollo de software. Se fundamenta en la existencia de dos ramas principales, ambas con una duración indefinida. Cada tarea asignada a un desarrollador se ejecuta en una rama de funcionalidad (feature branch) designada específicamente para esa tarea. Una vez que la tarea se ha completado, se genera una solicitud de extracción (pull request) hacia la rama ‘develop’ para que el código sea validado.

Ahora procederemos a detallar las dos ramas principales utilizadas en este flujo de trabajo:

  1. Master: Contiene el código en producción. A través del uso de versiones (releases), todo el código desarrollado se fusiona en esta rama en algún momento.
  2. Develop: Alberga el código en pre-producción. Cuando un desarrollador completa su tarea (feature), fusiona su trabajo en esta rama.

Durante el ciclo de desarrollo, se emplean varios tipos de ramas de soporte, que incluyen:

  • Feature: Se crea una nueva rama por cada tarea que se aborda, partiendo de ‘develop’.
  • Hotfix: Derivada de ‘master’, esta rama se encarga de solucionar incidencias críticas en producción.
  • Releases: También parte de ‘develop’, esta rama se utiliza para generar valor al producto o proyecto. Contiene el código que se desplegará, y una vez que se han probado las funcionalidades integradas en la versión (release), se fusiona en la rama ‘master’.

Ventajas:

  • Fácil comprensión del flujo de ramas.
  • Ideal para productos estables que no requieren desplegar cambios de inmediato.
  • Altamente recomendado cuando el equipo incluye diversos tipos de desarrolladores, ya que el control de las características (features) junto con las versiones (releases) previene el deterioro del código.
  • Excelente para proyectos de código abierto en los que pueden colaborar desarrolladores de diversos perfiles.

Desventajas:

  • No es la mejor opción si el proyecto necesita iterar de manera muy rápida y realizar despliegues en producción varias veces al día o semana.
  • En proyectos que hacen uso de varias herramientas de integración continua, la rama ‘develop’ puede volverse redundante respecto a ‘master’.
  • La rama ‘master’ como rama protegida puede plantear dificultades, ya que muchas herramientas de automatización la utilizan de forma predeterminada.
  • La creación de ramas para correcciones urgentes (hotfix) y versiones (releases) añade una gran complejidad, la cual puede ser eliminada a través de una implementación adecuada de la integración continua, facilitando así el proceso de despliegue.

GitHub Flow

La principal diferencia con GitFlow radica en la eliminación de la rama ‘develop’. Este flujo de trabajo se basa en los siguientes principios:

  1. Todo lo que se encuentra en la rama ‘master’ debe ser desplegado.
  2. Para cada nueva característica, se crea una rama a partir de ‘master’ utilizando un nombre descriptivo.
  3. Los cambios se confirman (commit) en esta rama localmente y luego se suben al servidor bajo el mismo nombre.
  4. Si es necesario recibir retroalimentación, se recurre a las herramientas de fusión, como las solicitudes de extracción (pull request).
  5. Una vez que el código ha sido revisado, se puede fusionar con ‘master’.
  6. Después de la fusión en ‘master’, se procede a desplegar los cambios.

Ventajas:

  • Compatible y fácil de integrar con las herramientas actuales de Integración Continua (CI) y Despliegue Continuo (CC).
  • Recomendado para características de corta duración, como aquellas que se desarrollan en un día o incluso en cuestión de horas.
  • Ofrece un flujo de trabajo ágil y es adecuado si el proyecto demanda una entrega constante de valor.

Desventajas:

  • Puede haber inestabilidad en la rama ‘master’ si no se emplean adecuadamente las herramientas de pruebas y las solicitudes de fusión.
  • No es recomendable para proyectos que necesitan soportar múltiples entornos de producción.
  • Dependiendo del tipo de producto, pueden existir restricciones en los despliegues, especialmente en aplicaciones de Software como Servicio (SaaS).

GitLab Flow

GitLab Flow representa una alternativa o extensión de GitHub Flow y Git Flow, surgiendo en respuesta a las limitaciones presentes en estos dos flujos de trabajo. Mientras que GitHub Flow promueve la idea de que todo lo que está en la rama ‘master’ se despliega, existen casos en los que esta premisa no es factible o simplemente no se requiere. Un ejemplo de ello son las aplicaciones iOS que deben pasar por una validación en la App Store o proyectos que demandan ventanas de despliegue específicas debido a requerimientos del cliente.

El flujo de GitLab propone la utilización de la rama ‘master’, ramas de características (features), y ramas de entorno. Una vez que una característica se completa, se crea una solicitud de fusión (merge request) con la rama ‘master.’ Cuando ‘master’ acumula varias características, se realiza una solicitud de fusión hacia el entorno de preproducción con el conjunto de características previas. Estas, a su vez, son candidatas a pasar a producción a través de otra solicitud de fusión. Este enfoque asegura una gran estabilidad en el código que se implementa en producción, ya que se someten a validación tanto a nivel individual como en lotes.

La naturaleza de este flujo no requiere la creación de ramas de versiones (releases), dado que cada entorno se despliega con cada solicitud de fusión aceptada.

Ventajas:

  • Elevada confianza en la versión de producción.
  • Ciclo de desarrollo altamente seguro, ya que se evalúa el código tanto a nivel individual en las características (features) como a nivel global al pasar a preproducción o producción, lo que mitiga el impacto de los errores.
  • Evita la necesidad de crear versiones, etiquetados (tagging) y fusiones con ‘develop’ (merge to develop).

Desventajas:

  • Requiere un equipo encargado de validar las solicitudes de fusión, tanto de las características (features) como de los diferentes entornos.
  • El tiempo necesario para entregar valor es relativamente extenso. Desde la creación y validación de una característica hasta su implementación en producción, deben atravesarse varias etapas de validación.
  • Más complejo que GitHub Flow.

Trunk-based Flow

Este flujo de trabajo guarda similitudes con GitHub Flow, pero introduce nuevas características, especialmente la inclusión de ramas de versiones (releases branch) y un cambio en la filosofía subyacente. Los principios fundamentales que guían este flujo de trabajo son los siguientes:

  1. Los desarrolladores deben colaborar directamente en la rama principal (trunk o master).
  2. Queda estrictamente prohibido crear ramas de características (features branch) basadas en documentación técnica. En situaciones de complejidad, se recurre a ‘feature flags’ (condicionales en el código) para activar o desactivar nuevas funcionalidades.
  3. Se fomenta el uso de la metodología Pair-Programming en lugar de depender en exceso de las solicitudes de extracción (PR).
  4. Se crean ramas de versiones (release) para permitir el despliegue del código en diversos entornos, ya sea en dispositivos móviles, web, u otros.

Ventajas:

  • Altamente efectivo en proyectos que requieren iteraciones rápidas y la entrega oportuna de valor.
  • Se adapta bien a proyectos ágiles de menor envergadura.
  • Ideal para equipos que implementan pair-programming como práctica habitual.
  • Funciona de manera óptima con equipos experimentados y cohesionados.

Desventajas:

  • Requiere de una responsabilidad significativa por parte de los desarrolladores para mantener un código de alta calidad.
  • El proyecto debe contar con un enfoque sólido en calidad asegurada (QA) y despliegue continuo (CD), o de lo contrario, se introducirán muchos errores en la rama principal.
  • No se recomienda su uso en proyectos de código abierto, ya que implicaría la necesidad de una validación adicional del código.

Master-only Flow

El flujo de trabajo adopta un enfoque que se basa en el uso de una única rama de desarrollo continua. Para fines de esta descripción, emplearemos el término ‘master,’ que es el nombre más común y una convención de Git ampliamente aceptada. Sin embargo, es importante señalar que también se pueden utilizar otros nombres como ‘current,’ ‘default,’ ‘mainline,’ u otros.

En este enfoque, cada nueva funcionalidad (feature) o corrección urgente (hotfix) se desarrolla directamente en la misma rama principal. Estas implementaciones se someten a pruebas y se realizan confirmaciones locales (commits) en el entorno del desarrollador. Una vez que estos cambios son validados, se realizan ‘push’ a la rama ‘master’ en el repositorio remoto (origin), lo que resulta en un despliegue inmediato en el entorno de producción.

Este flujo de trabajo está particularmente orientado a proyectos que involucran desarrolladores altamente experimentados y en los cuales se promueve el pair-programming. Además, se requiere la implementación de ‘feature flags’ para facilitar la integración del código en la rama ‘master’ y prevenir conflictos a lo largo del tiempo.

Ventajas:

  • Se mantiene únicamente una rama de desarrollo.
  • El historial del proyecto se mantiene limpio y sencillo.
  • Con el uso de pair-programming y desarrolladores experimentados, la entrega de funcionalidades en producción es inmediata.

Desventajas:

  • No es adecuado para proyectos que necesiten soportar múltiples entornos de producción.
  • Requiere de desarrolladores altamente experimentados para garantizar la estabilidad de la rama principal.
  • El proyecto debe contar con directrices de código altamente estrictas para evitar problemas.

Author

osceda@hotmail.com