Git
git merge

git merge comando: resolver conflicto, rebase aplastar diferencias, fusionar estrategias

En este artículo cubriremos el método git merge. Desde cómo fusionar hasta resolver conflictos, pasando por las características del merge commit, estrategias de fusión, diferencias con rebase y squash, y otras opciones para el comando git merge.

1. Cómo fusionar una rama

El comando git merge se usa para fusionar una rama en otra.

En el post git branch mencioné que el nombre de la rama es el último commit en esa rama. Por la misma razón, fusionar ramas acaba creando un nuevo commit que contiene todos los cambios del último commit de ambas ramas, También puedes pensar en ello como un nuevo commit en la rama de trabajo donde ejecutaste el comando git merge.

El comando git merge siempre realiza la confirmación de la fusión en la rama donde se crea. Por ejemplo, si estuvieras fusionando la rama feature-a desde la rama main, usarías un comando como este

$ git switch main
switched to branch 'main'
 
$ git merge feature-a
Merge made by the 'ort' strategy

En el ejemplo anterior, puedes ver que usamos la estrategia merge-ort, que es la última estrategia de fusión por defecto de Git, cambiada en 2022.

1.1. estrategia ort

Antes de pasar a la siguiente sección, echemos un vistazo rápido al algoritmo de fusión más reciente de Git, la estrategia ort.

ort son las siglas de "Ostensibly Recursive's Twin", lo que significa que fue creado para reemplazar al antiguo algoritmo por defecto, la estrategia recursive. Comparada con la estrategia recursiva, se dice que reduce los conflictos y se ocupa de los ficheros renombrados.

Básicamente se basa en el algoritmo de fusión de 3 vías, que compara los cambios de tres fuentes: el mismo commit antepasado de ambas ramas, el commit más reciente de ambas ramas, y el commit más reciente de ambas ramas, y luego realiza una fusión. Al fusionar dos ramas, utilizaremos principalmente la estrategia ort, porque funciona mejor que las estrategias resolve y recursive utilizadas anteriormente.

Otras estrategias que vale la pena conocer son la estrategia octopus para fusionar dos o más ramas, o la estrategia subtree para fusionar en un subdirectorio. Por ahora, vamos a familiarizarnos con los nombres.

Estas estrategias pueden especificarse con la opción -s o --strategy, como sigue.

$ git merge -s recursive feature-a

2. Cómo resolver un conflicto de fusión

Un conflicto de fusión ocurre cuando la misma línea en el mismo archivo en dos ramas diferentes tiene diferente contenido. Para preservar los datos, Git nunca borrará algo arbitrariamente a menos que le des una opción en la estrategia. En su lugar, pausará la fusión y nos dará una opción.

Veamos esto en acción.

Primero, modificamos el archivo 1.md con diferente contenido en las ramas main y develop. Entonces, cuando vamos a la rama main y tratamos de fusionar la rama develop, obtenemos un conflicto de fusión.

Crear conflicto de fusión

Si no conoces la opción -a del comando git commit, consulta git commit post.

En este punto, Git añadirá símbolos como <<<<<<< HEAD, =======, >>>>>>> branch-name a los contenidos de los archivos en conflicto para que sepas exactamente lo que hay que arreglar. Abramos el archivo 1.md.

situación de conflicto de fusión

Este es el archivo 1.md abierto en el editor Neovim. Sólo tenemos que mantener lo que queremos en esta parte, eliminar los símbolos que Git ha añadido y proceder a la confirmación.

Fusionar es aún más fácil en un editor que soporte Git, como VSCode. El resaltado es intuitivo, y pulsando el botón de las cuatro frases anteriores <<<<<<< HEAD se eliminará automáticamente el contenido excluido y los símbolos de Git.

vscode merge conflict situation

Después de modificar el contenido, completa la fusión con el comando git commit como una confirmación normal.

git merge conflicto resuelto

3. Diferencia con rebase

Los comandos git merge y git rebase tienen algo en común: ambos son formas de fusionar dos ramas y resolver conflictos de fusión. Sin embargo, hay diferencias en la forma en que funcionan, y es importante entenderlas para que puedas elegir la correcta para tus necesidades.

El comando git merge crea un nuevo commit de fusión con el último commit de las dos ramas como padre, como se muestra arriba. Como resultado, hay confirmaciones en el historial de confirmaciones que corresponden a dos ramas juntas. Las rutas feature-a, feature-b, etc. van y vienen en la ruta principal, llamada la rama main.

El comando git rebase fusiona las dos ramas para que no haya callejones sin salida en el historial de confirmaciones. Cómo funciona esto es más fácil de lo que piensas. Echemos un vistazo a la imagen de abajo.

git rebase explicado

Suponiendo que quieras fusionar la rama feature-a con la rama main, que diverge de un commit A común, el comando git rebase crea un nuevo commit con los mismos cambios que el commit en feature-a. En la figura, estos son los commits C y D.

Estos dos commits se añaden a B, el último commit de la rama main. Esto crea un único historial de confirmaciones, pero con el resultado de que todos los cambios en la rama feature-a pueden fusionarse en la rama main. La historia también es más simple, ya que no tenemos que crear una nueva confirmación de fusión.

Sin embargo, no es fácil decir a simple vista si los commits C y D son commits fusionados de diferentes ramas, o commits que estaban previamente en la rama main. Así que desde una perspectiva histórica, estás perdiendo información.

Por esta razón, deberías usar merge y rebase en situaciones apropiadas, dependiendo de la dirección que esté tomando tu equipo. Para más información sobre el comando git rebase, ver este post.

4. Diferencia con squash

Squash es un concepto en Git que comprime múltiples confirmaciones en una. No existe como un comando separado, pero puede usarse como una opción de los comandos merge o rebase. Cuando el comando git merge se utiliza con la opción --squash, se denomina squash merge.

Veamos la siguiente imagen para entender la fusión squash.

Comprendiendo la fusión squash

En el commit actual 8c12, las ramas main y develop están divididas. He probado a hacer un squash merge en la rama main, y ha funcionado sin problemas.

El resultado del comando git status muestra que todos los commits de la rama develop han sido puestos en la rama main.

git squash merge execution result

Si compruebas el historial desde la confirmación, verás que la rama develop permanece sin fusionar, pero sus cambios se han registrado como nuevas confirmaciones en main. Esto es lo que hace una fusión squash.

La opción squash también se puede utilizar durante el proceso de rebase, con la diferencia de que la historia de la rama develop no se deja como antes. Cubriremos esto de nuevo en el post rebase.

5. Reflexiones finales

Creo que los conflictos de fusión son una de las primeras cosas en las que se atascan los principiantes de Git. Sin embargo, la fusión y la resolución de conflictos de fusión son el núcleo de la colaboración en Git, por lo que es importante entenderlas y dominarlas. Espero que este post te ayude a empezar.

copyright for git merge

© 2023 All rights reserved.