Una rama no es una copia de archivos: es un puntero móvil de 41 bytes
Crear una rama en Git no duplica tu código en disco. Una rama es simplemente un archivo de texto plano de 41 bytes en .git/refs/heads/ que guarda el hash de un commit. HEAD es un puntero simbólico que indica en qué rama estás parado.
ref: refs/heads/main Puntero de rama activa: .git/refs/heads/... 3a8f91c78490a1b2c3d4e5f6a7b8c9d0e1f2a3b4 Fast-Forward vs 3-Way Merge: ¿cuándo se crea un merge commit?
Si la rama main no avanzó mientras trabajabas en feature, Git hace un Fast-Forward (solo desliza el puntero de main a la punta). Si main también avanzó, las historias divergieron y Git realiza un 3-Way Merge creando un commit de unión con dos padres.
✓ Sin commits adicionales. El historial permanece perfectamente lineal y limpio.
ℹ Git compara el ancestro común (C2) con C3 y C4. El commit M tiene 2 padres: C3 y C4.
¿Por qué ocurre un conflicto? La máquina no puede adivinar
Git es capaz de fusionar automáticamente cambios si están en archivos diferentes o en líneas separadas. Pero si dos personas modificaron exactamente la misma línea del mismo archivo, Git no tiene criterio de negocio para saber cuál es la correcta.
// config.ts
export const discount = 0.10;
export const currency = 'USD'; Valor original acordado la semana pasada.
// config.ts
export const discount = 0.15;
export const currency = 'USD'; Marketing subió el descuento al 15% en main.
// config.ts
export const discount = 0.20;
export const currency = 'USD'; Tu tarea de Black Friday puso 20% en feature.
⚠️ ¿15% o 20%? Ningún algoritmo puede tomar esa decisión por ti. Git detiene el merge y te cede el control.
Desarmando los marcadores de conflicto en tu editor
Cuando hay conflicto, Git edita tu archivo insertando 3 delimitadores: <<<<<<< HEAD (tu versión actual), ======= (separador divisorio) y >>>>>>> (versión entrante). Resuelve el conflicto eligiendo la opción correcta:
// src/config.ts
<<<<<<< HEAD
export const discount = 0.15; // Versión en main
=======
export const discount = 0.20; // Versión en feature
>>>>>>> feature/login
export const currency = 'USD'; El archivo tiene marcadores activos. Haz clic en una de las 3 opciones para limpiarlo.
git add para marcar resuelto, git commit para sellar
Una vez editado el archivo y eliminados todos los marcadores, debes notificarle a Git que la disputa terminó. El comando git add le indica que el archivo está resuelto en Staging, y git commit sella el merge commit final.
Verifica los archivos en conflicto listados como "both modified".
Abre el archivo, borra los marcadores, elige el código y corre los tests.
Marca el conflicto como resuelto y traslada el archivo limpio al Staging Area.
Genera el commit de unión automático. En versiones modernas: git merge --continue.
Si te equivocaste al resolver, el conflicto es inmanejable o necesitas consultar con un compañero antes de proceder, ejecuta git merge --abort. Git cancelará la fusión y devolverá todo tu repositorio al estado exacto antes de intentar el merge.
Menos conflictos no es suerte: es disciplina arquitectónica
Los conflictos no se evitan rezando, sino diseñando el código y el flujo de trabajo para minimizar las zonas de colisión concurrente entre desarrolladores.
Ramas de vida corta (Short-lived branches)
Una rama que vive 2 días tiene muy pocas probabilidades de conflicto. Una rama que vive 3 semanas acumula cientos de diferencias imposibles de digerir.
Modularidad y archivos pequeños
Si 5 programadores editan un archivo gigante de 3000 líneas (God File), chocarán a diario. Divide en componentes y módulos cohesivos de responsabilidad única.
Sincronizar frecuentemente con main
Trae los cambios de main a tu rama varias veces al día. Resolver un conflicto de 2 líneas hoy es mil veces más fácil que resolver 40 archivos el viernes a la tarde.
Comunicación antes de refactors masivos
Si vas a cambiar el formateador (Prettier/ESLint) o renombrar carpetas clave, avísale al equipo y mergea en una ventana coordinada sin ramas abiertas.