lección 6
Conflictos de merge: cuando dos personas tocan lo mismo
Qué es un conflicto, por qué ocurre, y cómo resolverlo sin pánico. Git no está roto — solo necesita tu decisión.
⏱ 55 min
El momento ha llegado. El temido conflicto de merge. Si has buscado "git conflict" en Google alguna vez, habrás visto foros llenos de gente aterrorizada preguntando "¿cómo deshago todo?". Tranquilo. Un conflicto de merge NO es un error. NO es que hayas roto algo. NO es que Git esté fallando. Es simplemente Git diciéndote: "oye, dos personas cambiaron la misma línea y yo no sé cuál versión quieres mantener — necesito que TÚ decidas".
Piensa en esta analogía: imagina que compartes un documento con un amigo. Tú cambias el título a "Reporte de Ventas Q4". Tu amigo, sin saber de tu cambio, lo cambia a "Informe Trimestral Q4". Cuando intentan fusionar ambas versiones, el sistema no puede adivinar cuál quieres. ¿Reporte o Informe? ¿Q4 o Trimestral? Necesita que un humano decida. Eso es un conflicto.
### Cuándo ocurren los conflictos
Los conflictos NO ocurren cuando dos personas editan el mismo ARCHIVO — eso Git lo maneja perfectamente (mientras sean líneas diferentes). Los conflictos ocurren cuando dos personas editan las MISMAS LÍNEAS del mismo archivo. Git puede fusionar automáticamente cambios en líneas distintas, pero cuando la línea 15 fue modificada en ambas branches, no tiene forma de saber cuál es la correcta.
- SIN conflicto: Ana edita línea 5, Pedro edita línea 42 del mismo archivo → Git fusiona sin problemas
- SIN conflicto: Ana edita archivo_a.py, Pedro edita archivo_b.py → archivos distintos, cero problemas
- CON conflicto: Ana edita línea 15, Pedro edita línea 15 del mismo archivo → Git necesita ayuda
- CON conflicto: Ana borra un archivo que Pedro modificó → Git no sabe si borrar o mantener
### Provocar un conflicto a propósito (para perder el miedo)
La mejor forma de perder el miedo a los conflictos es provocar uno intencionalmente. Vamos a hacerlo paso a paso:
1# Empezamos en main con un archivo2git switch main34# Crear un archivo de configuración5# 🟦 Windows (PowerShell):6# Set-Content config.py -Value "DB_HOST = 'localhost'\nDB_PORT = 5432\nDB_NAME = 'ventas'"7# 🍎 Mac:8# printf "DB_HOST = 'localhost'\nDB_PORT = 5432\nDB_NAME = 'ventas'" > config.py910git add config.py11git commit -m "feat: archivo de configuración de base de datos"
Preparamos el escenario del conflicto
1# Creamos la branch de Ana (cambia el host)2git switch -c feature/ana-produccion3# Ana cambia DB_HOST a 'prod-server.empresa.com' en config.py4# (edita el archivo manualmente o con sed/PowerShell)5git add config.py6git commit -m "feat: apuntar a servidor de producción"78# Volvemos a main y creamos la branch de Pedro (también cambia el host)9git switch main10git switch -c feature/pedro-staging11# Pedro cambia DB_HOST a 'staging.empresa.com' en config.py12git add config.py13git commit -m "feat: apuntar a servidor de staging"
Dos branches que tocan la misma línea
1# Fusionamos la branch de Ana primero (sin problemas)2git switch main3git merge feature/ana-produccion4# Fast-forward, todo bien. Main ahora tiene 'prod-server.empresa.com'56# Ahora intentamos fusionar la branch de Pedro...7git merge feature/pedro-staging8# ¡¡CONFLICTO!!9# Auto-merging config.py10# CONFLICT (content): Merge conflict in config.py11# Automatic merge failed; fix conflicts and then commit the result.
¡BOOM! El conflicto aparece
No entres en pánico. Git te dice exactamente qué pasó: hay un conflicto en config.py y necesita que lo resuelvas. Veamos qué aspecto tiene el archivo ahora:
### Anatomía de un conflicto: las marcas extrañas
Cuando abres config.py después del conflicto, ves algo así:
1<<<<<<< HEAD2DB_HOST = 'prod-server.empresa.com'3=======4DB_HOST = 'staging.empresa.com'5>>>>>>> feature/pedro-staging6DB_PORT = 54327DB_NAME = 'ventas'
Así se ve un conflicto en el archivo
Las marcas de conflicto tienen tres partes:
- <<<<<<< HEAD: inicio de TU versión (la branch donde estás, en este caso main que ya tiene los cambios de Ana)
- =======: separador entre las dos versiones
- >>>>>>> feature/pedro-staging: fin de la versión ENTRANTE (la branch que intentas fusionar)
Git te muestra ambas versiones y te dice: "elige una, combínalas, o escribe algo completamente diferente. Tú decides". Resolver el conflicto es tan simple como: 1) borrar las marcas (<<<, ===, >>>), 2) dejar el código que quieres, 3) guardar y commitear.
### Resolver el conflicto: 3 opciones
Tienes tres opciones para resolver:
1# OPCIÓN 1: Quedarte con la versión de Ana (HEAD/main)2DB_HOST = 'prod-server.empresa.com'3DB_PORT = 54324DB_NAME = 'ventas'56# OPCIÓN 2: Quedarte con la versión de Pedro7DB_HOST = 'staging.empresa.com'8DB_PORT = 54329DB_NAME = 'ventas'1011# OPCIÓN 3: Combinar ambas (lo más inteligente en este caso)12DB_HOST_PROD = 'prod-server.empresa.com'13DB_HOST_STAGING = 'staging.empresa.com'14DB_HOST = DB_HOST_PROD # Cambiar según entorno15DB_PORT = 543216DB_NAME = 'ventas'
Tres formas de resolver el mismo conflicto
1# Después de editar el archivo y resolver el conflicto:23# 1. Añadir el archivo resuelto al staging4git add config.py56# 2. Completar el merge con un commit7git commit -m "merge: resolver conflicto de host DB (usar prod por defecto)"89# ¡Hecho! El conflicto está resuelto y el merge completado.
Completar el merge después de resolver el conflicto
VS Code tiene una interfaz visual INCREÍBLE para conflictos. Cuando abres un archivo con conflicto, te muestra botones: "Accept Current", "Accept Incoming", "Accept Both". Es mucho más cómodo que editar las marcas a mano. Usa la herramienta, no seas masoquista.
### El plan de escape: abortar el merge
Si ves el conflicto y piensas "no tengo ni idea de qué hacer aquí", puedes abortar el merge y volver al estado anterior como si nada hubiera pasado:
1# "¡ABORTAR! Quiero volver a como estaba antes del merge"2git merge --abort34# Todo vuelve a la normalidad. main está como estaba.5# Puedes hablar con tu compañero y resolver el conflicto juntos después.
git merge --abort: tu botón de pánico
NUNCA hagas commit de un archivo con las marcas de conflicto (<<<<<<, =======, >>>>>>). Eso mete basura en tu código. Si ves esas marcas en un archivo, el conflicto NO está resuelto. Git te avisará si intentas commitear archivos sin resolver, pero por si acaso: siempre verifica.
### Prevenir conflictos (no eliminarlos)
Los conflictos son inevitables en equipos que trabajan activamente. No puedes eliminarlos, pero puedes minimizarlos:
- PRs pequeños y frecuentes: cuanto menos tiempo pases en tu branch, menos diverge de main
- git pull frecuente: actualiza tu branch con los cambios de main regularmente
- Comunicación: si sabes que tu compañero está tocando el mismo archivo, hablen
- Archivos modulares: funciones pequeñas en archivos separados = menos colisiones
- No dejes branches abiertas semanas: mientras más viejas, más conflictos acumulan
Truco de senior: antes de crear un PR, haz git switch main → git pull → git switch mi-branch → git merge main. Esto trae los últimos cambios de main a TU branch ANTES de pedir review. Si hay conflictos, los resuelves tú en tu branch (donde es seguro) en vez de que aparezcan al fusionar en main.
## ejercicios
Provoca y resuelve un conflicto
Escribe la secuencia completa de comandos para provocar un conflicto intencionalmente y resolverlo. Crea dos branches que modifiquen la misma línea de un archivo.
Lee y entiende las marcas de conflicto
Dado un archivo con marcas de conflicto, escribe un script Python que identifique y muestre las dos versiones en conflicto.
Actualiza tu branch con los últimos cambios de main
Tu branch feature/reportes lleva 3 días abierta. Main ha recibido cambios de otros compañeros. Escribe los comandos para actualizar tu branch con lo último de main ANTES de crear el PR.
Regístrate para guardar tu progreso.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...