Git workflow | Comparing workflows

Comparar workflows

 

Un flujo de trabajo de Git es una fórmula o una recomendación acerca del uso de Git para realizar trabajo de forma uniforme y productiva. Los flujos de trabajo de Git animan a los usuarios a sacar partido a Git de forma eficaz y estable. Git ofrece a los usuarios una amplia flexibilidad de gestión de cambios. Dado que Git se centra en la flexibilidad, no existe un proceso estandarizado acerca de cómo interactuar con Git. Cuando se trabaja con un equipo en un proyecto gestionado por Git, es importante asegurarse de que el equipo está de acuerdo con cómo se va a aplicar el flujo de cambios Para garantizar que todo el equipo se encuentra en sintonía, se debe desarrollar o seleccionar un flujo de trabajo de Git. Hay varios flujos de trabajo de Git publicados que pueden ser adecuados para tu equipo. Aquí hablaremos sobre algunas de estas opciones de flujo de trabajo.

La gama de flujos de trabajos posibles hace que resulte complicado saber por dónde hay que empezar a implementar Git en el lugar de trabajo. En esta página proporcionamos un punto de partida, ya que ofrecemos un análisis de los flujos de trabajo más habituales entre los equipos de software.

Ten en cuenta que estos flujos de trabajo se han diseñado a modo orientativo, en lugar de para usarlos como reglas concretas. Queremos mostrarte las posibilidades, de forma que puedas combinar y mezclar aspectos de distintos flujos de trabajo que respondan a tus necesidades.

¿Qué es un flujo de trabajo de Git exitoso?

Cuando evalúas un flujo de trabajo para tu equipo, lo más importante es que tengas en cuenta la cultura de tu equipo. Quieres que el flujo de trabajo mejore la eficacia de tu equipo, no que sea una carga que limite la productividad. Estas son algunas cosas que debes tener en cuenta a la hora de evaluar un flujo de trabajo de Git:

  • ¿Este flujo de trabajo se escala con el tamaño del equipo?
  • ¿Es fácil deshacer los errores y los fallos con este flujo de trabajo?
  • ¿Este flujo de trabajo impone excesos cognitivos sobre el equipo?

Flujo de trabajo centralizado

git workflow | Central and local repositories

El flujo de trabajo centralizado es un flujo de trabajo de Git estupendo para equipos que están realizando la migración desde SVN. Al igual que Subversion, el flujo de trabajo centralizado usa un repositorio central como punto de entrada de todos los cambios al proyecto. En lugar de trunk, la rama de desarrollo predeterminada se llama master, y todos los cambios se confirman en dicha rama. Este flujo de trabajo no requiere más ramas que master.

La migración a un sistema de control de versiones distribuido puede parecer una tarea complicada, pero no tienes que cambiar tu flujo de trabajo existente para sacarle partido a Git. Tu equipo puede desarrollar proyectos del mismo modo en el que lo hacían con Subversion.

No obstante, usar Git para impulsar tu flujo de trabajo de desarrollo presenta algunas ventajas en comparación con SVN. En primer lugar, le brinda a cada desarrollador su propia copia local del proyecto completo. Este entorno aislado deja que cada desarrollador trabaje de forma independiente a todos los demás cambios de un proyecto; pueden añadir confirmaciones a su repositorio local y olvidarse por completo de los desarrollos posteriores hasta que los necesiten.

En segundo lugar, te proporciona acceso al sólido modelo de fusión y creación de ramas de Git. Al contrario que SVN, las ramas de Git se han diseñado para constituir un mecanismo de seguridad de integración de código y uso compartido de cambios entre repositorios. El flujo de trabajo centralizado es similar a otros flujos de trabajo en lo que respecta al uso de un repositorio remoto alojado en servidor al que los desarrolladores pueden realizar envíos e incorporar cambios. En comparación con otros flujos de trabajo, el flujo de trabajo centralizado no tiene solicitudes de incorporación de cambios o patrones de bifurcación. Un flujo de trabajo centralizado suele ser más adecuado para equipos que migran desde SVN a Git y otros de tamaño reducido.

Funcionamiento

Los desarrolladores empiezan por clonar el repositorio central. En sus propias copias locales del proyecto, editan archivos y confirman cambios como lo harían en SVN; no obstante, estas nuevas confirmaciones se almacenan de forma local, completamente aisladas del repositorio central. Esto permite que los desarrolladores aplacen la sincronización con los niveles superiores hasta que realicen una pausa.

Para publicar cambios en el proyecto oficial, los desarrolladores "envían" su rama master local al repositorio central. Este proceso es equivalente a svn commit, excepto porque añade todas las confirmaciones locales que no se han enviado todavía a una rama master.

Incialización del repositorio central

Git Workflow: Initialize Central Bare Repository

En primer lugar, hace falta crear el repositorio central en un servidor. Si se trata de un proyecto nuevo, puedes inicializar un repositorio vacío. Si no es así, tendrás que importar un repositorio Git o SVN existente.

Los repositorios centrales deben ser siempre bare (vacíos, es decir, sin ningún directorio en funcionamiento), que se pueden crear de esta forma:

ssh user@host git init --bare /path/to/repo.git

Asegúrate de utilizar un nombre de usuario de SSH válido en user, el dominio o la dirección IP de tu servidor en host y la ubicación en la que quieres almacenar el repositorio en /path/to/repo.git. Ten en cuenta que la extensión .git se sueñe añadir al nombre del repositorio para indicar que es un repositorio bare (vacío).

Repositorios centrales alojados

Los repositorios centrales se suelen crear mediante servicios de alojamiento de Git de terceros, como Bitbucket Cloud o Bitbucket Server. El servicio de alojamiento realiza el proceso de inicializar un repositorio bare (vacío) que se ha explicado anteriormente en tu lugar. A continuación, dicho servicio de alojamiento proporcionará una dirección para acceder al repositorio central desde tu repositorio local.

Clonación del repositorio central

El siguiente desarrollador crea una copia local de todo el proyecto. Esto se consigue mediante el comando git clone:

git clone ssh://user@host/path/to/repo.git

Cuando clonas un repositorio, Git añade automáticamente un atajo de teclado llamado origin que apunta al repositorio principal, ya que asume que querrás interactuar con él más adelante. 

Aplicación de cambios y confirmaciones

Cuando el repositorio se clona de forma local, el desarrollador puede aplicar cambios mediante el proceso de confirmación estándar de Git: editar, preparar y confirmar. Si no te has familiarizado con el entorno de ensayo, debes saber que consiste en una forma de preparar una confirmación sin tener que incluir todos los cambios del directorio en funcionamiento. Esto te permite crear confirmaciones con un enfoque muy claro, incluso si has aplicado muchos cambios locales.

git status # Muestra el estado del repositorio
git add <some-file> # Prepara un archivo
git commit # Confirma un archivo</some-file>

Recuerda que, como estos comandos crean confirmaciones locales, John puede repetir el proceso todas las veces que quiera sin tener que preocuparse por lo que esté sucediendo en el repositorio central. Esta característica puede resultar muy útil para funciones de gran tamaño que se tienen que desglosar en bloques más sencillos y reducidos.

Envío de nuevas confirmaciones al repositorio central

Una vez que se hayan aplicado cambios nuevos al repositorio local, se deberán enviar estos cambios para compartirlos con otros desarrolladores del proyecto.

git push origin master

Este comando enviará los nuevos cambios confirmados al repositorio central. Cuando envías cambios al repositorio central, es posible que las actualizaciones enviadas anteriormente por otros desarrolladores contengan código que entra en conflicto con las actualizaciones que tú quieres enviar. Git mostrará un mensaje en el que se indica este problema. En esta situación, tendrá que ejecutarse el comando git pull en primer lugar. Esta situación de conflicto se explica en profundidad en la sección siguiente.

Gestión de conflictos

El repositorio central representa el proyecto oficial, por lo que su historial de confirmación se debe tratar como algo sagrado e inmutable. Si las confirmaciones locales de un desarrollador difieren de las del repositorio central, Git rechazará el envío de cambios porque estos sobrescribirían las confirmaciones oficiales.

Git Workflows: Managing conflicts

Antes de que el desarrollador pueda publicar una función, tiene que buscar y actualizar las confirmaciones centrales y reorganizar los cambios a partir de ellas. Es como decir "quiero añadir mis cambios a lo que los demás ya han hecho". El resultado es un historial perfectamente lineal, como las de los flujos de trabajo de SVN tradicionales.

Si los cambios locales entran en conflicto directo con las confirmaciones en niveles superiores, Git pondrá en pausa el proceso de modificación de bases y te dará la oportunidad de resolver los conflictos de forma manual. Lo bueno de Git es que usa los mismos comandos, git status y git add, tanto para generar confirmaciones como para resolver conflictos de fusión. Esto hace que a los nuevos desarrolladores les resulte sencillo gestionar sus propias fusiones. Además, si tienen problemas, Git hace que sea muy fácil abandonar por completo la reorganización y volver a intentarlo (o ir a pedir ayuda).

Ejemplo

Veamos un ejemplo general sobre cómo un equipo que suele ser pequeño puede colaborar mediante este flujo de trabajo. Hemos visto como dos desarrolladores, John y Mary, pueden trabajar en funciones separadas y compartir sus contribuciones mediante un repositorio centralizado.

John trabaja en su función

Git Workflows: Edit Stage Commit Feature Process

En este repositorio local, John puede desarrollar funciones mediante el proceso de confirmación estándar de Git: editar, preparar y confirmar.

Recuerda que, como estos comandos crean confirmaciones locales, John puede repetir este proceso tantas veces como desee sin tener que preocuparse por lo que está pasando en el repositorio central.

Mary trabaja en su función

Git Workflows: Edit Stage Commit Feature

Mientras tanto, Mary trabaja en su propia función y en su propio repositorio local con el mismo proceso de cambio, preparación y confirmación. Al igual que a John, no le importa lo que esté sucediendo en el repositorio central y, por supuesto, tampoco le importa lo que John está haciendo en su repositorio local, ya que todos los repositorios locales son privados.

John publica su función

Git Workflows: Publish Feature

Una vez que John ha completado su función, debe publicar sus confirmaciones locales en el repositorio central, de forma que otros miembros del equipo puedan acceder a ellas. Puede hacerlo con el comando git push de este modo:

git push origin master

Recuerda que origin es la conexión remota al repositorio central que Git creó cuando John lo clonó. El argumento master le indica a Git que intente hacer que la rama master de origin tenga el mismo aspecto que su rama master local. Como el repositorio central no se ha actualizado desde que John lo clonó, esta acción no creará ningún conflicto y el envío se realizará según lo previsto.

Mary intenta publicar su función

Git Workflows: Push Command Error

Veamos lo que pasa cuando Mary intenta enviar su función después de que John haya publicado con éxito sus cambios en el repositorio central. Puede usar el mismo comando push:

git push origin master

No obstante, como su historial local es distinto que el del repositorio, git rechazará la solicitud con un mensaje de error algo extenso:

error: failed to push some refs to '/path/to/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Así se evita que Mary sobrescriba las confirmaciones oficiales. Tiene que incorporar los cambios de las actualizaciones de John a su repositorio, integrarlos con sus cambios locales y, a continuación, volver a intentarlo.

Mary realiza una reorganización a partir de las confirmaciones de John

Git Workflows: Git Pull Rebase

Mary puede usar el comando git pull para incorporar cambios del nivel superior a su repositorio. Este comando es parecido a svn update, ya que incorpora los cambios de todo el historial de confirmación del nivel superior al repositorio local de Mary e intenta integrarlos con sus confirmaciones locales:

git pull --rebase origin master

La opción --rebase le indica a Git que transfiera todas las confirmaciones de Mary al extremo de la rama master después de sincronizarlos con el repositorio central, como se muestra a continuación:

Git workflows: Rebasing to Master

La incorporación de cambios seguirá funcionando si se te olvida esta opción, pero es posible que tengas que realizar una confirmación de fusión cada vez que alguien tenga que realizar una sincronización con el repositorio central. Para este flujo de trabajo, siempre es mejor reorganizar en lugar de generar una confirmación de fusión.

Mary soluciona un conflicto de fusión

Git Workflows: Rebasing on Commits

Modifica las bases de los trabajos mediante la transferencia de cada confirmación local a la rama master actualizada de una en una. De este modo, descubrirás los conflictos de fusión de cada confirmación, en lugar de tener que resolverlos todos con una confirmación de fusión masiva. Además, esto hace que tus confirmaciones mantengan un enfoque lo más claro posible, y produce un historial del proyecto limpio. También hace que resulte mucho más sencillo descubrir qué errores se han introducido y, si fuera necesario, revertir cambios con un impacto mínimo sobre el proyecto.

Si Mary y John trabajan en funciones que no están relacionadas, es poco probable que el proceso de reorganización genere conflictos. No obstante, si así fuera, Git pausará la reorganización en la confirmación actual y mostrará el siguiente mensaje, además de algunas instrucciones importantes:

CONFLICT (content): Merge conflict in <some-file>
Git workflows: Conflict Resolution

Lo bueno de Git es que cualquiera puede resolver sus propios conflictos de fusión. En nuestro ejemplo, Mary solo tiene que ejecutar un comando git status para ver dónde está el problema. Los archivos en conflicto se mostrarán en la sección Rutas no fusionadas:

# Rutas no fusionadas:
# (usa "git reset HEAD <some-file>..." para deshacer la reparación)#
(usa "git add/rm <some-file>..." según corresponda para indicar la resolución)
#
# ambos modificados: <some-file>

A continuación, editará los archivos como considere. Una vez que esté contenta con el resultado, podrá preparar los archivos según el método habitual y dejar que git rebase haga el resto:

git add <some-file>
git rebase --continue

Y esto es todo lo que hay que hacer. Git continuará con la siguiente confirmación y repetirá el proceso con cualquier otra confirmación que genere conflictos.

Si llegas a este punto y te das cuenta de que no tienes ni idea de lo que está pasando, no entres en pánico. Solo tienes que ejecutar el siguiente comando y volverás al punto de inicio:

git rebase --abort

Mary publica correctamente su función

Git Workflows: Synchronize Central Repo

Después de terminar con la sincronización del repositorio central, Mary podrá publicar los cambios correctamente:

git push origin master

Hacia dónde ir

Como puedes ver, es posible replicar un entorno de desarrollo de Subversion tradicional con solo unos comandos de Git. Este método es perfecto para los equipos que están migrando de SVN, pero no le sacan partido a la naturaleza distribuida de Git.

El flujo de trabajo centralizado es estupendo para equipos pequeños. El proceso de resolución de conflictos explicado anteriormente puede provocar un cuello de botella conforme tu equipo escala su tamaño. Si tu equipo está contento con el flujo de trabajo centralizado, pero quiere perfeccionar la colaboración, merece la pena analizar las ventajas del flujo de trabajo de rama de función. Al dedicar una rama aislada a cada función, es posible iniciar conversaciones en profundidad acerca de nuevas adiciones antes de integrarlas en el proyecto oficial.

Otros flujos de trabajo habituales

El flujo de trabajo centralizado consiste en un bloque de construcción de otros flujos de trabajo de Git. Los flujos de trabajo de Git más populares cuentan con una especie de repositorio centralizado del que los desarrolladores pueden incorporar cambios y al que pueden enviar los suyos. A continuación, hablaremos brevemente sobre otros flujos de trabajo de Git populares. Estos flujos de trabajo ampliados ofrecen patrones más específicos en lo que respecta a la gestión de ramas para el desarrollo de funciones, las correcciones inmediatas y la publicación.

Ramas de funcionalidades

La creación de ramas de funciones es una extensión lógica del flujo de trabajo centralizado. La idea principal que subyace al flujo de trabajo de rama de función es que el desarrollo de una función debe llevarse a cabo en una rama especializada, en lugar de en una rama master. Este aislamiento permite que varios desarrolladores trabajen en una función concreta sin perturbar el contenido del código base principal. También implica que la rama master no debe contener en ningún caso código erróneo, lo que supone una gran ventaja para los entornos de integración continua. 

Flujo de trabajo de Gitflow

El flujo de trabajo de Gitflow se publicó por primera vez en una entrada de blog de 2010 muy reconocida de Vincent Driessen en nvie. El flujo de trabajo de Gitflow define un modelo de creación de ramas estricto diseñado con la publicación del proyecto como fundamento. Este flujo de trabajo no añade ningún concepto o comando nuevo, solo los que se necesitan para el flujo de trabajo de rama de función. En su lugar, asigna funciones muy específicas a las distintas ramas y define cómo y cuándo deben realizarse las interacciones. 

Flujo de trabajo de bifurcación

El flujo de trabajo de bifurcación es muy diferente de los otros flujos de trabajo que se muestran en este tutorial. En lugar de usar un único repositorio en servidor para que actúe como código base central, le proporciona a cada desarrollador un repositorio en servidor. Esto quiere decir que cada contribuyente tiene dos repositorios de Git: uno local y privado y otro público y en servidor. 

Directrices

No existe un flujo de trabajo de Git universal. Como se ha indicado anteriormente, es muy importante desarrollar un flujo de trabajo de Git que suponga una mejora productiva para tu equipo. Además de la cultura del equipo, el flujo de trabajo debe ampliar la cultura empresarial. Las funciones de Git, como las ramas y las etiquetas, deben complementar la planificación de publicación de tu empresa. Si tu equipo usa software de gestión de proyectos con seguimiento de tareas, puede que quieras usar ramas que se correspondan con las tareas en curso. Aquí presentamos algunas directrices que se deben tener en cuenta a la hora de decantarse por un flujo de trabajo:

Ramas transitorias

Cuanto más tiempo se desarrolle una rama de forma independiente a la rama de producción, mayor será el riesgo de que surjan conflictos de fusión y retos de implementación. Las ramas transitorias proporcionan fusiones e implementaciones más limpias.

Minimización y simplificación de reversiones

Es importante disponer de un flujo de trabajo que ayuda de forma proactiva a evitar fusiones que tendrán que revertirse. Un ejemplo de esto son los flujos de trabajo que realizan pruebas de una rama antes de fusionarla con la rama master. No obstante, se producen accidentes. Con esto en mente, conviene tener un flujo de trabajo que permita realizar reversiones sencillas que no interrumpan el flujo de otros miembros del equipo.

Cumplimiento de una planificación de publicación

Un flujo de trabajo debe complementar tu ciclo de publicación de desarrollo de software empresarial. Si tienes pensado realizar varias publicaciones al día, querrás que tu rama master se mantenga estable. Si tu planificación de publicación es mucho menos frecuente, ten en cuenta que puedes usar etiquetas de Git para asignar una rama a una versión.

Resumen

En este documento, hemos hablado de los flujos de trabajo de Git, hemos analizado en profundidad el flujo de trabajo centralizado con ejemplos prácticos y hemos ampliado esta información con la de otros flujos de trabajo especializados. Estas son algunas de las ideas fundamentales de este documento:

  • No existe un flujo de trabajo de Git universal
  • Un flujo de trabajo debe ser sencillo y mejorar la productividad de tu equipo
  • Tus requisitos empresariales deben servir para dar forma al flujo de trabajo de Git

Para obtener más información sobre el flujo de trabajo de Git, echa un vistazo a nuestro desglose completo del flujo de trabajo de rama de función.

¿Listo para aprender a usar Git?

Prueba este tutorial interactivo.

Comienza ahora