¿Qué es un conflicto de fusión?
Cuando trabajas en equipo con Git, es común que varias personas modifiquen los mismos archivos simultáneamente. Git es muy inteligente combinando cambios, pero hay situaciones donde no puede hacerlo automáticamente. Estas situaciones se denominan conflictos de fusión (merge conflicts).
Imagina que tú y tu compañero están trabajando en el mismo archivo. Tú modificas la línea 5 y tu compañero modifica exactamente la misma línea pero con contenido diferente. Cuando intentas fusionar vuestras ramas, Git no sabe cuál de los dos cambios debe prevalecer. Aquí es donde tú, como desarrollador, debes intervenir.
¿Por qué ocurren los conflictos?
Los conflictos de fusión ocurren por varias razones:
- Ediciones en la misma línea: Dos personas modifican exactamente la misma línea de un archivo.
- Eliminación vs. modificación: Alguien elimina un archivo mientras otro lo modifica.
- Archivos modificados en ambas ramas: El mismo archivo se editó en ambas ramas sin relación entre los cambios.
- Cambios en archivos renombrados: Un archivo se renombra en una rama y se modifica en otra.
Identificando un conflicto de fusión
Cuando intentas fusionar ramas y Git detecta conflictos, te lo notificará inmediatamente. Veamos el proceso paso a paso:
- Inicias la fusión: Ejecutas
git mergeogit pull - Git detecta el problema: Verás un mensaje de error indicando conflictos
- Revisas el estado: Ejecutas
git statuspara ver los archivos en conflicto
Cuando Git no puede fusionar automáticamente, verás un mensaje como este:
Auto-merging archivo.js
CONFLICT (content): Merge conflict in archivo.js
Automatic merge failed; fix conflicts and then commit the result.
<<<<<<< HEAD, ======= y >>>>>>> nombre-rama.Entendiendo las marcas de conflicto
Cuando abres un archivo en conflicto, verás algo similar a esto:
<<<<<<< HEAD
const nombre = 'María García';
=======
const nombre = 'María';
>>>>>>> feature/nueva-funcion
Cada sección tiene un significado importante:
| Marca | Significado |
|---|---|
<<<<<<< HEAD | Indica el inicio de tu configuración actual (la rama donde estás) |
======= | Separador entre los dos bloques de código en conflicto |
>>>>>>> feature/nueva-funcion | Indica el inicio de los cambios de la otra rama |
Estrategias para resolver conflictos
Tienes varias opciones cuando te enfrentas a un conflicto:
1. Aceptar los cambios de la otra rama
Si decides que los cambios de la rama entrante son los correctos, puedes mantener solo esos:
git checkout --theirs archivo.js
git add archivo.js
2. Aceptar tus cambios actuales
Si tus cambios deben prevalecer:
git checkout --ours archivo.js
git add archivo.js
3. Resolver manualmente
Esta es la opción más común. Editas el archivo y decides qué va en cada sección:
- Abre el archivo en tu editor de código
- Revisa ambos bloques de código
- Elimina las tres líneas de marca (
<<<<<<<,=======,>>>>>>>) - Mantén el código que debe quedar o combina ambos cambios según sea necesario
- Guarda el archivo
- Ejecuta
git add archivo.js
Usando herramientas visuales
Aunque puedes resolver conflictos editando texto, las herramientas visuales hacen el proceso mucho más sencillo:
- VS Code: Tiene un sistema de resolución de conflictos integrado con opciones para aceptar uno u otro cambio.
- GitHub Desktop: Muestra los conflictos de forma visual comparando ambos lados.
- Meld: Herramienta gratuita de comparación visual para múltiples sistemas operativos.
- Beyond Compare: Editor profesional con detección de conflictos de Git.
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
git config --global mergetool.prompt false
Después de configurar, puedes usar git mergetool para abrir VS Code y resolver conflictos visualmente.
Completando la resolución
Una vez que has resuelto todos los conflictos en un archivo:
- Ejecuta
git add nombre-archivopara marcar el archivo como resuelto - Repite para cada archivo en conflicto
- Ejecuta
git statuspara verificar que no quedan conflictos pendientes - Finaliza con
git commitpara completar la fusión
Abortando una fusión
Si te encuentras perdido y prefieres empezar de nuevo, puedes abortar la fusión:
git merge --abort
Esto revertirá todo al estado anterior al intento de fusión. Es útil cuando te has confundido o decides que la fusión no era necesaria en este momento.
--abort perderá cualquier trabajo que hayas hecho en la resolución del conflicto. Asegúrate de que quieres descartar todo antes de ejecutarlo.Prevención de conflictos
La mejor estrategia contra los conflictos es evitarlos en la medida de lo posible:
- Comunica con tu equipo: Informa qué archivos estás modificando antes de comenzar.
- Haz pull frecuentemente: Mantén tu rama actualizada con los últimos cambios de la rama principal.
- Trabaja en módulos separados: Asigna diferentes archivos o funcionalidades a diferentes desarrolladores.
- Realiza integraciones frecuentes: No dejes pasar mucho tiempo entre integraciones.
- Usa ramas de corta duración: Cuanto más tiempo exista una rama, mayor probabilidad de conflictos.
«Los conflictos de fusión son como las reuniones de equipo: incómodos cuando son grandes y frecuentes, pero necesarios y manejables cuando se hacen correctamente.»
Conflictos en pull requests
Cuando trabajas con pull requests en GitHub o GitLab, puedes encontrarte con conflictos antes de poder fusionar. GitHub te mostrará qué archivos tienen conflictos y te permitirá resolverlos de dos formas:
- Desde la interfaz web: GitHub permite editar directamente en el navegador.
- Actualizando tu rama: Haz merge de la rama base en tu rama de trabajo y resuelve localmente.
Comandos útiles para conflictos
| Comando | Descripción |
|---|---|
git status | Muestra los archivos en conflicto |
git diff | Muestra las diferencias en archivos modificados |
git log --oneline --merge | Muestra los commits relacionados con el conflicto |
git mergetool | Abre la herramienta visual de merge configurada |
git merge --abort | Cancela la fusión en progreso |
Ejemplo práctico completo
Veamos un ejemplo real paso a paso:
# Estás en la rama develop
# Intentas fusionar la rama feature/login
git merge feature/login
# Git reporta conflicto:
# Auto-merging src/auth.js
# CONFLICT (content): Merge conflict in src/auth.js
# Automatic merge failed.
Ahora revisas el archivo:
// src/auth.js
function validarUsuario(datos) {
<<<<<<< HEAD
if (datos.email.includes('@')) {
return true;
}
=======
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(datos.email);
>>>>>>> feature/login
}
Decides que la validación con expresión regular es mejor, así que editas:
// src/auth.js
function validarUsuario(datos) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(datos.email);
}
Luego completas el proceso:
git add src/auth.js
git commit -m "Merge feature/login: usando validación robusta de email"
# La fusión está completa
¿Cuál de las siguientes NO es una causa común de conflictos de fusión en Git?
- A) Dos desarrolladores modificando la misma línea de un archivo
- B) Uno elimina un archivo mientras otro lo modifica
- C) Un desarrollador hace push a su rama personal
- D) El mismo archivo se modifica en dos ramas diferentes
Conclusión
Los conflictos de fusión son parte natural del trabajo en equipo con Git. Ahora que comprendes cómo ocurren, cómo identificarlos y cómo resolverlos, estás mejor preparado para colaborar efectivamente con otros desarrolladores. Recuerda: los conflictos no son fracasos, son oportunidades para revisar y mejorar el código junto con tu equipo.