Este artículo es parte de nuestra serie “Advanced Git”. Asegúrate de Síguenos en Twitter o suscríbete a nuestro boletín para conocer los próximos artículos.
Casi todos los sistemas de control de versiones (VCS) tienen algún tipo de soporte para la ramificación. En pocas palabras, la ramificación significa que abandona la línea de desarrollo principal creando un nuevo contenedor separado para su trabajo y continúa trabajando allí. De esta manera, puede experimentar y probar cosas nuevas sin estropear la base del código de producción. Los usuarios de Git saben que el modelo de ramificación de Git es especial e increíblemente poderoso; es una de las características más interesantes de este VCS. Es rápido y liviano, y alternar entre las ramas es tan rápido como crearlas o eliminarlas. Se podría decir que Git fomenta los flujos de trabajo que utilizan muchas ramificaciones y fusiones.
Git te deja totalmente en tus manos la cantidad de ramas que creas y la frecuencia con la que las fusionas. Ahora, si está codificando por su cuenta, puede elegir cuándo crear una nueva rama y cuántas ramas desea conservar. Sin embargo, esto cambia cuando trabajas en equipo. Git proporciona la herramienta, ¡pero usted y su equipo son responsables de usarla de la manera óptima!
En este artículo, voy a hablar sobre estrategias de ramificación y diferentes tipos de ramificaciones de Git. También te presentaré dos flujos de trabajo de ramificación comunes: Git Flow y GitHub Flow.
Serie avanzada de Git:
- Parte 1: Creando el compromiso perfecto en Git
- Parte 2: Estrategias de ramificación en Git (¡estás aquí!)
- Parte 3: Mejor colaboración con solicitudes de extracción
- Parte 4: Fusionar conflictos
- Parte 5: Rebase vs. Fusionar
- Parte 6: Rebase interactiva
- Parte 7: Compromisos de selección de cerezas en Git
- Parte 8: Uso de Reflog para restaurar confirmaciones perdidas
Trabajo en equipo: escribe una convención
Antes de explorar diferentes formas de estructurar lanzamientos e integrar cambios, hablemos de convenciones. Si trabaja en equipo, debe acordar un flujo de trabajo común y una estrategia de ramificación para sus proyectos. Es una buena idea dejar esto por escrito para que sea accesible a todos los miembros del equipo.
Es cierto que no a todo el mundo le gusta escribir documentación o pautas, pero dejar constancia de las mejores prácticas no solo evita errores y colisiones, sino que también ayuda a la hora de incorporar nuevos miembros al equipo. Un documento que explique sus estrategias de ramificación les ayudará a comprender cómo trabaja y cómo maneja su equipo las versiones de software.
Aquí hay un par de ejemplos de nuestra propia documentación:
master
representa la rama de lanzamiento público actualnext
representa la próxima rama de lanzamiento público (de esta manera podemos enviar revisiones en el maestro sin introducir cambios no deseados)- las ramas de características se agrupan bajo
feature/
- Las ramas de WIP se agrupan bajo
wip/
(estos se pueden utilizar para crear “copias de seguridad” de su WIP personal)
Un equipo diferente puede tener una opinión diferente sobre estas cosas (por ejemplo, en los grupos “wip” o “feature”), que sin duda se reflejarán en su propia documentación.
Integración de cambios y estructuración de lanzamientos
Cuando piense en cómo trabajar con ramas en sus repositorios de Git, probablemente debería comenzar pensando en cómo integrar los cambios y cómo estructurar las versiones. Todos esos temas están estrechamente conectados. Para ayudarlo a comprender mejor sus opciones, veamos dos estrategias diferentes. Los ejemplos están destinados a ilustrar los extremos del espectro, por lo que deberían darle algunas ideas de cómo puede diseñar su propio flujo de trabajo de ramificación:
- Desarrollo de línea principal
- Ramas de estado, lanzamiento y funciones
La primera opción podría describirse como “estar siempre integrando” que básicamente se reduce a: integrar siempre tu propio trabajo con el trabajo del equipo. En la segunda estrategia, reúne su trabajo y libera una colección, es decir, varios tipos diferentes de ramas entran en escena. Ambos enfoques tienen sus pros y sus contras, y ambas estrategias pueden funcionar para algunos equipos, pero no para otros. La mayoría de los equipos de desarrollo trabajan en algún punto intermedio entre esos extremos.
Comencemos con el desarrollo principal y expliquemos cómo funciona esta estrategia.
Desarrollo de línea principal
Lo dije antes, pero el lema de este enfoque es “estar siempre integrando”. Tienes una sola rama y todos contribuyen comprometiéndose con la línea principal:
Recuerde que estamos simplificando para este ejemplo. Dudo que algún equipo en el mundo real trabaje con una estructura de ramificación tan simple. Sin embargo, ayuda a comprender las ventajas y desventajas de este modelo.
En primer lugar, solo tiene una rama, lo que facilita el seguimiento de los cambios en su proyecto. En segundo lugar, las confirmaciones deben ser relativamente pequeñas: no puede arriesgarse a confirmaciones grandes e infladas en un entorno donde las cosas se integran constantemente en el código de producción. Como resultado, las pruebas de su equipo y los estándares de control de calidad deben ser de primera categoría. Si no tiene un entorno de prueba de alta calidad, el enfoque de desarrollo principal no funcionará para usted.
Ramas de estado, lanzamiento y características
Veamos ahora lo contrario y cómo trabajar con varios tipos diferentes de ramas. Todos tienen un trabajo diferente: las nuevas funciones y el código experimental se guardan en sus propias ramas, los lanzamientos se pueden planificar y administrar en sus propias ramas, e incluso varios estados en su flujo de desarrollo se pueden representar mediante ramas:
Recuerde que todo esto depende de las necesidades de su equipo y de los requisitos de su proyecto. Si bien este enfoque puede parecer complicado al principio, todo es cuestión de práctica y de acostumbrarse.
Ahora, exploremos dos tipos principales de ramas con más detalle: ramas de larga duración y ramas de corta duración.
Ramas de larga duración
Cada repositorio de Git contiene al menos una rama de ejecución prolongada que normalmente se llama maestra o principal. Por supuesto, su equipo puede haber decidido tener otras ramas de larga duración en un proyecto, por ejemplo, algo como desarrollo, producción o puesta en escena. Todas esas ramas tienen una cosa en común: existen durante toda la vida útil de un proyecto.
Una rama de la línea principal como master o main es un ejemplo de una rama de larga duración. Además, existen las denominadas ramas de integración, como desarrollo o puesta en escena. Estas ramas suelen representar estados en el proceso de lanzamiento o implementación de un proyecto. Si su código se mueve a través de diferentes estados en su ciclo de vida de desarrollo, por ejemplo, desde el desarrollo hasta la puesta en escena y la producción, también tiene sentido reflejar esta estructura en sus ramas.
Una última cosa sobre las ramas de larga duración: la mayoría de los equipos tienen una regla como “no comprometerse directamente con una rama de larga duración”. En cambio, las confirmaciones generalmente se integran a través de una fusión o rebase. Hay dos razones principales para tal convención:
- Calidad: No se debe agregar código no probado o revisado a un entorno de producción.
- Lanzamiento de agrupación y programación: Es posible que desee publicar código nuevo en lotes e incluso programar los lanzamientos con anticipación.
A continuación: ramas de corta duración, que generalmente se crean para ciertos propósitos y luego se eliminan después de que se haya integrado el código.
Ramas de vida corta
A diferencia de las ramas de larga duración, las ramas de corta duración se crean con fines temporales. Una vez que han cumplido con su deber y el código se ha integrado en la línea principal (u otra rama de larga duración), se eliminan. Hay muchas razones diferentes para crear una rama de corta duración, por ejemplo, comenzar a trabajar en una característica nueva y experimental, corregir un error, refactorizar su código, etc.
Normalmente, una rama de corta duración se basa en una rama de larga duración. Digamos que comienza a trabajar en una nueva función de su software. Puede basar la nueva función en su rama principal de larga duración. Después de varias confirmaciones y algunas pruebas, decides que el trabajo está terminado. La nueva función se puede integrar en la rama principal y, una vez que se haya fusionado o modificado, se puede eliminar la rama de la función.
Dos estrategias de ramificación populares
En la última sección de este artículo, veamos dos estrategias de ramificación populares: Git Flow y GitHub Flow. Si bien usted y su equipo pueden decidir algo completamente diferente, puede tomarlos como inspiración para su propia estrategia de ramificación.
Git Flow
Una estrategia de ramificación muy conocida se llama Git Flow. La rama principal siempre refleja el estado de producción actual. Hay una segunda rama de larga duración, normalmente denominada desarrollar. Todas las ramas de funciones comienzan desde aquí y se fusionarán para desarrollar. Además, es el punto de partida para las nuevas versiones: los desarrolladores abren una nueva rama de la versión, trabajan en ella, la prueban y envían sus correcciones de errores en dicha rama de la versión. Una vez que todo funcione y esté seguro de que está listo para la producción, vuelva a fusionarlo en main. Como último paso, agrega una etiqueta para la confirmación de lanzamiento en main y elimina la rama de lanzamiento.
Git Flow funciona bastante bien para software empaquetado como aplicaciones (de escritorio) o bibliotecas, pero parece un poco exagerado para proyectos de sitios web. Aquí, la diferencia entre la rama principal y la rama de lanzamiento a menudo no es lo suficientemente grande como para beneficiarse de la distinción.
Si está utilizando una GUI de escritorio de Git como Tower, encontrará las posibles acciones en la interfaz y no tendrá que memorizar ningún comando nuevo:
Flujo de GitHub
Si usted y su equipo siguen el enfoque de entrega continua con ciclos de producción cortos y lanzamientos frecuentes, sugeriría mirar GitHub Flow.
Es extremadamente ágil y simple: hay una rama de larga duración, la rama principal predeterminada. Cualquier cosa en la que esté trabajando activamente tiene su propia rama separada. No importa si es una característica, una corrección de errores o una refactorización.
¿Cuál es la “mejor” estrategia de ramificación de Git?
Si le pregunta a 10 equipos diferentes cómo están usando las ramas de Git, probablemente obtendrá 10 respuestas diferentes. No existe la “mejor” estrategia de ramificación ni un flujo de trabajo perfecto que todos deban adoptar. Para encontrar el mejor modelo para usted y su equipo, deben sentarse juntos, analizar su proyecto, hablar sobre su estrategia de lanzamiento y luego decidir sobre un flujo de trabajo de ramificación que lo respalde de la mejor manera posible.
Si desea profundizar en las herramientas avanzadas de Git, no dude en consultar mi “Kit de Git avanzado” (gratuito): es una colección de videos cortos sobre temas como estrategias de ramificación, Rebase interactiva, Reflog, Submódulos y mucho más.
Serie avanzada de Git:
- Parte 1: Creando el compromiso perfecto en Git
- Parte 2: Estrategias de ramificación en Git (¡estás aquí!)
- Parte 3: Mejor colaboración con solicitudes de extracción
- Parte 4: Fusionar conflictos
- Parte 5: Rebase vs. Fusionar
- Parte 6: Rebase interactiva
- Parte 7: Compromisos de selección de cerezas en Git
- Parte 8: Uso de Reflog para restaurar confirmaciones perdidas