Qué es un conflicto (y qué no)

Git combina dos ramas línea por línea. Si cada rama cambió partes distintas de un archivo, las mezcla sola y no te enteras. Hay conflicto cuando las dos cambiaron las mismas líneas, o cuando una rama borró un archivo que la otra modificó: ahí Git no puede adivinar cuál versión es la buena.

Un conflicto no es un error ni daña tu trabajo. Tus commits siguen intactos; el merge simplemente queda a medias hasta que lo termines o lo canceles.

Paso 1: Git se detiene

Imagina que estás en main y quieres traer rama-ana. Las dos ramas cambiaron la línea pan del archivo lista.txt. Lanzas el merge:

git merge rama-ana

Git responde con algo así:

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

Git muestra sus mensajes en el idioma de tu sistema: si lo tienes en español, verás lo mismo traducido. La palabra clave es CONFLICT, que nombra el archivo afectado.

Paso 2: Mira qué archivos tienen conflicto

git status
On branch main You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: lista.txt no changes added to commit (use "git add" and/or "git commit -a")

Los archivos bajo Unmerged paths son los que debes resolver. both modified significa que las dos ramas los cambiaron. Si son muchos, esta lista corta muestra solo los que siguen en conflicto:

git diff --name-only --diff-filter=U

Paso 3: Lee los marcadores

Abre el archivo en tu editor. Git escribió dentro las dos versiones, separadas por marcadores:

Compras
leche
<<<<<<< HEAD
pan de centeno
=======
pan integral
>>>>>>> rama-ana
huevos
  • Entre <<<<<<< HEAD y ======= está tu versión: la de la rama en la que estás parado (aquí, main).
  • Entre ======= y >>>>>>> rama-ana está la versión que llega, la de la rama que intentas traer.
  • Las líneas fuera de los marcadores no tuvieron conflicto y ya están mezcladas.

Paso 4: Decide cómo debe quedar y edita

Tienes tres opciones: quedarte con una de las dos versiones, combinar ambas o escribir algo nuevo. Cualquiera que elijas, borra las tres líneas de marcadores. Si decidimos combinar las dos ideas, el archivo termina así:

Compras
leche
pan integral de centeno
huevos

Antes de seguir, comprueba que no quedó ningún marcador olvidado:

git diff --check

Si no imprime nada, el archivo está limpio. Si queda alguno, avisa con leftover conflict marker y el número de línea. Este comando también señala espacios sobrantes al final de línea, que puedes corregir o ignorar.

Git no te protege de esto Si guardas los marcadores y sigues, Git los tratará como texto normal y acabarán en tu commit. Por eso conviene revisar con git diff --check antes de marcar el archivo como resuelto.

Paso 5: Marca el archivo como resuelto y termina

Avisa a Git de que ese archivo ya está listo:

git add lista.txt

Cuando no queden archivos sin resolver, cierra el merge con un commit:

git commit

Git abre tu editor con el mensaje ya escrito (Merge branch 'rama-ana'); guárdalo y ciérralo. Con git merge --continue logras exactamente lo mismo. Si aún queda algún archivo en conflicto, Git se niega a hacer el commit. Al terminar, el historial muestra la unión de las dos ramas:

git log --oneline --graph
* 717c8a6 Merge branch 'rama-ana' |\ | * 6ca490d pan integral * | 256c106 pan de centeno |/ * 1551e56 base

Los códigos de commit de tu repositorio serán distintos; lo importante es el commit de merge con dos padres arriba del todo.

Atajo: quedarte con una versión completa de un archivo

A veces no hay nada que combinar y quieres una versión entera. Para quedarte con la de tu rama:

git checkout --ours -- lista.txt

Y para quedarte con la que llega de la otra rama:

git checkout --theirs -- lista.txt

Después, git add lista.txt y sigue con el commit como en el paso 5.

Descarta todo lo del otro lado Estos comandos reemplazan el archivo completo, no solo las líneas en conflicto: los cambios del otro lado en ese archivo, aunque no chocaran, se pierden. Úsalos solo si de verdad quieres una de las dos versiones tal cual.

Cuando una rama borró el archivo

El otro tipo de conflicto aparece cuando una rama borró un archivo que la otra modificó:

CONFLICT (modify/delete): lista.txt deleted in rama-borra and modified in HEAD. Version HEAD of lista.txt left in tree. Automatic merge failed; fix conflicts and then commit the result.

En git status el archivo aparece como deleted by them (la rama que traes lo borró) o deleted by us (lo borró la tuya). Aquí no hay marcadores que editar: decides si el archivo se queda o se va. Para conservarlo:

git add lista.txt

Para aceptar el borrado:

git rm lista.txt

En ambos casos, termina con git commit.

Si te arrepientes, cancela

Mientras el merge siga a medias, puedes abandonarlo y volver a como estabas antes de empezar:

git merge --abort
Haz commit antes de mezclar Si empezaste el merge con cambios sin guardar, Git advierte que en algunos casos --abort no podrá reconstruirlos. Guarda tu trabajo con un commit antes de traer otra rama.

Preguntas frecuentes

¿Y si el conflicto aparece en un git pull o en un rebase?

git pull descarga y hace un merge, así que el proceso es el de esta guía. En un rebase el flujo es parecido, pero se termina con git rebase --continue y hay un detalle que confunde: --ours y --theirs se invierten. Durante un rebase, --ours es la rama sobre la que estás reaplicando tus commits y --theirs es tu propio commit. La guía Merge vs. rebase explica cuándo conviene cada uno.

¿Cómo se resuelve un conflicto en una imagen o un PDF?

Git no puede mezclar dentro de un archivo binario, así que no escribe marcadores: deja en tu carpeta la versión de tu rama y lo declara en conflicto. Elige una de las dos con git checkout --ours -- archivo o git checkout --theirs -- archivo, y luego git add archivo.

¿Puedo ver cómo era el texto original antes de los dos cambios?

Sí. Con este ajuste, los próximos conflictos incluirán una tercera sección con la versión base:

git config --global merge.conflictStyle diff3

El archivo quedará así, con el original entre ||||||| y =======:

Compras
leche
<<<<<<< HEAD
pan de centeno
||||||| 7ecd704
pan
=======
pan integral
>>>>>>> rama-ana
huevos

Ver qué había antes suele aclarar quién cambió qué.

¿Hay una forma más cómoda que editar los marcadores a mano?

Sí. Muchos editores de código muestran los conflictos con botones para elegir cada lado, y Git trae git mergetool, que abre la herramienta de comparación que tengas configurada. Editar a mano sigue siendo útil porque funciona en cualquier sitio y te obliga a leer lo que cambió.

¿Cómo evito tener tantos conflictos?

No se pueden eliminar, pero sí reducir: trae los cambios de main a tu rama con frecuencia, así resuelves diferencias pequeñas en vez de una enorme al final; haz commits pequeños y enfocados; y avisa a tu equipo cuando vayas a tocar un archivo que otras personas también están cambiando.