GitHub Flow

Problemas con git-flow

Viajo por todas partes enseñando Git a la gente y en casi todas las clases y talleres que he hecho recientemente me han preguntado qué pienso de git-flow. Siempre respondo que creo que es genial – ha tomado un sistema (Git) que tiene un millón de flujos de trabajo posibles y ha documentado un flujo de trabajo bien probado y flexible que funciona para muchos desarrolladores de una manera bastante sencilla. Se ha convertido en una especie de estándar para que los desarrolladores puedan moverse entre proyectos o empresas y estar familiarizados con este flujo de trabajo estandarizado.

Sin embargo, tiene sus problemas. He oído una serie de opiniones de la gente a lo largo de las líneas de no gustar que las nuevas ramas de características se inician fuera de develop en lugar de master, o la forma en que maneja hotfixes, pero esos son bastante menores.

Uno de los mayores problemas para mí es que es más complicado de lo que creo que la mayoría de los desarrolladores y equipos de desarrollo realmente requieren. Es lo suficientemente complicado que un gran script de ayuda fue desarrollado para ayudar a hacer cumplir el flujo. Aunque esto es genial, el problema es que no se puede aplicar en una GUI de Git, sólo en la línea de comandos, por lo que las únicas personas que tienen que aprender el complejo flujo de trabajo realmente bien, porque tienen que hacer todos los pasos manualmente, son las mismas personas que no se sienten lo suficientemente cómodas con el sistema para usarlo desde la línea de comandos. Esto puede ser un gran problema.

Ambos problemas pueden ser resueltos fácilmente con sólo tener un proceso mucho más simplificado. En GitHub, no usamos git-flow. Utilizamos, y siempre hemos utilizado, un flujo de trabajo Git mucho más simple.

Su simplicidad le da una serie de ventajas. Una de ellas es que es fácil de entender para la gente, lo que significa que pueden aprender rápidamente y que rara vez, o nunca, lo estropean o tienen que deshacer los pasos que hicieron mal. Otra es que no necesitamos un script envolvente para ayudar a aplicarlo o seguirlo, por lo que el uso de GUIs y demás no es un problema.

GitHub Flow

Entonces, ¿por qué no usamos git-flow en GitHub? Bueno, la cuestión principal es que desplegamos todo el tiempo. El proceso de git-flow está diseñado en gran medida en torno a la «liberación». En realidad no tenemos «releases» porque desplegamos a producción todos los días, a menudo varias veces al día. Podemos hacerlo a través de nuestro robot de la sala de chat, que es el mismo lugar donde se muestran nuestros resultados de CI. Intentamos que el proceso de pruebas y envíos sea lo más sencillo posible para que todos los empleados se sientan cómodos haciéndolo.

Hay una serie de ventajas en desplegar con tanta regularidad. Si se despliega cada pocas horas, es casi imposible introducir un gran número de grandes errores. Se pueden introducir pequeños problemas, pero entonces se pueden arreglar y volver a desplegar muy rápidamente. Normalmente habría que hacer un ‘hotfix’ o algo fuera del proceso normal, pero es simplemente parte de nuestro proceso normal – no hay diferencia en el flujo de GitHub entre un hotfix y una característica muy pequeña.

Otra ventaja de desplegar todo el tiempo es la capacidad de abordar rápidamente los problemas de todo tipo. Podemos responder a los problemas de seguridad que se nos plantean o implementar peticiones de características pequeñas pero interesantes con increíble rapidez, y sin embargo podemos utilizar exactamente el mismo proceso para abordar esos cambios que para manejar el desarrollo de características normales o incluso grandes. Es el mismo proceso y es muy sencillo.

Cómo lo hacemos

Entonces, ¿qué es GitHub Flow?

  • Todo lo que esté en la rama master es desplegable
  • Para trabajar en algo nuevo, crea una rama con nombre descriptivo fuera de master (ie: new-oauth2-scopes)
  • Comprométase con esa rama localmente y empuje regularmente su trabajo a la misma rama con nombre en el servidor
  • Cuando necesite retroalimentación o ayuda, o crea que la rama está lista para ser fusionada, abrir una solicitud de extracción
  • Después de que alguien más ha revisado y firmado en la característica, se puede fusionar en el maestro
  • Una vez que se fusiona y empujó a ‘maestro’, usted puede y debe desplegar inmediatamente

Ese es el flujo completo. Es muy simple, muy eficaz y funciona para equipos bastante grandes – GitHub es 35 empleados ahora, tal vez 15-20 de los cuales trabajan en el mismo proyecto (github.com) al mismo tiempo. Creo que la mayoría de los equipos de desarrollo -grupos que trabajan en el mismo código lógico al mismo tiempo lo que podría producir conflictos- son alrededor de este tamaño o más pequeños. Especialmente aquellos que son lo suficientemente progresivos como para estar haciendo despliegues rápidos y consistentes.

Así que, vamos a ver cada uno de estos pasos a su vez.

#1 – cualquier cosa en la rama maestra es desplegable

Esta es básicamente la única regla dura del sistema. Sólo hay una rama que tiene un significado específico y consistente y la llamamos master. Para nosotros, esto significa que se ha desplegado o, en el peor de los casos, se desplegará en cuestión de horas. Es increíblemente raro que esto se rebobine (la rama se mueve hacia atrás a un commit anterior para revertir el trabajo) – si hay un problema, se revertirán los commits o se introducirán nuevos commits que solucionen el problema, pero la rama en sí casi nunca se rebobina.

La rama master es estable y siempre, siempre es seguro desplegar desde ella o crear nuevas ramas a partir de ella. Si empujas algo a master que no está probado o rompe la construcción, rompes el contrato social del equipo de desarrollo y normalmente te sientes bastante mal por ello. Cada rama que empujamos tiene pruebas ejecutadas en ella y reportadas en la sala de chat, así que si no las has ejecutado localmente, puedes simplemente empujar a una rama temática (incluso una rama con un solo commit) en el servidor y esperar a que Jenkins te diga si pasa todo.

Podrías tener una rama deployed que se actualiza sólo cuando despliegas, pero no hacemos eso. Simplemente exponemos el SHA actualmente desplegado a través de la propia webapp y curl si necesitamos que se haga una comparación.

#2 – crear ramas descriptivas fuera de master

Cuando quieres empezar a trabajar en algo, creas una rama con nombre descriptivo fuera de la rama estable master. Algunos ejemplos en la base de código de GitHub ahora mismo serían user-content-cache-key, submodules-init-task o redis2-transition. Esto tiene varias ventajas – una es que cuando se obtiene, se puede ver los temas que todo el mundo ha estado trabajando. Otra es que si abandonas una rama durante un tiempo y vuelves a ella más tarde, es bastante fácil recordar cuál era.

Esto está bien porque cuando vamos a la página de la lista de ramas de GitHub podemos ver fácilmente en qué ramas se ha trabajado recientemente y aproximadamente cuánto trabajo tienen.

Lista de ramas de Github

Es casi como una lista de próximas características con el estado actual aproximado. Esta página es impresionante si no la estás usando – sólo te muestra las ramas que tienen trabajo único en ellas en relación con tu rama actualmente seleccionada y las ordena de manera que las más recientemente trabajadas están en la parte superior. Si tengo mucha curiosidad, puedo hacer clic en el botón ‘Comparar’ para ver cuál es el diff unificado real y la lista de commit que es única para esa rama.

Así que, en el momento de escribir esto, tenemos 44 ramas en nuestro repositorio con trabajo no fusionado en ellas, pero también puedo ver que sólo alrededor de 9 o 10 de ellas han sido empujadas en la última semana.

#3 – empujar a las ramas con nombre constantemente

Otra gran diferencia con git-flow es que empujamos a las ramas con nombre en el servidor constantemente. Dado que la única cosa que realmente tenemos que preocuparnos es master desde un punto de vista de despliegue, empujando al servidor no se desordena a nadie o confundir las cosas – todo lo que no es master es simplemente algo que se está trabajando.

También asegurarse de que nuestro trabajo es siempre una copia de seguridad en caso de pérdida de la computadora portátil o fallo del disco duro. Y lo que es más importante, pone a todos en constante comunicación. Un simple ‘git fetch’ básicamente le dará una lista de tareas pendientes de lo que cada uno está trabajando actualmente.

$ git fetchremote: Counting objects: 3032, done.remote: Compressing objects: 100% (947/947), done.remote: Total 2672 (delta 1993), reused 2328 (delta 1689)Receiving objects: 100% (2672/2672), 16.45 MiB | 1.04 MiB/s, done.Resolving deltas: 100% (1993/1993), completed with 213 local objects.From github.com:github/github * charlock-linguist -> origin/charlock-linguist * enterprise-non-config -> origin/enterprise-non-config * fi-signup -> origin/fi-signup 2647a42..4d6d2c2 git-http-server -> origin/git-http-server * knyle-style-commits -> origin/knyle-style-commits 157d2b0..d33e00d master -> origin/master * menu-behavior-act-i -> origin/menu-behavior-act-i ea1c5e2..dfd315a no-inline-js-config -> origin/no-inline-js-config * svg-tests -> origin/svg-tests 87bb870..9da23f3 view-modes -> origin/view-modes * wild-renaming -> origin/wild-renaming

También permite a todos ver, mirando a la página de la lista de rama de GitHub, lo que todo el mundo está trabajando en lo que pueden inspeccionar y ver si quieren ayudar con algo.

#4 – abrir una solicitud de extracción en cualquier momento

GitHub tiene un sistema de revisión de código increíble llamado Pull Requests que me temo que no hay suficiente gente sabe acerca. Mucha gente lo utiliza para el trabajo de código abierto – bifurcar un proyecto, actualizar el proyecto, enviar un pull request al mantenedor. Sin embargo, también puede ser fácilmente utilizado como un sistema de revisión de código interno, que es lo que hacemos.

En realidad, lo usamos más como una vista de conversación de la rama más que una solicitud de extracción. Usted puede enviar solicitudes de extracción de una rama a otra en un solo proyecto (público o privado) en GitHub, por lo que puede utilizarlos para decir «Necesito ayuda o revisión en esto», además de «Por favor, fusionar esto en».

mensaje temprano pr

Aquí se puede ver Josh cc’ing Brian para la revisión y Brian viene con algunos consejos sobre una de las líneas de código. Más abajo podemos ver a Josh reconociendo las preocupaciones de Brian y empujando más código para abordarlas.

más discusión

Finalmente se puede ver que todavía estamos en la fase de prueba – esto no es una rama lista para el despliegue todavía, utilizamos los Pull Requests para revisar el código mucho antes de que realmente queramos fusionarlo en master para el despliegue.

Si estás atascado en el progreso de tu característica o rama y necesitas ayuda o consejo, o si eres un desarrollador y necesitas que un diseñador revise tu trabajo (o viceversa), o incluso si tienes poco o nada de código pero algunas capturas de pantalla o ideas generales, abre un pull request. Usted puede citar a la gente en el sistema de GitHub mediante la adición de un @nombre de usuario, así que si usted quiere la revisión o la retroalimentación de las personas específicas, sólo tiene que citarlos en el mensaje de PR (como viste Josh hacer arriba).

Esto es genial porque la función de solicitud de extracción le permite comentar sobre las líneas individuales en el diff unificado, en los commits individuales o en la propia solicitud de extracción y tira de todo en línea a una sola vista de la conversación.También te permite seguir empujando a la rama, por lo que si alguien comenta que te olvidaste de hacer algo o hay un error en el código, puedes arreglarlo y empujar a la rama, GitHub mostrará los nuevos commits en la vista de conversación y puedes seguir iterando en una rama como esa.

Si la rama ha estado abierta durante demasiado tiempo y sientes que se está desincronizando con la rama maestra, puedes fusionar la maestra en tu rama temática y seguir adelante. Puedes ver fácilmente en la discusión del pull request o en la lista de commits cuando la rama se actualizó por última vez con la ‘master’.

master merge

Cuando todo está real y verdaderamente hecho en la rama y sientes que está lista para desplegar, puedes pasar al siguiente paso.

#5 – fusionar sólo después de la revisión del pull request

No nos limitamos a hacer el trabajo directamente en master o trabajar en una rama temática y fusionarla cuando creemos que está hecho – tratamos de obtener la firma de alguien más en la empresa. Esto es generalmente un +1 o emoji o «:shipit:» comentario, pero tratamos de conseguir que alguien más lo vea.

shipit comentario

Una vez que conseguimos eso, y la rama pasa CI, podemos fusionarlo en master para el despliegue, que cerrará automáticamente el Pull Request cuando lo empujamos.

#6 – desplegar inmediatamente después de la revisión

Finalmente, su trabajo está hecho y fusionado en la rama master. Esto significa que aunque no lo despliegues ahora, la gente basará el nuevo trabajo en él y el próximo despliegue, que probablemente ocurrirá en unas horas, lo empujará. Así que como realmente no quieres que otra persona empuje algo que escribiste que rompe cosas, la gente tiende a asegurarse de que realmente es estable cuando se fusiona y la gente también tiende a empujar sus propios cambios.

Nuestro bot campfire, hubot, puede hacer despliegues para cualquiera de los empleados, por lo que un simple:

hubot depoy github to production

desplegará el código y el tiempo de inactividad cero reiniciar todos los procesos necesarios. Puedes ver lo común que es esto en GitHub:

nuestros registros de campfire

Puedes ver a 6 personas diferentes (incluyendo un chico de soporte y un diseñador) desplegando unas 24 veces en un día.

He hecho esto para ramas con un commit que contiene un cambio de una línea. El proceso es simple, directo, escalable y poderoso. Usted puede hacerlo con ramas de características con 50 commits en ellos que tomaron 2 semanas, o 1 commit que tomó 10 minutos. Es un proceso tan simple y sin fricción que no te molesta tener que hacerlo incluso para 1 commit, lo que significa que la gente rara vez trata de saltarse o evitar el proceso a menos que el cambio sea tan pequeño o insignificante que simplemente no importa.

Este es un proceso increíblemente simple y poderoso. Creo que la mayoría de la gente estaría de acuerdo en que GitHub tiene una plataforma muy estable, que los problemas se abordan rápidamente si alguna vez surgen, y que las nuevas características se introducen a un ritmo rápido. No se compromete la calidad o la estabilidad para que podamos obtener más velocidad o simplicidad o menos proceso.

Conclusión

Git en sí mismo es bastante complejo de entender, hacer que el flujo de trabajo que se utiliza con él sea más complejo de lo necesario es simplemente añadir más sobrecarga mental al día de todos. Yo siempre abogaría por utilizar el sistema más simple posible que funcione para su equipo y hacerlo hasta que no funcione más y luego añadir la complejidad sólo cuando sea absolutamente necesario.

Para los equipos que tienen que hacer lanzamientos formales en un intervalo de tiempo más largo (unas pocas semanas a unos pocos meses entre los lanzamientos), y ser capaz de hacer hot-fixes y ramas de mantenimiento y otras cosas que surgen de envío con tan poca frecuencia, git-flow tiene sentido y yo abogaría por su uso.

Para los equipos que han establecido una cultura de envío, que empujan a la producción todos los días, que están constantemente probando y desplegando, yo abogaría por elegir algo más simple como GitHub Flow.

Leave a Reply