Type something to search...
Implementando Trunk Based Development con Ramas de Vida Corta en Tu Equipo: Una Guía Completa

Implementando Trunk Based Development con Ramas de Vida Corta en Tu Equipo: Una Guía Completa

En el ámbito del desarrollo de software, la elección de una estrategia de versionamiento eficiente y estable es fundamental para el éxito de un equipo. El Trunk Based Development (TBD) tradicional, donde los desarrolladores trabajan directamente sobre una única rama principal (master o main), es ideal para equipos pequeños de 1 a 3 desarrolladores. Para equipos de 4 a 5 desarrolladores, aunque sigue siendo una opción viable, requiere indispensablemente la implementación de pruebas automáticas. Sin embargo, para equipos más grandes, con seis o más desarrolladores, una variante del TBD se presenta como una solución escalable: el Trunk Based Development con Ramas de Vida Corta (TBD con SLB). Esta estrategia, utilizada por empresas como Google, utiliza ramas de vida muy corta para gestionar los cambios en lugar de que los desarrolladores hagan commits directamente en el tronco.

¿En qué Consiste TBD con SLB?

En TBD con SLB, la práctica central es que los desarrolladores no hacen commits directos sobre la rama principal o tronco. En su lugar, trabajan en ramas dedicadas y de muy corta duración. Estas ramas, llamadas ramas de vida corta (short-lived branches), duran muy poco tiempo, idealmente menos de 3 días, y como máximo 3 días. Incluso, pueden contener un solo commit. Una vez que la tarea o funcionalidad de la rama está terminada y lista, se integra de nuevo al tronco mediante un merge back, y la rama de vida corta se elimina.

Implementación Paso a Paso (Desarrollo de Nuevas Funcionalidades)

La implementación de TBD con SLB para añadir o modificar funcionalidades sigue un ciclo bien definido. Suponiendo que la rama principal se llama main (puede ser master en repositorios antiguos).

1. Creación de Ramas de Vida Corta

Cada vez que un desarrollador inicia una nueva tarea, debe crear una nueva rama de desarrollo de vida corta. Esta rama se crea a partir de la última versión del tronco (main). Es crucial asegurarse de que tu copia local del tronco esté actualizada antes de crear la rama.

Comandos Git:

# Asegúrate de estar en la rama principal (trunk)
git checkout main
# Descarga los últimos cambios del tronco remoto
git pull origin main
# Crea una nueva rama de vida corta basada en el tronco actual
# Reemplaza 'feature/nombre-tarea' con un nombre descriptivo para tu tarea
git checkout -b feature/nombre-tarea

image

Ilustración: La rama feature/nombre-tarea se crea a partir del último commit en main (representado por los commits existentes C1 y C2 en main).

codigo mermaid

    gitGraph
        commit id: "C1"
        commit id: "C2"
        branch feature/nombre-tarea
        checkout feature/nombre-tarea
  

2. Desarrollo y Commits Locales

El desarrollador trabaja sobre su rama recién creada y realiza los commits necesarios con sus cambios, trabajando a su propio ritmo.

Comandos Git:

# Realiza cambios en tus archivos...
# Por ejemplo, crea o modifica un archivo: touch nuevo-archivo.txt
# Agrega los cambios al área de staging
git add .
# Realiza un commit con un mensaje descriptivo
git commit -m "Implementa la funcionalidad X"
# Repite los pasos add/commit según sea necesario mientras trabajas en la tarea

image

Ilustración: Nuevos commits (F1, F2) se añaden a la rama feature/nombre-tarea, mientras main permanece inalterada.

codigo mermaid

    gitGraph
        commit id: "C1"
        commit id: "C2"
        branch feature/nombre-tarea
        checkout feature/nombre-tarea
        commit id: "F1"
        commit id: "F2"
  

3. Sincronización con el Tronco (Previo al Merge)

Antes de preparar la integración de los cambios, es esencial que la rama local del desarrollador esté actualizada con los últimos cambios que ya se encuentran en el tronco. Esto se logra descargando los cambios del tronco y aplicándolos a tu rama, típicamente usando merge o rebase. rebase es a menudo preferido en TBD para mantener un historial más lineal.

Comandos Git (Usando Rebase - Preferido en TBD para historial limpio):

# Asegúrate de que tu tronco local esté actualizado
git checkout main
git pull origin main
# Vuelve a tu rama de trabajo
git checkout feature/nombre-tarea
# Rebase tu rama sobre el tronco actualizado
# Esto reescribe el historial de tu rama para que parezca que tus cambios
# se hicieron después de los últimos cambios del tronco
git rebase main

Comandos Git (Usando Merge - Alternativa):

# Asegúrate de que tu tronco local esté actualizado
git checkout main
git pull origin main
# Vuelve a tu rama de trabajo
git checkout feature/nombre-tarea
# Fusiona los cambios del tronco en tu rama
# Esto crea un commit de merge si hay cambios en el tronco
git merge main

image

Ilustración: main ha avanzado con C3. El merge crea un nuevo commit (M) en feature/nombre-tarea que combina los cambios de main y los de la rama feature.

codigo mermaid

    gitGraph
        commit id: "C1"
        commit id: "C2"
        branch feature/nombre-tarea
        commit id: "F1"
        commit id: "F2"
        checkout main
        commit id: "C3" 
        checkout feature/nombre-tarea
        merge main id: "M"
  

4. Creación de un Pull Request (PR)

Una vez que los cambios están completos, la rama está sincronizada y lista para integrarse, el desarrollador crea un Pull Request (PR) dirigido al tronco (main). Este paso generalmente se realiza a través de la interfaz web de la plataforma de gestión de código (GitHub, GitLab, Bitbucket, Azure DevOps, etc.), después de haber subido la rama local al repositorio remoto.

Comandos Git (para subir la rama antes del PR):

# Sube tu rama de vida corta al repositorio remoto
# La opción -u (o --set-upstream-to) configura el seguimiento remoto
git push -u origin feature/nombre-tarea

5. Revisión de Código y Pruebas Automáticas Pre-Merge

El uso de PRs es una característica distintiva y ventajosa del TBD con SLB. Permite la revisión de código por otros miembros del equipo y, crucialmente, habilita la ejecución de pruebas automáticas antes de que se realice el merge. Esto es una diferencia significativa con el TBD tradicional, donde las pruebas automáticas a menudo se realizan después del merge. La ventaja clave es que evita que commits con errores lleguen al tronco. Este paso es un proceso que ocurre en la plataforma de código, no un comando Git ejecutado por el usuario para realizar la revisión o las pruebas, aunque los revisores pueden descargar la rama si necesitan probar localmente.

6. Merge al Tronco y Eliminación de la Rama

Si el PR es aprobado (por revisores) y las pruebas automáticas pasan, los cambios de la rama de vida corta se integran al tronco (main) mediante un merge (generalmente completando el PR en la plataforma). Posteriormente, la rama de vida corta es eliminada. Todo desarrollo futuro para nuevas tareas siempre empieza creando una nueva rama de vida corta desde el tronco.

image

codigo mermaid

   gitGraph
        commit id: "C1"
        commit id: "C2"
        branch feature/nombre-tarea
        commit id: "F1"
        commit id: "F2"
        checkout main
        commit id: "C3" 
        checkout feature/nombre-tarea
        merge main id: "M"
        checkout main
        merge feature/nombre-tarea
  

Comandos Git (Después de completar el PR en la plataforma):

# Vuelve al tronco local
git checkout main
# Asegúrate de tener el último estado del tronco (que ahora incluye el merge)
git pull origin main
# Elimina la rama de vida corta localmente (usa -D para forzar si no se ha mergeado, -d es seguro)
git branch -d feature/nombre-tarea
# Elimina la rama de vida corta del repositorio remoto
git push origin --delete feature/nombre-tarea

image

codigo mermaid

   gitGraph
        commit id: "C1"
        commit id: "C2"
        commit id: "C3"
        commit id: "T1" tag: "merge tarea 1" 
  

Cómo se Gestionan los Releases (Versiones para Producción)

Una parte fundamental del versionamiento es la gestión de las liberaciones de software (releases) a entornos productivos. En el TBD con SLB, el manejo de las ramas de release es directo y se deriva del tronco:

  • Creación de la Rama de Release: Cuando el estado actual del tronco (main) se considera listo para ser liberado como una nueva versión, simplemente se crea una nueva rama a partir de ese punto.
  • Denominación y Uso: Esta nueva rama se nombra típicamente con el número de la versión que se va a lanzar (por ejemplo, release/1.0.0). Esta rama de versión es la que se utiliza para ser desplegada en producción. Es la línea base a partir de la cual se gestionarán los despliegues y, si es necesario, las correcciones de bugs específicos de esa versión. El tronco (main) sigue siendo la rama activa para el desarrollo de nuevas funcionalidades.

Comandos Git:

# Asegúrate de estar en el tronco y que esté actualizado
git checkout main
git pull origin main
# Crea la rama de release a partir del tronco actual
# Reemplaza 'release/1.0.0' con el nombre de tu versión
git checkout -b release/1.0.0
# Opcional pero recomendado: Etiqueta este punto para una referencia clara de la versión
git tag v1.0.0 release/1.0.0
# Sube la rama de release y la etiqueta al remoto
git push -u origin release/1.0.0
git push origin v1.0.0

image

Ilustración: Se crea la rama release/1.0.0 (y potencialmente se etiqueta v1.0.0) a partir de un commit específico en main (C5). main continúa para el desarrollo futuro.

codigo mermaid

   gitGraph
        commit id: "C1"
        commit id: "C2"
        commit id: "C3"
        commit id: "T1" tag: "merge tarea 1" 
  

Escenarios para Solucionar Bugs en Producción

Los bugs que se descubren en una versión ya desplegada en producción (es decir, en la rama de Release) deben manejarse cuidadosamente para mantener la coherencia con la metodología TBD y la integridad del tronco. La forma de proceder depende de si el error aún se puede reproducir en la versión actual del tronco.

Escenario 1: El Bug Sigue Existiendo en el Tronco (Preferido)

Este es el escenario recomendado y se alinea con la práctica de empresas como Google. Se corrige el bug en el tronco y luego se “trasplanta” esa corrección a la rama de Release.

  1. Verificar el Bug en el Tronco: Se confirma que el error se puede replicar en la versión actual del tronco (main). (Esto es una verificación manual o automatizada, no un comando Git).

  2. Crear Rama de Vida Corta desde el Tronco: Se crea una nueva rama de vida corta específicamente para el bug fix, partiendo directamente del tronco.

Comandos Git:

# Asegúrate de estar en el tronco y actualizado
git checkout main
git pull origin main
# Crea la rama para el bug fix desde el tronco
git checkout -b bugfix/nombre-bug-en-produccion
  1. Solucionar el Bug: El bug se corrige en esta nueva rama de vida corta.

Comandos Git:

# Realiza los cambios para corregir el bug...
# Agrega y realiza el commit
git add .
git commit -m "Fix: Corrige el bug X reportado en v1.0.0 (también presente en main)"
  1. Merge del Bug Fix al Tronco: El commit que contiene la solución del bug se integra de vuelta al tronco (main). Esto se hace mediante el proceso habitual de TBD con SLB (usando un PR).

Comandos Git (Después de completar el PR en la plataforma):

# Sube la rama con el bug fix
git push -u origin bugfix/nombre-bug-en-produccion
# Crea un PR en la plataforma de 'bugfix/nombre-bug-en-produccion' a 'main'
# ... (Una vez aprobado y mergeado) ...
# Vuelve al tronco local y actalízalo
git checkout main
git pull origin main
  1. Cherry Pick a la Rama de Release: Finalmente, se realiza un Cherry Pick del commit específico que contiene el bug fix (el commit B1 original o el merge commit M_B1, aunque B1 es más limpio para cherry-pick) desde el tronco (main) hacia la rama de la versión en producción (la rama release/1.0.0 donde se encontró el bug).

Comandos Git:

# Identifica el hash del commit de bug fix en el tronco (ej: el commit B1 original o M_B1)
# Puedes usar 'git log main' para encontrarlo
# Vuelve a la rama de release
git checkout release/1.0.0
# Aplica el commit de bug fix desde el tronco a esta rama
# Reemplaza <commit-hash-del-bugfix> con el hash real
git cherry-pick <commit-hash-del-bugfix>
# Sube la rama de release actualizada al remoto
git push origin release/1.0.0

image

codigo mermaid

    gitGraph
        commit id: "C1"
        commit id: "C2"
        commit id: "C3"
        commit id: "T1"
        branch release/1.0.0
        checkout release/1.0.0
        commit id: "R1" tag: "v1.0.0"
        checkout main
        commit id: "C4"
        commit id: "C5"
        branch bugfix/nombre-bug-en-produccion
        checkout bugfix/nombre-bug-en-produccion
        commit id: "B1" tag: "Bugfix Commit"
        checkout main
        merge bugfix/nombre-bug-en-produccion id: "M_B1" tag: "Bugfix on Main"
        checkout release/1.0.0
        cherry-pick id:"M_B1" parent:"B1" tag:"v1.0.1"
  

Este proceso, aunque involucra más pasos (crear rama, merge al tronco, cherry pick a la rama de Release), garantiza que solo el bug fix se incorpore a la versión de producción. Es la forma de respetar el contrato del Trunk Based Development y asegurar que el tronco sigue siendo la fuente principal de verdad. El desarrollo normal de nuevas funcionalidades continúa siempre en nuevas ramas de vida corta creadas a partir del tronco. Google utiliza este enfoque: las soluciones de bugs para un release se desarrollan en la línea principal y luego se hace un cherry pick a la rama de release.

Escenario 2: El Bug NO Sigue Existiendo en el Tronco (Menos Sugerido)

Este escenario es menos común y no es el recomendado por los expertos en TBD. Ocurre si el bug ya fue corregido en el tronco por un commit que, sin embargo, incluye otras funcionalidades que no deben ir a la rama de Release actual, lo que impide crear la rama de bug fix desde el tronco.

  1. Verificar el Bug y el Tronco: Se confirma que el bug no es replicable en el tronco, pero la solución en el tronco está ligada a otros cambios no deseados en la versión de producción. (Verificación manual/automatizada).

  2. Crear Rama de Vida Corta desde la Rama de Release: En esta situación excepcional, se crea una rama de vida corta desde la rama de la versión en producción (la rama release/1.0.0).

Comandos Git:

# Asegúrate de estar en la rama de release y actualizada
git checkout release/1.0.0
git pull origin release/1.0.0
# Crea la rama para el hotfix directamente desde la rama de release
git checkout -b hotfix/nombre-bug-solo-en-v1.0.0
  1. Solucionar el Bug: El bug se corrige en esta rama creada directamente desde la rama de Release.

Comandos Git:

# Realiza los cambios para corregir el bug...
# Agrega y realiza el commit
git add .
git commit -m "Hotfix: Corrige el bug Y específicamente en v1.0.0"
  1. Merge del Bug Fix a la Rama de Release: Se integra el bug fix de vuelta a la rama de la versión en producción (release/1.0.0) mediante un merge (idealmente vía PR). La solución está ahora en la versión que la necesita.

Comandos Git (Después de completar el PR en la plataforma):

# Sube la rama con el hotfix
git push -u origin hotfix/nombre-bug-solo-en-v1.0.0
# Crea un PR en la plataforma de 'hotfix/nombre-bug-solo-en-v1.0.0' a 'release/1.0.0'
# ... (Una vez aprobado y mergeado) ...
# Vuelve a la rama de release local y actualízala
git checkout release/1.0.0
git pull origin release/1.0.0
# La rama hotfix/nombre-bug-solo-en-v1.0.0 ahora se eliminaría
  1. Merge de la Rama de Release al Tronco: Por último, se integra la rama de la versión en producción actualizada (release/1.0.0) de vuelta al tronco (main). Esto es crucial para asegurar que la corrección hecha en la rama de Release también se refleje en el tronco, evitando la divergencia y que el mismo bug reaparezca en futuras versiones creadas desde main.

Comandos Git:

# Asegúrate de estar en el tronco y actualizado
git checkout main
git pull origin main
# Fusiona la rama de release (ahora con el hotfix) en el tronco
git merge release/1.0.0
# Sube el tronco actualizado al remoto
git push origin main

image

codigo mermaid

    gitGraph
        commit id: "C1"
        commit id: "C2"
        commit id: "C3"
        commit id: "T1"
        branch release/1.0.0
        checkout release/1.0.0
        commit id: "R1" tag: "v1.0.0"
        checkout main
        commit id: "C4"
        commit id: "C5"
        checkout release/1.0.0
        branch bugfix/nombre-bug-en-produccion
        checkout bugfix/nombre-bug-en-produccion
        commit id: "B1" tag: "Bugfix Commit"
        checkout release/1.0.0
        merge bugfix/nombre-bug-en-produccion id:"M_B1" tag: "v1.0.1"
        checkout main
        cherry-pick id:"M_B1" parent:"B1"
  

Este escenario invierte el flujo habitual de los cambios. Una vez completado este proceso, el desarrollo continúa siempre en nuevas ramas de vida corta creadas desde el tronco.

Características Clave y Beneficios del TBD con SLB

El TBD con SLB se define por las siguientes características y aporta importantes beneficios:

  • Ramas de Vida Corta: Las ramas de desarrollo duran muy poco, idealmente menos de 4 horas y un máximo de 3 días.
  • Uso de Pull Requests: La integración de cambios al tronco se realiza exclusivamente a través de PRs, lo que trae consigo sus beneficios.
  • Pruebas Automáticas Pre-Merge: Permite la ejecución de pruebas automatizadas antes de fusionar los cambios al tronco, lo que mejora significativamente la estabilidad del tronco al prevenir que lleguen commits con errores.
  • Evita “Merge Hell”: Al trabajar con ramas pequeñas e integrar cambios con mucha frecuencia, se minimizan los conflictos de merge dolorosos que son comunes con ramas de vida larga.
  • Soporte para Versionamiento: Se gestionan versiones creando ramas de Release a partir del tronco.
  • Escalabilidad: Es una variante escalable del TBD, siendo muy adecuada para equipos grandes con más de seis desarrolladores.
  • Alineación con Prácticas de Grandes Empresas: Es una estrategia utilizada por compañías como Google, donde el desarrollo en ramas (excepto para releases) es inusual y las ramas de vida larga son extremadamente raras.

Conclusión

Implementar Trunk Based Development con Ramas de Vida Corta es una estrategia de versionamiento robusta, profesional y altamente escalable que se adapta bien a equipos de desarrollo grandes. Al basarse en la creación, el trabajo y la rápida fusión (vía PR y con pruebas pre-merge) de ramas muy pequeñas, esta metodología mantiene el tronco (master o main) en un estado más estable y listo para ser desplegado en cualquier momento. Aunque la gestión de bug fixes para versiones en producción requiere un proceso específico (preferiblemente el escenario 1, con Cherry Pick desde el tronco a la rama de Release), el flujo de trabajo general simplifica la integración continua, reduce drásticamente los conflictos de fusión (merge hell) y facilita un ritmo de desarrollo ágil y confiable. Su adopción por grandes empresas como Google subraya su eficacia y solidez como una práctica de versionamiento moderna y eficiente.

Related Posts

Desarrollo de Software Implementando Gitflow

Desarrollo de Software Implementando Gitflow

Introducción El desarrollo de software requiere metodologías y flujos de trabajo que permitan un control eficiente del código fuente. Uno de los enfoques más utilizados para la gestión de versiones

Leer más
Gitea: Cómo Montar tu Propio Servidor Git en Minutos

Gitea: Cómo Montar tu Propio Servidor Git en Minutos

A medida que los proyectos crecen y se diversifican, muchos desarrolladores empiezan a preguntarse si realmente necesitan depender de plataformas como GitHub o GitLab para gestionar su código. No es q

Leer más
Observabilidad de Servidores y Contenedores Docker: Una Mirada Práctica con Prometheus, Grafana y cAdvisor

Observabilidad de Servidores y Contenedores Docker: Una Mirada Práctica con Prometheus, Grafana y cAdvisor

En el mundo de la infraestructura moderna, especialmente con la creciente adopción de contenedores y arquitecturas distribuidas, entender qué está sucediendo dentro de nuestros sistemas en tiempo real

Leer más
Docker: La Revolución que Empaquetó tu Código

Docker: La Revolución que Empaquetó tu Código

En el dinámico mundo del desarrollo y la infraestructura de tecnologías de la información, la necesidad de empaquetar, distribuir y ejecutar aplicaciones de forma consistente ha llevado a la populariz

Leer más
Exploración Profunda de Kubernetes: Componentes Clave y Principios Fundamentales

Exploración Profunda de Kubernetes: Componentes Clave y Principios Fundamentales

En el panorama tecnológico actual, caracterizado por arquitecturas de microservicios y despliegues en la nube, la gestión efectiva de aplicaciones contenedorizadas es un desafío crítico. Kubernetes su

Leer más
Convención de Nombres en Clases Java: Mejora de Legibilidad y Mantenibilidad

Convención de Nombres en Clases Java: Mejora de Legibilidad y Mantenibilidad

En proyectos de gran escala, identificar rápidamente el tipo de una clase facilita la comprensión del código, la colaboración y la depuración. Sin un esquema de nombres estandarizado, es común que los

Leer más
Estructuración de Carpetas en Proyectos de Software

Estructuración de Carpetas en Proyectos de Software

En proyectos de software de gran escala, la falta de una estructura de carpetas bien definida puede generar desorden, dificultando la mantenibilidad, escalabilidad y comprensión del código. Muchas vec

Leer más
Descubre el Poder del SemVer: Optimiza el Versionado de tu Software y Mantén un CHANGELOG Excepcional

Descubre el Poder del SemVer: Optimiza el Versionado de tu Software y Mantén un CHANGELOG Excepcional

El Versionado Semántico (SemVer) es una herramienta fundamental para comunicar de forma precisa los cambios en el software, facilitando el mantenimiento y la colaboración. Complementarlo con un **

Leer más
Estándar de Codificación y Gestión de Errores en Arquitecturas de Microservicios

Estándar de Codificación y Gestión de Errores en Arquitecturas de Microservicios

En el ecosistema de aplicaciones web modernas, la arquitectura de microservicios distribuidos se ha consolidado como un paradigma dominante. Su flexibilidad, escalabilidad y resiliencia son innegables

Leer más
Arquitectura DDD y Hexagonal: Construyendo Software para el Futuro

Arquitectura DDD y Hexagonal: Construyendo Software para el Futuro

En el dinámico mundo del desarrollo de software, la complejidad es el enemigo silencioso. Las aplicaciones crecen, los requisitos cambian y, sin una guía clara, el código puede convertirse rápidamente

Leer más
Manejando el Caos: Una Guía Definitiva sobre Excepciones de Dominio 🎯

Manejando el Caos: Una Guía Definitiva sobre Excepciones de Dominio 🎯

En el desarrollo de software moderno, escribir código que funciona perfectamente en escenarios ideales es solo el primer paso. La verdadera fortaleza de un sistema se manifiesta cuando debe enfrentar

Leer más
El Arte de Conectar: Forjando un DataSource Dinámico en Spring Boot

El Arte de Conectar: Forjando un DataSource Dinámico en Spring Boot

En el vertiginoso universo del desarrollo de software, donde la seguridad es un pilar innegociable y la agilidad es la moneda de cambio, nos enfrentamos a desafíos que van más allá de la simple lógica

Leer más