git merge
Información sobre el comando git merge, cómo funciona y las diferencias entre fusión fast-forward y fusión a 3 vías.
El comando git merge une dos o más líneas de desarrollo. Cuando terminas una funcionalidad en su propia rama, git merge toma el trabajo de esa rama y lo incorpora a la rama en la que te encuentras actualmente, produciendo un historial combinado único.
Esta página explica qué sucede durante una fusión, la diferencia entre una fusión fast-forward y una fusión a 3 vías, cómo forzar un commit de fusión y cómo reconocer y resolver un conflicto de fusión.
Funciona estrechamente con git branch (para crear y eliminar ramas), git checkout (para cambiar a la rama receptora) y git pull (para actualizar antes de fusionar). Si prefieres un historial lineal sin commits de fusión, consulta git rebase como alternativa.
Cómo funciona
El uso principal de git merge es combinar dos ramas. También se utiliza para integrar múltiples commits de una rama en otra. En la siguiente ilustración, git merge toma los extremos de dos ramas y encuentra un commit ancestro común entre ellas. Ese commit base común se utiliza para crear un nuevo commit de fusión que combina los cambios de ambas ramas. Aquí tenemos dos ramas: master y stage. Debemos fusionar la rama stage en la rama master.

Los commits de fusión son únicos porque tienen dos commits padre. Git combina automáticamente historiales separados al crear un nuevo commit de fusión. Sin embargo, si ambas ramas modifican las mismas líneas, Git no puede combinarlas automáticamente, lo que produce un conflicto de fusión.

Proceso de fusión
Antes de iniciar el proceso de fusión, sigue estos pasos:
- Asegúrate de estar en la rama receptora correcta. Ejecuta
git checkout <rama receptora>para cambiar a ella. - Actualiza la rama de destino con los últimos cambios remotos. Ejecuta
git pullpara obtener e integrar los últimos commits remotos. - El paso final es ejecutar
git merge <nombre de rama>, que especifica la rama que se fusionará en la rama receptora.
Fusión fast-forward
Una fusión fast-forward ocurre cuando el camino desde la rama actual hasta la rama de destino es lineal. La fusión fast-forward combina los historiales, ya que todos los commits alcanzables desde la rama de destino están disponibles a través de la rama actual. Aquí tienes un ejemplo de fusión fast-forward:

Cuando los dos historiales han divergido, Git utiliza la fusión a 3 vías como alternativa. La fusión a 3 vías usa un commit dedicado para combinar dos historiales.

Las fusiones fast-forward se usan típicamente para funcionalidades pequeñas o correcciones de errores, mientras que las fusiones a 3 vías se utilizan para integrar funcionalidades de larga duración. Los siguientes ejemplos utilizan una fusión fast-forward:
git merge
# Start the stage
git checkout -b stage master
# Edit some files
git add <file>
git commit -m "Start with the stage"
# Edit some files
git add <file>
git commit -m "Finish with the stage"
# Merge in the stage branch
git checkout master
git merge stage
git branch -d stageEjecutamos git branch -d para eliminar la rama stage, ya que stage ahora es accesible desde la rama master.
El comando git merge con la opción --no-ff se ejecuta si necesitas un commit de fusión durante una fusión fast-forward para fusionar la rama especificada en la rama actual, generando siempre un commit de fusión (incluso en el caso de una fusión fast-forward):
git merge --no-ff
git merge --no-ff <branch>Fusión a 3 vías
Este escenario requiere una fusión a 3 vías cuando la rama master avanza mientras la rama stage aún está en desarrollo. Esto se utiliza cuando los miembros del equipo trabajan simultáneamente en una funcionalidad grande:
el comando git merge
# Start the stage
git checkout -b stage master
# Edit some files
git add <file>
git commit -m "Start with the stage"
# Edit some files
git add <file>
git commit -m "Finish with the stage"
# Develop the master branch
git checkout master
# Edit some files
git add <file>
git commit -m "Make some super-stable changes to master"
# Merge in the stage branch
git merge stage
git branch -d stageEn el ejemplo anterior, stage sería una funcionalidad más grande que requiere mucho tiempo de desarrollo, por eso usamos una fusión a 3 vías. Si tu funcionalidad es pequeña, es mejor usar una fusión fast-forward para evitar commits innecesarios que ensucien el historial del proyecto.
Opciones útiles de fusión
Estas opciones modifican el comportamiento de git merge:
| Opción | Qué hace |
|---|---|
--no-ff | Siempre crea un commit de fusión, incluso cuando es posible un fast-forward. Mantiene la rama de funcionalidad visible en el historial. |
--ff-only | Fusiona solo si es posible un fast-forward; de lo contrario, aborta. Útil en scripts para rechazar un commit de fusión. |
--squash | Combina todos los commits de la rama en un único conjunto de cambios preparados (que luego se confirman manualmente). No hay commit de fusión ni segundo padre. |
--abort | Detiene una fusión con conflictos y restaura la rama a su estado anterior a la fusión. |
-m "<msg>" | Establece el mensaje del commit de fusión directamente en lugar de abrir un editor. |
Una fusión squash es útil cuando una rama de funcionalidad tiene muchos commits pequeños de "trabajo en progreso" que no quieres en el historial principal:
git merge --squash
git checkout master
git merge --squash stage
git commit -m "Add stage feature"Resolución de conflictos
Al fusionar dos ramas, si la misma parte del mismo archivo ha sido modificada, se producen conflictos de fusión porque Git no puede determinar qué versión usar. Cuando esto ocurre, Git se detiene antes de crear el commit de fusión para permitirte resolver el conflicto. El proceso de fusión de Git usa un flujo de trabajo de editar/preparar/confirmar para resolver conflictos de fusión. Cuando ocurre un conflicto, ejecutar git status mostrará los archivos que necesitan resolverse. La siguiente imagen aparecerá cuando las mismas partes del archivo example.txt hayan sido modificadas:
git status
On branch master
Unmerged paths:
(use "git add/rm ..." as appropriate to mark resolution)
both modified: example.txtSi decides no continuar con la fusión, puedes cancelarla en cualquier momento ejecutando git merge --abort.
Cómo se presentan los conflictos
En caso de conflictos, Git edita el contenido de los archivos afectados con marcas visuales a ambos lados del contenido en conflicto. Los conflictos solo pueden ocurrir durante una fusión a 3 vías: una fusión fast-forward nunca genera conflictos, porque la rama receptora no tenía nuevos commits propios con los que chocar.
Los marcadores principales son <<<<<<<, ======= y >>>>>>>. Te ayudan a localizar las secciones en conflicto en tus archivos.
git conflicts
here is some content not affected by the conflict
<<<<<<< master
this is conflicted text from master
=======
this is conflicted text from stage branch
>>>>>>> stagePara resolver el conflicto, abre el archivo, elimina las tres líneas de marcadores (<<<<<<<, =======, >>>>>>>), y edita el texto restante con la versión que deseas conservar. Luego ejecuta git add <file> en el archivo con conflicto para marcarlo como resuelto, y ejecuta git commit para crear el commit de fusión.
Un ejemplo completo paso a paso
La sesión a continuación crea dos ramas que editan la misma línea, las fusiona, encuentra un conflicto, lo resuelve y finaliza la fusión. Puedes pegar estos comandos en cualquier directorio vacío para reproducirlo exactamente.
reproduce a conflict and resolve it
git init demo && cd demo
echo "line one" > file.txt
git add file.txt
git commit -m "Initial commit"
# Create a branch and change the line there
git checkout -b stage
echo "change from stage" > file.txt
git commit -am "Edit on stage"
# Change the same line on master
git checkout master
echo "change from master" > file.txt
git commit -am "Edit on master"
# Merge stage into master -> conflict
git merge stage
# Auto-merging file.txt
# CONFLICT (content): Merge conflict in file.txt
# Automatic merge failed; fix conflicts and then commit the result.Después de editar file.txt para conservar la versión que deseas, finaliza la fusión:
git add file.txt
git commit -m "Merge stage, keep resolved line"
git branch -d stageVerificación de una fusión
Después de fusionar, confirma el resultado con git log. Las opciones --graph y --oneline dibujan la topología de las ramas, por lo que un commit de fusión (con dos padres) es fácil de identificar:
git log --oneline --graphSi decides que una fusión completada fue un error, git reset puede mover la rama de vuelta al commit anterior a la fusión.