Branching, haciendo crecer nuestro árbol del repositorio de código

En el artículo anterior de esta miniserie, estuve tratando sobre la necesidad básica de tener un repositorio de código. Y de una primera aproximación a la gestión más madura del trabajo por medio del etiquetado de versiones: labeling.

En esta segunda parte, final, quiero dar un paso adelante y describir una técnica de separación de las líneas de desarrollo en el repositorio de código fuente que nos ayude, en gran medida, a organizar la complejidad inherente a todo desarrollo en equipo.

Branching, dicho de forma espantosa sería algo como “rameando” o ir haciendo ramas, se utiliza en los repositorios de código. No es algo novedoso, ni mucho menos. De hecho, al menos desde los años 70 ya existen aplicaciones como CA Software Change Manager, que permiten hacer branching; mucho antes de que algunos de nuestros lectores hubiese, tan siquiera nacido.

Porqué necesitamos hacer branching


Por ejemplo, estoy integrado en un equipo de cuatro personas haciendo un proyecto de una aplicación de gestión de una empresa de repuestos. Y empezamos a trabajar sobre el módulo de almacén.

Vemos que vamos a necesitar hacer una pantalla típica de CRUD: alta, modificación, baja y listado de piezas. Para ir más deprisa vamos a trabajar los cuatro al mismo tiempo en la misma pantalla, por lo cual vamos a trastear en el mismo código tanto en la capa de representación, en la de negocio y en la de acceso a datos.

Para que no haya problemas, habilitamos la capacidad de checkin múltiple, así varios podemos tocar el mismo código al mismo tiempo, y mantenemos la coherencia del código por medio de merges. Cuando lo tenemos acabado y vemos que ha funcionado bien, le ponemos una etiqueta, y continuamos con la siguiente pantalla.

Cuando tenemos terminado el módulo de almacén, y todas sus pantallas, volvemos a etiquetar y le damos al cliente el módulo para su puesta en producción. Y nos disponemos a continuar con el módulo de facturación, que está muy relacionado con el de almacén.Nos volvemos a repartir el trabajo, y empezamos a modificar y añadir las líneas del nuevo código al ya existente de almacén.

Y en esto nos encontramos que el cliente ha encontrado un fallo crítico y hay que corregirlo y publicar una actualización. Para ello nos hacemos una copia de seguridad, recuperamos la etiqueta, realizamos los arreglos, volvemos a etiquetar y se lo mandamos al cliente el módulo arreglado.

¿Y ahora cómo vuelvo al código original, que aún no funciona y que está en desarrollo; y, además, le añado los arreglos añadidos en la nueva versión?

La respuesta más obvia es, utilizando desarrollo en ramas (branching).

Cuando he terminado de hacer el módulo de almacén, no solamente lo etiqueto si no que creo una nueva rama, que es una copia del código, en donde voy a ir desarrollando el nuevo módulo de facturación. Así, si tengo que modificar el módulo de almacén, no tengo que esperar a tener una versión funcional del de facturación, o andar haciendo copias de seguridad.

Como se ve en la figura, este sistema es mucho más robusto y seguro. Y evito que los trabajos en un módulo me afecten al trabajo en los demás.

Diferentes sabores


Ahora que tengo claro que la complejidad del desarrollo del software me lleva de la mano a realizar ramas en mi repositorio de código, quiero compartir los dos primeros niveles de branching que utilizo con diariamente.

El primero es una forma secuencial en donde tengo el tronco de la aplicación (siempre lista para ser desplegada), etiquetado cada punto de publicación y en donde las modificaciones y añadidos se inician, se completan y se unen al tronco por medio de una rama. Una vez terminada la misma, iniciaría otra rama para el siguiente módulo.

Esta forma de trabajo tiene la ventaja de ser muy ordenada y que la dirección de las actualizaciones siempre es del branch al trunk. Es decir, del nuevo desarrollo a la línea base. Como inconveniente, se complica hacer varios trabajos de forma simultánea. A menos que arranquemos tareas de similar duración que acaben al mismo tiempo o que no compartan nada de código (lo cual es difícil en cuanto empiezas a trabajar en capas).

Lo más habitual es que el grafo del árbol de ramas alrededor del tronco principal, sea de múltiples direcciones. No solamente de las ramas hacia el trunk, si no de este a diferentes ramas o, incluso, entre ramas diferentes.

Así, por ejemplo, en la figura anterior he iniciado una corrección en el trunk mientras termino el módulo1. Ya que he terminado la corrección, hago un merge de este con el branch del módulo 2, para que esté actualizado; ya que hay cosas en la capa de negocio que están implicadas.

Como se ve, con esta forma de trabajo voy a tener una versión de la aplicación lista para ser publicada en cualquier momento. Aseguro el no tener que esperar a que se acabe un trabajo para iniciar otro. Y puedo mantener actualizado los módulos según lo necesite en cada caso.

El mayor inconveniente es la complejidad. Si somos varios equipos, y realizamos desarrollos cruzados, con puntos en común crecientes y que se deben mantener sincronizados, puedo tener un árbol con muchas ramas que llegue a ser confuso o difícil de abarcar.

A partir de este punto de madurez, podemos ir ganando complejidad subdividiendo los trabajos incluso hasta tener una rama por Sprint o por tarea dentro de un Sprint. Teniendo siempre claro que el concepto subyacente es que el desarrollo no impida tener código funcionando en cualquier momento.

Incluso podemos llegar a un sistema de branching similar a una publicación continua, en donde no trabajamos contra un tronco, si no con simultaneas ramas. Y donde se activan o desactivan las funcionalidades según tengamos finalizados y probados los módulos.

Ahora solamente queda el pasar de la teoría a la práctica y ver un ejemplo en mi repositorio de código.

Más información | Visual Studio Team Foundation Server Branching and Merging Guide, Git. Magia Con Los Branches
En GenbetaDev | Etiquetando,haciendo crecer nuestro árbol del repositorio de código, Manejo de ramas de desarrollo con git

Portada de Genbeta