Close

Git merge

La fusión es la forma que tiene Git de volver a unir un historial bifurcado. El comando git merge permite tomar las líneas independientes de desarrollo creadas por git branch e integrarlas en una sola rama.

Ten en cuenta que todos los comandos presentados a continuación se fusionan en la rama actual. La rama actual se actualizará para reflejar la fusión, pero la rama de destino no se verá afectada en absoluto. Una vez más, esto significa que git merge se suele utilizar junto con git checkout para seleccionar la rama actual y git branch -d para eliminar la rama de destino obsoleta.


Funcionamiento


git merge combinará varias secuencias de confirmaciones en un historial unificado. En los casos de uso más frecuentes, git merge se utiliza para combinar dos ramas. Los ejemplos siguientes del presente documento se centrarán en este patrón de fusión de ramas. En estos casos, git merge toma dos punteros de confirmación, normalmente los extremos de la rama, y encuentra una confirmación base común entre ellos. Una vez que Git encuentra una confirmación base en común, crea una "confirmación de fusión" nueva que combina los cambios de cada secuencia de confirmación de fusión puesta en cola.

Supongamos que tenemos una rama de función nueva que se basa en la rama main. Ahora, queremos fusionar esa rama de función con la rama main.

Fusionar la rama de funciones en main
Ventana de consola
Material relacionado

Git log avanzado

Logotipo de Bitbucket
VER LA SOLUCIÓN

Aprende a usar Git con Bitbucket Cloud

Al invocar este comando, la rama de función especificada se fusionará con la rama actual, la cual asumiremos que es la main. Git determinará el algoritmo de fusión automáticamente (véase más adelante).

Nodo de nueva confirmación de fusión

Las confirmaciones de fusión son únicas con respecto a otras confirmaciones en el hecho de que tienen dos confirmaciones principales. Al crear una confirmación de fusión, Git tratará de fusionar automáticamente los historiales independientes. Sin embargo, si encuentra datos que se han cambiado en ambos historiales, no podrá combinarlos de ese modo. En ese caso, se crea un conflicto de control de versiones y Git solicitará la intervención del usuario para poder continuar.

Preparación para fusionar


Antes de ejecutar una fusión, hay un par de pasos de preparación que llevar a cabo con el fin de garantizar que la fusión se realice sin problemas.

Confirmación de la rama de recepción


Ejecuta git status para asegurarte de que HEAD apunte a la rama de fusión-recepción correcta. En caso necesario, ejecuta git checkout para cambiar a la rama de recepción. En nuestro caso, ejecutaremos git checkout main.

Recuperación de las últimas confirmaciones remotas


Asegúrate de que la rama de recepción y la rama de fusión están actualizadas con los cambios remotos más recientes. Ejecuta git fetch para incorporar los cambios de las confirmaciones remotas más recientes. Una vez que la recuperación se haya completado, asegúrate de que la rama main tenga las actualizaciones más recientes mediante la ejecución del comando git pull.

Fusión


Una vez adoptados los pasos comentados anteriormente de "preparación para la fusión", se puede iniciar una fusión ejecutando git merge donde es el nombre de la rama que se fusionará con la rama de recepción.

Fusión de avance rápido


Puede que se produzca una fusión con avance rápido cuando hay un proceso lineal desde el extremo de la rama actual hasta la rama de destino. En lugar de fusionar “realmente” las ramas, lo único que tiene que hacer Git para integrar los historiales es mover el extremo de la rama actual al extremo de la rama de destino (es decir, realizar un “avance rápido”). De este modo, combina de manera eficaz los historiales, ya que todas las confirmaciones alcanzables desde la rama de destino están ahora disponibles a través de la rama actual. Por ejemplo, una fusión con avance rápido de una rama de función en una main se vería de la siguiente manera:

Los nodos del nodo de función que están por delante del nodo principal se encuentran en el mismo nodo tras el avance rápido

Sin embargo, no es posible una fusión con avance rápido si las ramas han divergido. Cuando no hay un proceso lineal hacia la rama de destino, Git no tiene más opción que combinarlas mediante una fusión de 3 vías. Las fusiones de 3 vías utilizan una confirmación específica para unir dos historiales. Esta fusión recibe su nombre del hecho de que Git utiliza tres confirmaciones para generar la confirmación de fusión: los dos extremos de la rama y su predecesor común.

Diagrama tras una fusión de 3 vías

Aunque se pueden utilizar cualquiera de estas estrategias de fusión, a muchos desarrolladores les gusta utilizar las fusiones con avance rápido (facilitadas a través del comando rebasing) para funciones pequeñas o correcciones de errores, mientras que se reservan las fusiones de tres vías para la integración de funciones con una ejecución de mayor duración. En este último caso, la confirmación de fusión resultante sirve como una unión simbólica de las dos ramas.

Nuestro primer ejemplo muestra una fusión con avance rápido. El código a continuación crea una rama nueva, le añade dos confirmaciones y, seguidamente, la integra en la línea principal con una fusión con avance rápido.

# Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Merge in the new-feature branch
git checkout main
git merge new-feature
git branch -d new-feature

Se trata de un flujo de trabajo común para las ramas temáticas transitorias que se utilizan más como un desarrollo aislado que como una herramienta de organización para funcionalidades con una ejecución de mayor duración.

Ten en cuenta también que Git no debería quejarse sobre el comando git branch -d, ya que ahora se puede acceder a la nueva función desde la rama principal.

En caso de necesitar una confirmación de fusión durante una fusión con avance rápido para mantener registros, es posible ejecutar git merge con la opción --no-ff.

git merge --no-ff <branch>

Este comando fusiona la rama especificada en la rama actual, pero siempre genera una confirmación de fusión (incluso si se trata de una fusión con avance rápido). Esto resulta útil para documentar todas las fusiones que tienen lugar en tu repositorio.

Fusión de 3 vías


El siguiente ejemplo es muy similar, pero requiere una fusión de tres vías porque la rama main ha avanzado mientras la función se está desarrollando. Este es un caso habitual con funciones grandes o cuando hay varios desarrolladores trabajando en un proyecto simultáneamente.

Start a new feature
git checkout -b new-feature main
# Edit some files
git add <file>
git commit -m "Start a feature"
# Edit some files
git add <file>
git commit -m "Finish a feature"
# Develop the main branch
git checkout main
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to main"
# Merge in the new-feature branch
git merge new-feature
git branch -d new-feature

Ten en cuenta que es imposible que Git lleve a cabo una fusión con avance rápido, ya que no hay forma de mover la rama main a la de new-feature sin retroceder.

En la mayoría de los flujos de trabajo, la rama de new-feature sería una función muy grande que ha tardado mucho en desarrollarse, por lo que, mientras tanto, se han ido incorporando nuevas confirmaciones a la rama main. Si tu rama de función fuera en realidad tan pequeña como la del ejemplo anterior, probablemente sería mejor que la fusionases mediante cambio de base a la rama main y que hicieses una fusión con avance rápido. Esto evitaría que apareciesen confirmaciones de fusión superfluas en el historial del proyecto.

Resolución de conflicto


Si las dos ramas que tratas de fusionar han cambiado la misma parte del mismo archivo, Git no podrá averiguar qué versión utilizar. Cuando esto ocurre, Git se detiene justo antes de la confirmación de fusión para que puedas resolver los conflictos manualmente.

Algo muy interesante del proceso de fusión de Git es que utiliza el conocido flujo de trabajo de edición, preparación y confirmación para resolver los conflictos de fusión. Cuando se observa un conflicto de fusión, la ejecución del comando git status muestra qué archivos se deben resolver. Por ejemplo, si en ambas ramas se ha modificado la misma sección de hello.py, se vería algo parecido a esto:

On branch main
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: hello.py

Cómo se presentan los conflictos


Si Git encuentra un conflicto durante una fusión, editará el contenido de los archivos afectados con indicadores visuales que marquen ambas caras del contenido conflictivo. Estos marcadores visuales son: <<<<<<<, =======, y>>>> >>>. Es útil buscar estos indicadores en un proyecto durante una fusión para saber dónde hay que resuelto los conflictos.

here is some content not affected by the conflict
<<<<<<< main
this is conflicted text from main
=======
this is conflicted text from feature branch
>>>>>>> feature branch;

Normalmente, el contenido que se encuentra delante del marcador ======= es la rama de recepción y el de la parte de detrás es la rama de fusión.

Una vez identificadas las secciones conflictivas, puedes entrar y arreglar la fusión a tu gusto. Cuando estés listo para terminar la fusión, lo único que tienes que hacer es ejecutar git add en los archivos conflictivos para indicar a Git que se han resuelto. Seguidamente, ejecutas un git commit normal para generar la confirmación de fusión. El proceso es exactamente el mismo que el de la confirmación de una instantánea normal, lo que significa que es fácil para los desarrolladores habituales gestionar sus propias fusiones.

Ten en cuenta que los conflictos de fusión solo se producirán en el caso de una fusión de 3 vías. Los cambios conflictivos en una fusión de avance rápido no son posibles.

Resumen


Este documento es un resumen del comando git merge. La fusión es un proceso esencial cuando se trabaja con Git. Hemos hablado de los mecanismos internos que hay detrás de una fusión y de las diferencias entre una fusión con avance rápido y una de 3 vías auténtica. Algunas de las principales conclusiones son las siguientes:

1. La fusión en Git combina secuencias de confirmaciones en un solo historial unificado de confirmaciones.

2. En Git hay, principalmente, dos tipos de fusión: con avance rápido y de tres vías.

3. Git permite fusionar las confirmaciones automáticamente salvo que haya cambios que entren en conflicto en ambas secuencias de confirmación.

Este documento ha integrado y hecho referencia a otros comandos de Git como, por ejemplo: git branch, git pull y git fetch. Para obtener más información sobre ellos, visita sus respectivas páginas.


Compartir este artículo

Lecturas recomendadas

Consulta estos recursos para conocer los tipos de equipos de DevOps o para estar al tanto de las novedades sobre DevOps en Atlassian.

Gente que colabora utilizando un muro lleno de herramientas

Blog de Bitbucket

Ilustración de Devops

Ruta de aprendizaje de DevOps

Demostraciones de funciones con expertos de Atlassian del Centro de demostraciones

Cómo funciona Bitbucket Cloud con Atlassian Open DevOps

Suscríbete para recibir el boletín de DevOps

Thank you for signing up