Por Anónimo (no verificado) , 29 Abril 2026

Introducción

Git tiene dos resultados de merge fundamentalmente diferentes: fast-forward, donde la punta de un branch simplemente se mueve, y three-way, donde se crea un nuevo commit con dos padres. La elección depende de si los branches han divergido.

Fast-forward

Si la punta de main es ancestro de feature, no se necesita un merge real. Git solo mueve main hacia adelante:

      A---B---C   feature
     /
main

# después de git merge feature
A---B---C   main, feature

Comando:

git switch main
git merge feature

Para forzar un merge commit real incluso cuando es posible fast-forward:

git merge --no-ff feature

Merge three-way

Cuando ambos branches han divergido, Git encuentra la merge base (el ancestro común más reciente) y combina los cambios de ambos lados:

      A---B---C   feature
     /
A---D---E   main

# después de git merge feature
A---D---E---M   main
     \     /
      B---C   feature

La estrategia de merge predeterminada de Git desde 2.33 es ort; antes era recursive. Ambas calculan un merge three-way por archivo usando la merge base.

Inspeccionando

git merge-base main feature
git log --oneline --graph --all
git show --stat HEAD          # ver el merge commit

Estrategias y opciones

git merge -X ours feature        # preferir nuestro lado en conflictos
git merge -X theirs feature      # preferir su lado
git merge -X ignore-space-change feature
git merge --squash feature       # aplicar cambios sin merge commit

--squash crea un solo commit que contiene todos los cambios de feature, sin enlace de padre a él. Útil para historial ordenado pero pierde el detalle por commit.

Abortando y deshaciendo

git merge --abort                # a mitad de merge, volver al estado pre-merge
git reset --hard ORIG_HEAD       # después de un merge terminado, deshacerlo

Configurando política fast-forward

git config --global merge.ff false      # siempre crear merge commit
git config --global merge.ff only      # solo fast-forward, rechazar de lo contrario
git config --global pull.ff only       # igual para pulls

Drivers de merge y atributos

Algunos archivos se mergean mal con three-way basado en texto (lockfiles generados por máquina, documentación generada). Configura un driver de merge personalizado vía .gitattributes y git config:

# .gitattributes
package-lock.json merge=ours
Gemfile.lock merge=union
git config merge.ours.driver true
git config merge.union.name "Line union merge"
git config merge.union.driver "git merge-file --union %A %O %B"

La estrategia integrada union mantiene ambos lados; ours siempre elige nuestra versión; los drivers personalizados pueden ejecutar cualquier programa. Úsalos con moderación; comportamiento de merge sorprendente confunde a los reviewers.

Errores comunes

Creer que fast-forward es de alguna manera especial o arriesgado; no lo es, es solo un movimiento de puntero. Usar --no-ff en cada merge en un proyecto de movimiento rápido, contaminando el historial con merge commits vacíos. Usar -X ours cuando querías --strategy=ours (que descarta el otro lado por completo) o viceversa. Finalmente, editar manualmente el mensaje de merge commit después del hecho y romper la redacción estandarizada "Merge branch 'X'" en la que las herramientas se basan; si debes editarlo, hazlo antes de git commit.