Resolución de conflictos

Lectura
30 min~8 min lectura

🔀 Resolución de Conflictos en Git

Has estado trabajando tranquilo en tu rama, haciendo commits, cuando de repente intentas hacer un git merge o git pull y aparece algo así:

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

¡Felicidades! Has encontrado tu primer conflicto de merge. No te preocupes, en esta lección aprenderás exactamente qué son, por qué ocurren y cómo resolverlos como un profesional.

CONCEPTO CLAVE
Un conflicto de merge ocurre cuando Git no puede resolver automáticamente las diferencias entre dos ramas porque las mismas líneas de código fueron modificadas en ambas. Git necesita que tú decidas cuál versión mantener o cómo combinarlas.

¿Por Qué Ocurren los Conflictos?

Los conflictos son una consecuencia natural del trabajo colaborativo. Ocurren porque:

  • Múltiples desarrolladores modifican el mismo archivo simultáneamente
  • Alguien edita una función que tú también estás editando
  • Se borran archivos en una rama y se modifican en otra
  • Los cambios en diferentes ramas afectan las mismas líneas de código
📌 Dato importante: Los conflictos no son un error ni una falla de Git. Son un mecanismo de seguridad que evita que se pierdan cambios automáticamente. Git te da el control total sobre qué versión del código finalmente se queda.

Identificando un Conflicto

Cuando intentas hacer un merge y hay conflictos, Git te lo indica claramente:

  1. El comando git merge o git pull se detiene
  2. Aparece el mensaje "CONFLICT" junto al archivo afectado
  3. El archivo conflictivo tendrá marcadores especiales en su contenido
  4. Puedes verificar todos los archivos en conflicto con git status

Los Marcadores de Conflicto

Cuando abres un archivo con conflicto, verás algo como esto:

<<<<<<< HEAD
const nombre = "María";
=======
const nombre = "Carlos";
>>>>>>> rama-login

function saludar() {
  console.log("Hola " + nombre);
}

Desglosemos estas secciones:

Marcador Significado
<<<<<<< HEAD Indica el inicio del conflicto. Todo lo que sigue es tu rama actual (la que estás mergingando)
======= Separador entre los dos cambios en conflicto
>>>>>>> rama-login Indica el fin del conflicto y el nombre de la otra rama
💡 Consejo: Después de >>>>>>> siempre verás el nombre de la rama o commit que estás trayendo. Esto te ayuda a recordar de dónde viene cada cambio.

Resolviendo Conflictos Paso a Paso

Ahora viene la parte práctica. Aquí está el proceso completo para resolver conflictos:

Paso 1: Identificar Todos los Archivos en Conflicto

git status
# Verás algo como:
# Unmerged paths:
#   both modified:   src/app.js
#   both modified:   src/utils.js

Paso 2: Abrir los Archivos Afectados

Abre cada archivo en tu editor de código favorito. Verás los marcadores de conflicto que mostramos antes.

Paso 3: Decidir la Estrategia de Resolución

Tienes cuatro opciones para cada conflicto:

  1. Mantener solo tu versión (HEAD): Borra todo incluyendo los marcadores y los cambios de la otra rama
  2. Mantener solo la otra versión: Borra todo incluyendo los marcadores y tus cambios
  3. Combinar ambas versiones: Integra los cambios de ambas ramas de forma manual
  4. Escribir algo completamente nuevo: A veces la mejor solución es un código diferente a ambas versiones

Paso 4: Editar el Archivo

Elimina los marcadores de conflicto y deja únicamente el código que deseas:

# ANTES (con marcadores):
<<<<<<< HEAD
const nombre = "María";
=======
const nombre = "Carlos";
>>>>>>> rama-login

# DESPUÉS (resuelto):
const nombre = "María García";  // Combinamos: nombre + apellido

# O si decides usar la otra versión:
const nombre = "Carlos";

# O si combinas ambas:
const nombre = "María";
const segundoNombre = "Carlos";

Paso 5: Guardar y Marcar como Resuelto

Después de editar cada archivo:

git add src/app.js

# Si tienes varios archivos:
git add .

Paso 6: Completar el Merge

git commit -m "Merge rama-login: resuelvo conflictos en app.js"

# Si Git abrió el editor automáticamente, simplemente guarda y cierra
⚠️ Advertencia: No omitas el mensaje de commit después de resolver conflictos. Si Git abre el editor, puedes modificar el mensaje, pero el commit se creará automáticamente al guardar. Un commit de merge sin mensaje puede causar confusión.

Usando Visual Studio Code para Resolver Conflictos

VS Code tiene herramientas integradas que hacen la resolución de conflictos mucho más fácil:

📌 Panel de Conflictos de VS Code: Cuando abres un archivo con conflicto, aparece un menú de tres opciones en la esquina superior derecha que te permiten aceptar la versión actual, la entrante, o ambas.

Funciones Útiles de VS Code:

  • Resolución con un clic: El editor resalta en colores las diferencias y ofrece botones para aceptar cambios
  • Vista lado a lado: Puedes ver ambas versiones simultáneamente
  • Resaltado de sintaxis: El código dentro de los marcadores mantiene los colores
  • GitLens y extensiones: Herramientas adicionales para gestión visual de conflictos
# En VS Code puedes:
# 1. Hacer clic en "Accept Current Change"  → Usa tu versión
# 2. Hacer clic en "Accept Incoming Change"  → Usa la otra versión  
# 3. Hacer clic en "Accept Both Changes"     → Mantiene las dos
# 4. Editar manualmente el código

Estrategias para Evitar Conflictos

💡 Prevención es mejor que cura: Aunque no siempre se pueden evitar los conflictos, estas prácticas reducen significativamente su frecuencia.
Estrategia Descripción Beneficio
Sincroniza frecuentemente Haz git pull o git merge main regularmente en tu rama Resuelves conflictos pequeños en lugar de grandes
Comunica con tu equipo Avisa cuando vayas a editar archivos importantes Coordina quién modifica qué
Ramificaciones cortas Mergear ramas pequeñas y frecuentes Menos líneas en conflicto
Extraer lógica a funciones Divide archivos grandes en módulos pequeños Menos probabilidad de conflicto
Rebase en lugar de merge Usa git rebase main en vez de fusionar ramas Historial lineal, conflictos en tu rama local

Conflictos Durante un Rebase

Los conflictos también pueden ocurrir durante un git rebase. El proceso es similar, pero con una diferencia clave:

CONCEPTO CLAVE
En un rebase, los commits se aplican uno por uno sobre la base nueva. Si hay un conflicto en el commit 3, debes resolverlo antes de continuar con el commit 4. Después de resolver, usas git add y git rebase --continue.
# Durante un rebase con conflicto:
# 1. Resuelve el conflicto en el archivo

git add archivo-resuelto.js

# 2. Continúa con el siguiente commit
git rebase --continue

# Si quieres abortar todo el rebase:
git rebase --abort

# Si quieres saltarte este commit problemático:
git rebase --skip
⚠️ Cuidado con --skip: Saltar un commit durante un rebase elimina ese commit permanentemente. Solo hazlo si estás seguro de que no necesitas esos cambios.

Abortar un Merge Conflictivo

A veces simplemente quieres empezar de nuevo. Git te permite revertir un merge:

# Abortar el merge en curso
git merge --abort

# Esto revertirá todo al estado antes del merge
git status  # Verás que estás de vuelta en tu rama original
Un buen desarrollador sabe cuándo resolver un conflicto y cuándo retroceder y replanificar. Abortar no es rendirse, es tomar una decisión inteligente.

Herramientas Avanzadas para Conflictos

Ver más: Herramientas externas de merge

Para conflictos complejos, puedes usar herramientas dedicadas:

  • KDiff3: Gratuita, muestra tres paneles (base, local, remoto)
  • Beyond Compare: Potente, muy usada en industria
  • Meld: Open source, interface simple
  • P4Merge: De Perforce, gratuita para uso personal

Configúralas con:

git config --global merge.tool nombre-herramienta
git mergetool

Buenas Prácticas Post-Conflicto

  1. Prueba siempre el código: Ejecuta los tests después de resolver conflictos
  2. Revisa el código completo: Asegúrate de que la lógica tenga sentido
  3. Comunica a tu equipo: Si el conflicto involucraba código de otros, notifícales
  4. Documenta decisiones: En el mensaje de commit explica por qué elegiste cierta versión
  5. Haz push: Sube los cambios resueltos lo antes posible
# Ejemplo de buen mensaje de commit post-conflicto:
git commit -m "Merge feature/pagos: resuelvo conflicto en calculo.js

- Mantengo mi validación de email del frontend
- Agrego la función de sanitización de backend
- Resuelto conflicto con María sobre formato de fechas

Verifico: todos los tests pasan ✓"
📌 Recuerda: Un conflicto resuelto no significa que algo salió mal. Significa que dos personas trabajaron simultáneamente en código importante. Los conflictos son una señal de actividad colaborativa, no de problemas.

Resumen Rápido

Situación Comando
Ver archivos en conflicto git status
Ver diferencias git diff
Marcar como resuelto git add archivo.js
Completar merge git commit
Abortar merge git merge --abort
Continuar rebase git rebase --continue
Herramienta visual git mergetool
🧠 Quiz: Resolución de Conflictos

¿Cuál es el orden correcto para resolver un conflicto de merge?

  • A) Hacer git push, resolver conflicto, hacer git commit
  • B) Ver los marcadores, editar el archivo, hacer git add, hacer git commit
  • C) Hacer git abort, hacer git pull, resolver
  • D) Eliminar la rama, crear nueva rama, empezar de nuevo
✅ Respuesta correcta: B) Primero ves los marcadores de conflicto en el archivo, editas manualmente dejando el código que deseas, luego haces git add para marcarlo como resuelto, y finalmente git commit para completar el merge.
🧠 Quiz: Conflictos

¿Qué significa el marcador <<<<<<< HEAD en un archivo?

  • A) El inicio de tu archivo local
  • B) El inicio de la sección en conflicto de tu rama actual (HEAD)
  • C) Indica que el archivo está corrupto
  • D) Marca el final de los cambios remotos
✅ Respuesta correcta: B) <<<<<<< HEAD marca el inicio de la sección en conflicto. Todo entre este marcador y el separador ======= representa los cambios de tu rama actual (HEAD). Después del ======= vienen los cambios de la otra rama.

Conclusión

Los conflictos de merge pueden parecer intimidantes al principio, pero con práctica se convierten en algo rutinario. Recuerda: cada conflicto es simplemente Git pidiéndote que tomes una decisión informada sobre el código. Con las técnicas de esta lección, podrás resolver cualquier conflicto de manera eficiente y mantener tu código funcionando correctamente.

En la próxima lección, exploraremos las estrategias de branching para equipos y cómo organizar el flujo de trabajo para minimizar conflictos desde el diseño inicial del proyecto.