Merge: fusionando ramas

Lectura
25 min~9 min lectura

Merge: Fusionando Ramas en Git

Bienvenido a esta lección sobre merge, uno de los comandos más fundamentales y utilizados cuando trabajas con Git en equipos de desarrollo. Si has seguido el curso, ya conoces cómo crear ramas para trabajar en funcionalidades separadas. Ahora es momento de aprender cómo unir esas ramas de vuelta a la línea principal de desarrollo.

📌 ¿Qué aprenderás hoy?
  • Comprender qué es un merge y cuándo usarlo
  • Diferenciar entre los tipos de merge en Git
  • Ejecutar fusiones de ramas de forma segura
  • Reconocer y resolver conflictos básicos
  • Aplicar buenas prácticas para merges exitosos

¿Qué es un Merge?

Un merge en Git es el proceso de combinar los cambios de una rama diferente dentro de tu rama actual. Cuando trabajas en una rama aislada (como feature/nueva-funcionalidad), todos los commits permanecen en esa rama. El merge permite integrar esos cambios a otra rama, típicamente main o develop.

CONCEPTO CLAVE

El merge toma todos los cambios de una rama fuente y los aplica sobre la rama destino, creando un nuevo commit de merge que tiene dos padres. Este commit especial conecta ambas líneas de desarrollo en el historial de Git.

Tipos de Merge en Git

Git maneja diferentes estrategias de merge según la situación. Comprenderlas te ayudará a entender qué ocurre detrás de escenas.

Tipo de Merge Descripción Cuándo ocurre
Fast-Forward Git simplemente mueve el puntero hacia adelante No hay cambios en la rama destino
Recursive Crea un commit de merge con dos padres Ambas ramas tienen cambios
Squash Merge Combina todos los commits en uno solo Quieres historial lineal
Octopus Fusiona múltiples ramas a la vez Ramas de release con múltiples features

Fast-Forward Merge

Este es el tipo de merge más simple. Ocurre cuando la rama destino no tiene ningún commit nuevo desde que creaste tu rama de trabajo. Git simplemente avanza el puntero de la rama destino hasta el último commit de tu rama.

# Situación antes del merge:
# main:    A - B
# feature:       C - D - E

git checkout main
git merge feature

# Resultado:
# main:    A - B - C - D - E
# (los commits de feature se "avanzan" a main)
💡 Consejo: Si quieres evitar un fast-forward aunque sea posible (para preservar el historial de ramas), usa la bandera --no-ff. Esto crea un commit de merge explícito incluso cuando Git podría hacer fast-forward.

Recursive Merge (Three-Way Merge)

Cuando tanto la rama destino como la rama que quieres fusionar tienen cambios nuevos, Git utiliza un merge recursivo de tres vías. Este algoritmo:

  1. Identifica el ancestro común de ambas ramas
  2. Compara los cambios de cada rama con ese ancestro
  3. Combina los cambios automáticamente donde es posible
  4. Crea un commit de merge que une ambas líneas
# Situación:
#        A - B - C  (main)
#            \
#             D - E  (feature)

git checkout main
git merge feature

# Resultado:
#        A - B - C - F
#            \     /
#             D - E
#
# F es el commit de merge
CONCEPTO CLAVE

El commit de merge tiene dos padres: el último commit de la rama destino y el último commit de la rama que estás fusionando. Esto es lo que permite a Git reconstruir el historial completo de ambas ramas.

Realizando tu Primer Merge

Vamos a practicar con un ejemplo completo paso a paso.

Escenario Práctico

Imagina que estás desarrollando una aplicación web y necesitas agregar una nueva funcionalidad de búsqueda:

# 1. Verifica que estás en main y está actualizado
git checkout main
git pull origin main

# 2. Crea una rama para la nueva funcionalidad
git checkout -b feature/buscador

# 3. Trabaja en tu funcionalidad (agregas archivos, haces commits)
touch buscador.js
git add buscador.js
git commit -m "Agrega módulo de búsqueda básico"

echo "function buscar() { return []; }" > buscador.js
git add buscador.js
git commit -m "Implementa lógica de búsqueda"

# 4. Una vez terminado, vuelves a main
git checkout main

# 5. Fusionas tu rama feature con main
git merge feature/buscador

# 6. Sube los cambios al repositorio remoto
git push origin main
💡 Buena práctica: Siempre haz git pull en tu rama destino antes de hacer merge. Esto minimiza la posibilidad de conflictos y asegura que estás integrando código actualizado.

¿Qué pasa cuando hay conflictos?

Un conflicto ocurre cuando Git no puede fusionar automáticamente los cambios porque las mismas líneas fueron modificadas en ambas ramas. Esto es común cuando dos desarrolladores trabajan en las mismas partes del código.

⚠️ Importante: Los conflictos no son un error ni algo malo. Son una señal de que dos personas修改aron el mismo código, lo cual es normal en equipos. Git simplemente necesita que un humano decida cuál versión mantener.

Identificando Conflictos

Cuando intentas hacer merge y hay conflictos, Git te lo notificará:

git merge feature/nueva-funcion
Auto-merging archivo.js
CONFLICT (content): Merge conflict in archivo.js
Automatic merge failed; fix conflicts and then commit the result.

El archivo en conflicto tendrá marcadores especiales:

<<<<<<< HEAD (rama actual: main)
const titulo = "Bienvenido";
=======
const titulo = "Hola Mundo";
>>>>>>> feature/nueva-funcion

Los marcadores significan:

  • <<<<<<< HEAD: Inicio del conflicto, indica tu rama actual
  • =======: Separador entre ambas versiones
  • >>>>>>> feature/nueva-funcion: Fin del conflicto, indica la rama que estás fusionando

Resolviendo Conflictos

  1. Abre el archivo en conflicto con tu editor de código favorito
  2. Decide qué versión mantener: puede ser la de HEAD, la otra rama, o una combinación de ambas
  3. Elimina los marcadores de conflicto (<<<<<<<, =======, >>>>>>>)
  4. Edita el archivo dejando solo la versión final que deseas
  5. Guarda el archivo y cierra el editor
  6. Stage y commit: git add archivo.js y git commit
# Ejemplo de resolución - mantienes ambas versiones combinadas:
const titulo = "Bienvenido"; // conservas el texto de main
const subtitulo = "Buscador actualizado"; // agregas algo nuevo

# Luego:
git add archivo.js
git commit -m "Resuelve conflicto: combina títulos de ambas ramas"

# O si decides mantener solo una versión:
const titulo = "Hola Mundo";  // eliminas todo y dejas solo esto

git add archivo.js
git commit -m "Resuelve conflicto: usa versión de feature/nueva-funcion"
Ver más: Herramientas para resolver conflictos visualmente

Además de editar manualmente, existen herramientas que facilitan la resolución de conflictos:

  • VS Code: Tiene un editor de conflictos integrado que muestra las diferencias lado a lado
  • GitKraken: Cliente visual de Git con resolución de conflictos gráfica
  • Meld: Herramienta gratuita de diff visual
  • Beyond Compare: Comparador profesional (de pago)

Puedes configurar tu herramienta preferida con: git config --global merge.tool nombre_herramienta

Estrategias para Migrations Exitosos

"Un merge bien ejecutado es aquel donde nadie pierde su trabajo y todos los cambios terminan en el código final."
  • Haz commits pequeños y frecuentes: Esto hace que los merges sean más fáciles de resolver
  • Sincroniza frecuentemente: Ejecuta git pull o merge desde la rama principal regularmente
  • Comunica con tu equipo: Si sabes que alguien más está trabajando en el mismo archivo, coordínalo
  • Revisa los cambios antes de commitear: Usa git diff para entender qué se está combinando
  • Usa pull requests: En GitHub, los PRs permiten revisar código antes de hacer merge
💡 Tip profesional: Muchos equipos usan la estrategia merge often, ship often. En lugar de mantener ramas separadas por semanas, hacen merges pequeños y frecuentes para evitar conflictos grandes.

Comandos Útiles para Merges

Comando Función
git merge --abort Cancela el merge en progreso y vuelve al estado anterior
git merge --continue Continúa después de resolver conflictos
git merge --no-ff Fuerza creación de commit de merge
git merge --squash Combina todos los commits en uno solo
git merge --ff-only Solo hace merge si puede hacer fast-forward
git log --merge Muestra commits que causan conflictos

Merge vs Rebase: ¿Cuál elegir?

Esta es una pregunta común en la comunidad de Git. Ambos tienen sus ventajas:

📌 Resumen rápido:
  • Merge: Preserva el historial completo, más seguro para trabajo en equipo, puede crear historial complejo
  • Rebase: Historial lineal y limpio, no usar en ramas públicas, riesgo de perder trabajo si se hace mal

Para principiantes, recomendamos usar merge ya que es más difícil cometer errores irreversibles. El rebase se cubre en detalle en lecciones avanzadas del curso.

Práctica en GitHub

En plataformas como GitHub, también puedes hacer merges directamente desde la interfaz web:

  1. Abre el Pull Request de la rama que quieres fusionar
  2. Revisa los cambios en la pestaña "Files changed"
  3. En la pestaña "Conversation", haz clic en Merge pull request"
  4. Opcionalmente, marca "Squash and merge" para combinar commits
  5. Confirma con Confirm merge
⚠️ Precaución: Una vez que haces merge en GitHub, no puedes deshacerlo fácilmente. Asegúrate de revisar bien los cambios antes de confirmar. Si necesitas revertir, tendrás que crear un nuevo commit que revierte los cambios.

Resumen

En esta lección has aprendido:

  • Qué es un merge y por qué es fundamental para trabajar en equipo
  • Los diferentes tipos de merge: fast-forward, recursive, squash
  • Cómo ejecutar un merge paso a paso
  • A identificar y resolver conflictos de forma manual
  • Estrategias para hacer merges exitosos
  • Herramientas y comandos útiles del día a día
🧠 Quiz: Merge en Git

1. ¿Qué tipo de merge ocurre cuando la rama destino no tiene cambios nuevos desde que creaste tu rama?

  • A) Three-way merge
  • B) Fast-forward merge
  • C) Squash merge
  • D) Octopus merge
✅ Respuesta correcta: B) Fast-forward merge. Ocurre cuando Git puede simplemente mover el puntero hacia adelante porque no hay cambios divergentes en la rama destino.

2. ¿Qué debes hacer primero cuando Git indica conflictos durante un merge?

  • A) Eliminar la rama con conflictos
  • B) Editar los archivos en conflicto y resolverlos manualmente
  • C) Reiniciar el computador
  • D) Crear una nueva rama sin resolver
✅ Respuesta correcta: B) Editar los archivos en conflicto y resolverlos manualmente. Los conflictos indican que Git necesita que un humano decida qué cambios mantener.

3. ¿Cuál comando cancela un merge que está en progreso?

  • A) git merge --cancel
  • B) git merge --undo
  • C) git merge --abort
  • D) git merge --stop
✅ Respuesta correcta: C) git merge --abort. Este comando cancela el proceso de merge y regresa tu repositorio al estado anterior al merge.

¡Felicitaciones! Ahora tienes las bases para fusionar ramas en Git de manera efectiva. En la siguiente lección exploraremos cómo resolver conflictos más complejos y las mejores prácticas para trabajo colaborativo.

💡 Próximo paso: Practica creando ramas, haciendo cambios, y fusionándolas. Experimenta con conflictos intencionales para familiarizarte con su resolución. La práctica es la mejor manera de dominar los merges.