Toda organización que se dedique a desarrollar software debería tener un workflow, y en cuanto al versionado de código este post indica en líneas generales como hacemos para versionar, y por qué.
Alguna vez di una plática sobre Git a estudiantes de la UAM-CEUAMI acerca del control de versiones. En ella, el énfasis lo puse primero que nada en la razón de ser del versionado de código. Es la mejor manera, que hayamos inventado, para organizar el desarrollo de software para más de una persona (e incluso para una sola, si nos importa).
El versionado permite:
- conocer la historia del desarrollo de un proyecto (¿en qué momento exacto se introdujo este cambio? y más importante ¿por qué?)
- deslindar responsabilidades (ah! con que tu fuiste el que introdujo este maldito bug!)
- organizar el trabajo de un equipo (¿cómo hacemos para que este cambio mío no choque con el que tú aún estás trabajando?)
Es vital que cualquier organización que desarrolle software haga uso de una herramienta para el versionado. En PodemosTI usamos Git.
Pero, vamos, usar una herramienta no es lo mismo que usarla BIEN.
Y si de algo nos dimos cuenta es que para ello también necesitamos implementar un buen flujo de trabajo (workflow para los cuates :D )
Existen muchas formas de hacer esto, incluso algunas famosas que suelen compartirse por las redes (como esta: http://nvie.com/posts/a-successful-git-branching-model/)
Nosotros (aún) no necesitamos tanto así, por lo que buscando un modelo más adecuado nos topamos con lo que necesitábamos en otro lugar.
Battle for Wesnoth (Batalla por Wesnoth) es un juego de estrategia multiplataforma creado en 2003. Desarrollado en lenguaje C++, es un juego con licencia libre (GPL), lo cual significa que cualquiera puede acceder a su código fuente y hacer con el como le plazca (siempre bajo los lineamientos de la licencia GPL, claro está). Incluso ha formado parte de un capítulo del primer volumen del libro The Architecture of Open Source Applications (¡puedes verlo en línea aquí!)
Por lo tanto es desarrollado por muchísimas personas alrededor del mundo, y por ello también necesitan algún proceso a seguir para poder aportar colaboraciones.
En https://wiki.wesnoth.org/Git_for_Wesnoth_Crash_Course , el equipo de Battle for Wesnoth explica su proceso, incluyendo su git workflow.
Y en PodemosTI usamos algo similar:
- Mantenemos nuestros repositorios usando la fabulosa herramienta Gitlab.
- En Gitlab tenemos nuestros repositorios principales, los orígenes de cualquier proyecto versionado en git.
- Cualquiera que desee trabajar en un proyecto debe primero hacer un fork al principal, y así tener su propio repositorio en Gitlab.
- Luego el desarrollador puede hacer un
- PERO primero debe establecer un origen remoto llamado upstream en su ambiente local que apunte al proyecto principal:
- El origen llamado origin estará, por default, apuntando al fork del desarrollador. Sobre él trabajará de manera normal.
- Mientras que el upstream deberá apuntar al repositorio principal. ¿Para qué? Bueno, cuando OTRO desarrollador haga cambios y estos se liberen en el principal, el desarrollador podrá obtener estos cambios fácilmente jalándolos de upstream, manteniendo su base de código al día y resolviendo conflictos con sus cambios cuanto antes.
Esa es en términos generales la estructura con la que trabajamos nuestros repositorios. En cuanto al workflow, se puede ilustrar de la siguiente manera:
Watson es el nombre del host donde viven nuestros repositorios principales, también donde vive Gitlab.
Para cada repositorio principal existen siempre dos branches:
- Master
- Review
Master no lo toca nadie, excepto el dueño del repositorio principal en cuestión, que usualmente es el SysAdmin que funja como administrador de versiones del proyecto.
Review por otro lado es donde ocurre la mayor parte de la acción de versionado (fuera de los repositorios locales de cada desarrollador).
Como siempre, el desarrollador debe seguir buenas prácticas al usar git:
- crear un branch especial para el cambio que quiera desarrollar, en su ambiente local (su computadora usualmente). Ese branch lo puede subir a su propio fork del proyecto en Gitlab cuantas veces quiera.
- sus commits deben contener mensajes claros y bien especificados (https://chris.beams.io/posts/git-commit/)
- usar
- todos sus cambios deben llevar pruebas unitarias lo más completas posibles. Y siempre hacer Test Driven Development para trabajar (de esto también di una plática en CEUAMI, pero ya será tema de otra entrada ;-)
Cuando un desarrollador quiere liberar un cambio entonces lo sube a su fork en Gitlab, y después solicita un Merge Request al repositorio principal, al branch Review, asignándolo a otro colaborador (en principio podría ser a cualquier otro). Tenemos pendiente todavía acoplarnos para que en vez de hacer merges, se hagan fast-forward merges, que serían equivalentes a hacer un rebase.
Asignar el merge a otro colaborador distinto es de hecho y sin exagerar una de las partes MÁS VITALES de nuestro proceso. La idea detrás de esto es que se haga un peer- review del cambio, para detectar posibles errores, áreas de oportunidad, que se acople a los estándares y convenciones, etc. Y una vez que el colaborador valida que el cambio es correcto (con un posible proceso intermedio de comentarios y correcciones), se hace el merge y se procede a la liberación del cambio.
En cuanto a la liberación, es labor del administrador de versiones del proyecto hacer un
(NUNCA un
) del branch review al branch master y posteriormente algún colaborador que funja como administrador del proyecto podría liberarlo en producción.
Y ese es básicamente nuestro proceso y workflow. No mencionamos nada sobre Integración Continua ni pruebas unitarias, pero basta mencionar que Gitlab proporciona potentes herramientas para también validar programáticamente los cambios y no permitir merges a review o master si las pruebas unitarias no pasan correctamente.
Git es una herramienta potentísima para la muy necesaria administración de versiones en todo proyecto de software. Pero usarla bien implica no sólo conocerla sino también organizarnos para usarla eficientemente. Eso implica establecer un buen workflow, y claro, seguir siempre buenas prácticas.