Categories
Git

Git Merge y Git Rebase

Git Merge

El comando git merge fusionará cualquier cambio que se haya hecho en la base de código en una rama separada de tu rama actual como un nuevo commit.

La sintaxis del comando es la siguiente:

git merge NOMBRE-DE-LA-RAMA

Por ejemplo, si estás trabajando actualmente en una rama llamada dev y deseas fusionar los nuevos cambios que se hayan realizado en una rama llamada new-features, ejecutarías el siguiente comando:

git merge new-features

Nota: Si hay algún cambio al que no se le ha hecho commit en la rama actual, Git no te permitirá fusionar hasta que se hayan realizado commit todos los cambios en tu rama actual. Para manejar esos cambios, puedes hacer lo siguiente:

Crear una nueva rama y realizar commit a los cambios

git checkout -b nombre-de-la-nueva-rama
git add .
git commit -m "<tu mensaje de commit>"

Guardarlos en el stash

git stash               # agregarlos al stash
git merge new-features  # fusionarlos
git stash pop           # obtén los cambios devuelta al árbol de trabajo (working tree)

Abandonar todos los cambios

git reset --hard        # remueve todos los cambios pendientes

Git Rebase

Realizar un rebase a una rama (branch) en Git es una form ade mover la totalidad de una rama a otro punto del árbol. El ejemplo más simple es mover una rama más arriba en el árbol. Digamos que tenemos una rama que se separó de la rama master en el punto A:

    /o-----o---o--o-----o--------- branch
--o-o--A--o---o---o---o----o--o-o-o--- master

Cuando se realiza rebase se puede mover así:

                      /o-----o---o--o-----o------ branch
--o-o--A--o---o---o---o----o--o-o-o master

Para realizar rebase, asegúrate de tener todos los commits que quieras en el rebase en tu rama master. Revisar la rama en la que quieres hacer el rebase y escribe git rebase master (donde master es la rama en la que quieres hacer el rebase).

También es posible hacer rebase en una rama diferente, de modo que, por ejemplo, una rama que se basaba en otra rama (llamémosla feature) se rebasa en master:

                            /---o-o branch
           /---o-o-o-o---o--o------ feature
----o--o-o-A----o---o--o-o-o--o--o- master

Después de git rebase master branch o git rebase master si te encuentras (checked out) en branch, obtendrás:

           /---o-o-o-o---o--o------ feature
----o--o-o-A----o---o--o-o-o--o--o- master
                                  \---o-o branch

Git rebase interactivo en la consola

Para usar git rebase en la consola con una lista de commits, puedes elegir, editar o soltar en el rebase:

  • Introduce git rebase -i HEAD~5 con el último número que sea cualquier número de commits del más reciente hacia atrás que quieras revisar.
  • En vim, presiona esc, luego i para empezar a editar la prueba.
  • A la izquierda puedes sobreescribir pick con uno de los comandos de abajo. Si quieres aplastar (squash) un commit a uno anterior y descartar el mensaje de commit, introduce f en lugar de pick en el commit.
  • Guarda y sal del editor de texto.
  • Cuando se detiene a rebase, haz los ajustes necesarios, y luego usa git rebase --continue hasta que el rebase sea exitoso.
  • Si el rebase es exitoso, entonces necesitas forzar el push de tus cambios con git push -f para agregar la versión con rebase a tu repositorio remoto.
  • Si hay un «merge conflict» (conflicto al querer fusionar las ramas), hay varias maneras de arreglarlo, incluyendo seguir las sugerencias de esta guía. Una forma es abrir los archivos en un editor de texto y eliminar las partes del código que no quieras. Luego usa git add <file name> seguido de git rebase --continue. Puedes saltarte el commit de conflicto ejecutando git rebase --skip, para el rebase ejecutando git rebase --abort en tu consola.
pick 452b159 <message for this commit>
pick 7fd4192 <message for this commit>
pick c1af3e5 <message for this commit>
pick 5f5e8d3 <message for this commit>
pick 5186a9f <message for this commit>

# Rebase 0617e63..5186a9f onto 0617e63 (30 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but stop to edit the commit message.
# e, edit = use commit, but stop to amend or add commit.
# s, squash = use commit, meld into previous commit and stop to edit the commit message.
# f, fixup = like "squash", but discard this commit's log message thus doesn't stop.
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom. 
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Merge Conflicts

Un merge conflict es cuando realizar commits en ramas separadas que alteran la misma línea de manera conflictiva. Si esto ocurre, Git no sabrá que versión del archivo guardar en un mensaje de error similar al siguiente:

CONFLICT (content): Merge conflict in resumé.txt Automatic merge failed; fix conflicts and then commit the result.

Si miras el archivo resumé.txt en tu editor de texto, puedes ver dónde tuvo lugar el conflicto:

<<<<<<< HEAD
Address: 808 South Street
=======
Address: 505 North Street
>>>>>>> updated_address

Git agregó algunas líneas adicionales en el archivo:

  • <<<<<<< HEAD
  • =======
  • >>>>>>> updated_address

Piensa en  ======= como la línea divisoria del conflicto. Todo lo que hay entre <<<<<<< HEAD y ======= es el contenido de la rama actual a la que apunta HEAD ref. Por otro lado, todo lo que hay entre  ======= y >>>>>>> updated_address es el contenido de la rama que se está fusionando, updated_address.

Git Merge vs Git Rebase

Tanto git merge como git rebase son comandos muy útiles, y uno no es mejor que el otro. Sin embargo, hay algunas diferencias muy importantes entre los dos comandos que tú y tu equipo deben tener en cuenta.

Cada vez que se ejecuta git merge, se crea un merge commit extra. Siempre que trabajes en tu repositorio local, tener demasiados merge commits puede hacer que el historia del commits parezca confuso. Una forma de evitar el merge commit es usar git rebase en su lugar.

git rebase es una característica muy poderosa. Dicho esto, también es arriesgado si no se usa de la manera correcta. git rebase altera el historial de commits, así que úsalo con cuidado. Si el rebase se hace en el repositorio remoto, entonces puede crear muchos problemas cuando otros desarrolladores intentan sacar los últimos cambios de código del repositorio remoto. Recuerda que sólo debes ejecutar git rebase en un repositorio local.

Categories
Git

Como iniciar el GitFlow sin morir en el intento

Durante el ciclo de vida del proyecto, durante la planificación, desarrollo y puesta a producción el producto existe muchas interacciones y personas involucradas.

Sin embargo, los desarrolladores deben de cumplir un papel muy importante para la entrega del producto, en la actualidad existen muchos desarrollos empíricos en la que no cuentan con buenas practicas y que en el proceso de ensayo y error logran alcanzar un pequeño proceso que se ajusta a su realidad.

GitFlow

Es un flujo de trabajo basado en GIT diseñado para organizar todo el proceso de la integración continua.

¡Porque Implementarlo!

  • Aumenta la velocidad de entrega de código terminado al equipo de pruebas.
  • Disminuyen los errores humanos en la mezcla de las ramas.
  • Elimina la dependencia de funcionalidades al momento de entregar código para ser puesto en producción.

¿Cuando se recomienda implementarlo?

  • El equipo de trabajo está conformado por más de dos (2) personas.
  • Se emplean metodologías ágiles.
  • El proyecto tiene cambios frecuentes y se requiere actualizar el ambiente de producción garantizando continuidad en la operación.
  • El proyecto tiene un nivel de complejidad considerable.
  • Se desea tener un proceso de soporte a errores efectivo con actualizaciones rápidas.

Proceso de implementación

La definición de las ramas deben de ser bien definidas, para ello el estándar recomendado son los siguientes.

Ramas Principales:

  • master
  • develop

Otras Ramas:

  • feature: Rama para la creacion de nuevas o modificaciones funcionalidades del proyecto.
  • hotfix: Corrección de parches de bug en producción estas son solucionadas de manera rápida.
  • release: Desplegar la nueva funcionalidad en en producción lanzando nueva versión, esta va a pasar por pruebas.

  • bugfix: Correcciones de fallos que toman mas tiempo de lo debido y es fusionado con la rama master
  • support: Soporte de las funcionalidades y documentación de las mismas.

Plan de Inicio

En realidad, Gitflow es una especie de idea abstracta de un flujo de trabajo de Git. Esto quiere decir que ordena qué tipo de ramas se deben configurar y cómo fusionarlas. Explicaremos brevemente los objetivos de las ramas a continuación. El conjunto de herramientas de git-flow es una herramienta de línea de comandos propiamente dicha que tiene un proceso de instalación. El proceso de instalación de git-flow es sencillo. Los paquetes de git-flow están disponibles en varios sistemas operativos.

Se debe de instalar los paquetes, el proceso se encuentra en el siguiente link: https://danielkummer.github.io/git-flow-cheatsheet/

espués de instalar git-flow, puedes utilizarlo en tu proyecto ejecutando git flow init. Git-flow es un contenedor para Git. El comando git flow init es una prolongación del comando predeterminado git init y no cambia nada de tu repositorio aparte de crear ramas para ti.

Funcionamiento

Ramas principales y de desarrollo

El primer paso es complementar la rama main predeterminada con una rama develop. Una forma sencilla de hacerlo es que un desarrollador cree de forma local una rama develop vacía y la envíe al servidor:

git branch develop git push -u origin develop

Esta rama contendrá el historial completo del proyecto, mientras que main contendrá una versión abreviada. A continuación, otros desarrolladores deberían clonar el repositorio central y crear una rama de seguimiento para develop.

A la hora de utilizar la biblioteca de extensiones de git-flow, ejecutar git flow init en un repositorio existente creará la rama develop:

Ramas de función

Todas las funciones nuevas deben residir en su propia rama, que se puede enviar al repositorio central para copia de seguridad/colaboración. Sin embargo, en lugar de ramificarse de main, las ramas feature utilizan la rama develop como rama primaria. Cuando una función está terminada, se vuelve a fusionar en develop. Las funciones no deben interactuar nunca directamente con main

Ten en cuenta que las ramas feature combinadas con la rama develop conforman, a todos efectos, el flujo de trabajo de ramas de función. Sin embargo, el flujo de trabajo Gitflow no termina aquí.

Las ramas feature suelen crearse a partir de la última rama develop.

Creación de una rama de función

git flow feature start feature_branch

Sigue trabajando y utiliza Git como lo harías normalmente.

Publicacion en la rama remota

Cuando se haya realizado los commits de manera local se debe de publicar la rama en el remote con el siguiente comando:

git flow feature publish feature_branch

Finalización de una rama de función

Cuando hayas terminado con el trabajo de desarrollo en la función, el siguiente paso es fusionar feature_branch en develop.

git flow feature finish feature_branch

Ramas de publicación

Cuando develop haya adquirido suficientes funciones para una publicación (o se acerque una fecha de publicación predeterminada), debes bifurcar una rama release (o de publicación) a partir de develop. Al crear esta rama, se inicia el siguiente ciclo de publicación, por lo que no pueden añadirse nuevas funciones una vez pasado este punto (en esta rama solo deben producirse las soluciones de errores, la generación de documentación y otras tareas orientadas a la publicación). Cuando está lista para el lanzamiento, la rama release se fusiona en main y se etiqueta con un número de versión. Además, debería volver a fusionarse en develop, ya que esta podría haber progresado desde que se iniciara la publicación.

Crear ramas release es otra operación de ramificación sencilla. Al igual que las ramas feature, las ramas release se basan en la rama develop. Se puede crear una nueva rama release utilizando los siguientes métodos.

git checkout develop
git checkout -b release/0.1.0

En cuanto la publicación esté lista para su lanzamiento, se fusionará en las ramas main y develop, y luego se eliminará la rama release. Es importante volver a fusionarla en la rama develop porque podrían haberse añadido actualizaciones importantes a la rama release, y las funciones nuevas tienen que poder acceder a ellas. Si en tu organización se da mucha importancia a la revisión de código, este sería el lugar ideal para una solicitud de incorporación de cambios.

git checkout main
git merge release/0.1.0

Flujo General: Resumen

  • Se crea una rama develop a partir de main.
  • Se crea una rama release a partir de la develop.
  • Se crean ramas feature a partir de la develop.
  • Cuando se termina una rama feature, se fusiona en la rama develop.
  • Cuando la rama release está lista, se fusiona en las ramas develop y generar una petición de fusión a main.
  • Si se detecta un problema en main, se crea una rama hotfix a partir de main.
  • Una vez terminada la rama hotfix, esta se fusiona tanto en develop y genera una petición de fusión a main.