Ir al contenido principal

Nombrado de ramas en Git

Git es un sistema de control de versiones. Se encarga de registrar los cambios de los archivos en un proyecto, y coordina en un repositorio central los cambios de diferentes desarrolladores que trabajan en paralelo. Gracias al exito de Github y Gitlab, Git es una herramienta muy utilizada.

Git trabaja con el concepto de ramas de forma nativa. Un proyecto en Git parte de una rama principal, normalmente llamada master. Desde una rama determinada se pueden generar nuevas ramas (tanto desde master, como desde cualquier otra). Una rama podríamos verlo como un directorio en el que se copia todo el contenido de la rama principial, y sobre el que se puede trabajar por separado. Se pueden realizar desarrollos sobre una rama concreta, y git se encargará de auditar cuales son las modificaciones realizas. Con posterioridad, Git proporciona un modo de mezclar una rama origen en una rama destino. De esa forma, se comparan los diferentes cambios que se aplicaron en la rama origen, y se intenta replicar en la rama destino.

Gracias a estas herramientas de Git, es sencillo tener un código fuente base; crear una rama separada para ese código fuente; realizar cambios sobre esa rama separada, y cuando estemos seguros de que los cambios sean correctos, realizamos una mezcla de nuevo sobre el código base.

Vicent Driessen, propuso en su blog un criterio para el nombrado y utilización de ramas muy interesante para grandes proyectos.

Master y Develop

El proceso de gestión de ramas propuesto gira en torno a estas dos ramas. Estas son las ramas más importantes de cualqueir proyecto, y todo lo que hagamos como desarrolladores debe terminar en una de estas dos ramas.

  • Master: contiene el código que está desplegado en producción. Es la copia en oro de nuestra aplicación o de nuestro servicio. En cualquier momento podemos coger la rama master y usar su código fuente para generar de nuevo un paquete instalable que será exactamente igual que el que está desplegado en producción. Esta rama es intocable, y nunca se debería mover a ella nada que no esté en producción. Gracias a esto, en caso de que aparezca algún problema en producción podemos recuperar el código exacto que está desplegado y trabajar sobre él.
  • Develop: contiene todos los desarrollos que estan pendientes de pasar a producción. Develop tiene que ser una rama estable, y debe ser la copia en oro del equipo de desarrollo. Cualquier persona debe poder llegar nueva al equipo, coger la rama de Develop, y empezar a trabajar sobre ella sin problemas ni incompatibilidades. Ningún desarrollo parcial debe mezclarse contra Develop hasta no estar seguros de que está correcto, y que ha sido testeado de forma razonable. El objetivo de esta rama es poder sacar una nueva versión de producción en cualquier momento. El equipo de gestión del proyecto no tiene porque saber como es el estado de los desarrollos abiertos, pero si que tiene que poder saber que en un momento dado, pueden coger Develop y usarla para preparar un pase a explotación de forma segura.

Nunca se debería tocar directamente el código de esas ramas. Tenerla como discos de oro ofrece la seguridad de tener dos puntos de partida seguros para las tareas realacionadas con el código fuente.

Para trabajar con el código fuente, utilizaremos las diferentes ramas de trabajo:

  • Para hacer el desarrollo de una historia de usuario se abrirá una rama "feature/xxxx" desde develop. Un desarrollador o equipo de desarrollo trabajará sobre esa rama hasta tener implementada la solución para la historia de usaurio. El equipo de desarrollo debe probar sus desarrollos en la rama de feature para estar seguros de que funcionan correctamente los desarrollos, y que el programa sigue siendo estable. Cuando esté todo listo, lo ideal es hacer una mezcla desde desarrollo hacia la feature (para recoger los últimos cambios que hayan podido llegar a desarrollo), pasar un ciclo de pruebas en la feature, y terminar haciendo un merge desde la feature hacia develop para intergrar en develop la solución de la historia de usuario.
  • Para hacer una corrección de un bug que se ha detectado en producción se abrirá una rama "hotfix/xxxx" desde master. Un desarrollaodr o equipo de desarrollo trabajará sobre esa rama hasta tener implementada la corrección. El equipo probará en la rama de hotfix que la solución arreglé el problema y que el programa sigue siendo estable. Cuando esté todo listo, se hará un merge desde master hacia la rama hotfix para coger los últimos cambios de master (para recoger los últimos cambios que se hayan podido hacer en otro hotfix); se pasará un ciclo de pruebas completo en la rama de hotfix. Para terminar se generará la versión de producción corregida desde la rama de hotfix, y cuando esté en producción se hará el merge de hotfix en master. Despues de ello, se hará un merge de develop en el hotfix y se comprobaran que tanto la solución como el programa siguen estables, y una vez validado, se hará el merge de hotfix en develop y se cerrará.
  • Para pasar el código de desarrollo a producción se abrirá una rama release como una copia de develop. El código que está en la rama de release se utilizará para publicar una versión de la aplicación en un entorno de pruebas. Cualquier problema que se encuentre durante la revisión de la release se corrige directamente en la rama de release, hasta que se está seguro de que sirve para publicar. En ese momento, se pasa a producción, y se hace primero mezcla de la release con master. Despues de ello se hara mezcla de develop con la release para validar posibles desarrollos, y de vuelta de release a develop para tener en develop el código actualizado con lo que se publicó en real.

Feature

Cada vez que querramos hacer un desarollo de una nueva caracteristica para el software, en lugar de trabajar directamente sobre la rama de desarollo, abrimos una rama para el desarrollo de dicha feature a partir de la rama de desarrolo. De esa forma contamos con un entorno aislado para hacer el desarrollo de dicha caracteristica. Dicho entorno permite que el desarrollo de una caracteristica no interfiera con el desarrollo de otras caracteristicas.

Evitamos que el código de desarrollo esté bloqueado por un desarrollo a medio terminar. En caso de que el desarrollo de una caracteristica se encuentre con problemas y se retrasen; o que por alguna decisión de negocio una de dichas caracteristicas se posponga, no hay problema. La rama de desarrollo sigue estando estable y no incluye elementos que no sepueden terminar o comprobar. Simplemente se puede abandonar la rama (o posponerla) con la seguridad de que no vaya a tener código espúreo o sin control.

Cuando el desarrollo de una característica está terminado, es necesario integrar dicho desarrollo con la rama de desarrollo. Es importate recordar que desarrollo debe estar siempre estable. Dado que durante el desarrollo de una caracteristica, es probable que otros equipos de desarrollo puedan haber terminado con otras caracteristicas y las hayan integrado en la rama de desarrollo. No tenemos la seguridad de que cuando vayamos a reintegrar el código tras desarrollar una características, la rama de desarrollo conserve el mismo código y la misma estructura que cuando se inició el trabajo en la característica. Para poder reintegrar de forma segura, se debería primero hacer un merge desde develop para que en la feature se disponga de la última versión de desarrollo. Con ese mergue completado, se debería pasar un ciclo de QA sobre la rama feature para confirmar que los los cambios siguen siendo estables tras traer los mezclar los desarrollos de otros equipos.

Una ventaja adicional que se obtiene con usando ramas separadas para las features es que cada desarrollo queda aislado de otros durante su la mayor parte de su ciclo de vida. Si hay varios equipos de desarrollo estan trabajando en paralelo en diferentes desarrollos, y alguno de dichos equipos hace un cambio que desestabilicen la aplicaión... dichos problemas quedan aislados en la rama del equipo que lo probocó. Otros equipos no se veran bloqueados por un sistema no disponible por causa de algún problema introducido por otros equipos (o al menos no se convertirá en algo habitual).

Hotfix

Cuando se detecta un error en un entorno de producción es importante poder corregirlo de manera segura. Si dependieramos de la rama de desarrollo para poder corregir un error de producción, estaríamos ante un problema bastante grave. Nada nos aseguraría que los desarrollos en progreso esten seguros como para poder pasarlos a explotación. De echo, aunque los desarrollos estén estables para poder pasarlos a producción, podemos encontrarnos con que desde el equipo de marketing o de negocio no se quiera que determinados desarrollos lleguen a producción en dicho momento.

Para poder hacer una corrección de un bug en producción, lo que se hace es sacar una rama "hotfix" a partir de la rama master. De esta forma es posible mantener aislados el desarrollo de una corrección concreta, y en paralelo abrir una nueva corrección para otro problema que se pueda detectar.

Release

Cuando por fin se planifica una entrega del software, lo normal es ponerlo en manos de un equipo de QA que ejecute pruebas en un entorno muy similar al entorno real, para así minimizar los posibles errores que se lleven a real. Siendo sinceros, no son raros los errores que aparecen únicamente en entornos de este tipo: peticiones se vuelven insoportablemente lentas al trabajar con grandes volumenes de datos, registros de base de datos extrañamente incompletos y teóricamente imposibles que probocan problemas.... No es nada extraño tener que desarrollar parches y soluciones para corregir problemas que se detecten en el entorno de QA.

Evidentemente, cuando el código de una entrega no cumple con los mínimos necesarios, la respuesta es echarlo atras, y volver a trabajar en la rama de desarrollo. Sin embargo existe un paso intermedio: cuando se detectan pequeñas incidencias las soluciones suelen ser bastante sencillas, se pueden hacer directamente sobre la rama de Release. De esa manera no se afecta a posibles trabajos que se esten haciendo sobre la rama de desarrollo.

Cuando las validaciones de QA se alargan en el tiempo, no es raro empezar a acumular desarrollos en la rama de desarrollo mientras la validacion y corrección de la rama de release correspondiente se prolongan. Teniendo ese código de release separado, se consigue la seguridad de que no se verá afectado por nuevos desarrollos que puedan obligar a volver a iniciar la revisión del código.

Comentarios