Un conflicto de merge pasa cuando dos ramas modificaron la misma parte de un archivo y Git no puede decidir solo cuál versión dejar: te pide que lo decidas vos. No significa que se rompió nada ni que perdiste trabajo: ambas versiones siguen intactas en sus commits. Cuando pasa, Git detiene la fusión, marca el archivo como sin fusionar y deja dentro los marcadores <<<<<<< HEAD, ======= y >>>>>>> rama con las dos versiones en pugna. Resolverlo es editar esa parte, borrar los marcadores, dejar el contenido final, avisarle a Git con git add y confirmar con un commit. Mientras no confirmes ese commit podés cancelar todo con git merge --abort; después ya no sirve, y hay que usar git reset o git revert. Si todavía no tenés claro qué es un commit o una rama, convine repasar antes Git y GitHub desde cero: esta guía asume esos conceptos y se concentra solo en los conflictos.
Ver índice de contenidos
Qué es un conflicto de merge (y qué no es)
Fusionar (merge) es integrar los cambios de una rama en otra. La mayor parte del tiempo Git lo hace solo: si dos ramas tocaron partes distintas de un archivo, combina ambos cambios sin preguntarte nada. El conflicto aparece cuando las dos ramas modificaron la misma línea (o líneas muy cercanas) de un mismo archivo con contenido distinto: ahí Git no tiene forma de saber cuál versión es la correcta, porque las dos son válidas desde su punto de vista.
Es un evento normal, sobre todo en equipos donde varias personas tocan el mismo archivo, y no implica que el código se haya roto ni que se haya perdido trabajo: ambas versiones siguen intactas, guardadas en sus respectivos commits. Lo único que falta es una decisión humana sobre cuál contenido final dejar, o cómo combinarlos.
Git no te está avisando que hiciste algo mal. Te está avisando que dos historias válidas chocan en el mismo lugar, y que necesita que decidas cuál queda —o cómo se combinan— porque eso es una decisión de contenido, no algo que una máquina pueda resolver sola.
Los marcadores y git status
Cuando ejecutás git merge nombre-rama y hay un conflicto, Git detiene el proceso ahí mismo e imprime un mensaje como CONFLICT (content): Merge conflict in archivo, indicando qué archivo quedó sin fusionar. Si corrés git status en ese momento, aparece una sección llamada Unmerged paths, con el archivo marcado como both modified —lo que en el formato corto de git status aparece como el código UU—: los dos lados modificaron el mismo archivo y ninguno de los dos ganó todavía.
$ 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: precios.js
no changes added to commit (use "git add" and/or "git commit -a")
Dentro del archivo en conflicto, Git no borra nada de las dos versiones: las deja a ambas, delimitadas por tres marcadores.
<<<<<<< HEAD
precio = 100;
=======
precio = 120;
>>>>>>> feature/precio-nuevo
Todo lo que está entre <<<<<<< HEAD y =======: la versión que ya tenía tu rama actual, donde estabas parado cuando corriste el merge.
Todo lo que está entre ======= y >>>>>>>: la versión de la rama que estás fusionando, identificada por su nombre al final.
Las tres líneas de marcadores no son código válido: hay que borrarlas siempre, dejando solo el contenido final que decidiste conservar.
El flujo completo, paso a paso
- Intentás la fusiónCon
git merge nombre-rama. Si Git puede combinar todo solo, termina ahí; si no, avisa el conflicto y pausa. - Revisás qué quedó sin fusionarCon
git statusves la sección Unmerged paths y el archivo marcadoboth modified. - Editás el archivo y decidís el contenido finalLeés los dos bloques delimitados por los marcadores y dejás el contenido correcto, borrando las tres marcas.
- Marcás el archivo como resueltoCon
git add archivo. Si te arrepentís antes de confirmar,git restore --staged archivodeshace ese paso. - Confirmás la resoluciónCon
git commit(Git ya prepara un mensaje de fusión) o congit merge --continue, que hace lo mismo.
git merge nombre-rama
# CONFLICT (content): Merge conflict in archivo
# ...editás el archivo, borrás los marcadores...
git add archivo
git commit
Si el merge afectó a varios archivos, se resuelven uno por uno: volvé a correr git status después de cada git add para ver cuáles siguen apareciendo en Unmerged paths. El commit solo se puede confirmar cuando ya no queda ninguno.
La salida de emergencia: git merge --abort
git merge --abort cancela el merge y devuelve tu rama exactamente al estado en que estaba antes de intentarlo, como si nunca hubiera pasado. Pero tiene una condición temporal que conviene tener clara: funciona solo mientras el merge sigue en curso, antes de confirmar la resolución con un commit. Una vez que confirmaste —con git commit o con git merge --continue—, el merge ya terminó, no hay nada «en curso» que abortar, y el comando deja de tener efecto.
| Antes de confirmar el commit | Después de confirmarlo | |
|---|---|---|
| Comando | git merge --abort | git reset o git revert |
| Qué hace | Cancela la fusión y vuelve al estado previo a intentarla | git reset mueve la rama a un commit anterior; git revert crea un commit nuevo que anula los cambios |
| Riesgo | Ninguno: todavía no se generó ningún commit | git reset reescribe historial local, riesgoso si ya lo compartiste; git revert es seguro para historial ya publicado |
Si te arrepentís después de confirmar, la elección entre git reset y git revert depende de si ya compartiste ese commit con alguien más. Si es local y nadie lo tiene, git reset mueve tu rama a un punto anterior, aunque reescribe historial. Si ya lo subiste, la opción segura es git revert, que no borra el commit de fusión sino que agrega uno nuevo que deshace sus cambios, sin alterar lo que ya está publicado.
No repetir el conflicto: git rerere
git rerere («reuse recorded resolution», reutilizar una resolución grabada) es una función poco conocida que resuelve un problema muy concreto: el mismo conflicto apareciendo una y otra vez, típicamente durante un rebase —una operación que reaplica cada commit de una rama uno por uno sobre otra base, y que puede chocar contra el mismo cambio en cada paso—.
git config --global rerere.enabled true
Con rerere.enabled en true, Git empieza a grabar cómo resolviste cada conflicto: guarda el estado del archivo con los marcadores tal como quedaron y el contenido final que dejaste. La próxima vez que aparece un conflicto con esa misma forma, Git reconoce el patrón grabado y reaplica automáticamente la misma resolución, sin que tengas que repetirla a mano en cada commit del rebase.
Tiene una limitación documentada: rerere reconoce el conflicto por cómo quedan los marcadores en el archivo, así que si el conflicto cambia levemente de forma —otro contexto alrededor, otras líneas— puede no reconocerlo como el mismo caso, o aplicar una resolución que ya no corresponde a ese contexto nuevo. Conviene revisar igual el resultado antes de confirmar, en lugar de confiar en rerere a ciegas.
Resolver desde GitHub
Todo lo anterior es válido tanto si trabajás desde la terminal como si el conflicto aparece en una solicitud de cambios (pull request) de GitHub: es el mismo mecanismo de Git por debajo, solo cambia la interfaz. Cuando una solicitud no se puede fusionar de forma automática, GitHub lo avisa en la propia página y, para conflictos simples, ofrece un editor web con los mismos marcadores que verías en tu terminal; ahí elegís el contenido final y GitHub genera un commit de resolución sobre tu rama, igual que si lo hubieras resuelto localmente y subido el resultado con push.
Ese editor web está pensado para casos acotados. Si el conflicto es más complejo o preferís tu propio editor, seguí trayendo la rama a tu máquina, resolviendo en la terminal —con git mergetool si tenés una herramienta visual configurada— y subiendo el resultado, lo que actualiza automáticamente la solicitud en GitHub.
Errores frecuentes
- Creer que se rompió algo o que se perdió trabajo. Un conflicto solo significa que Git necesita que decidas vos; ambas versiones siguen intactas en sus commits.
- Editar el archivo y olvidarse de
git add. Sin ese paso, Git no sabe que ya resolviste el conflicto y no te deja continuar. - Usar
git merge --abortdespués de confirmar el commit. Ya no tiene efecto; a esa altura hay que usargit resetogit revert. - Pensar que resolver en GitHub es otro mecanismo. Es el mismo Git por debajo; la web solo cambia la interfaz para casos simples.
- Quedar atrapado entre marcadores sin saber qué borrar. Suele pasar por no tener una herramienta de fusión configurada;
git mergetoolresuelve ese problema.
Preguntas frecuentes
¿Qué significa exactamente «CONFLICT (content): Merge conflict in archivo»?
Es el mensaje que imprime git merge cuando intenta combinar dos ramas y encuentra que ambas modificaron la misma parte de un mismo archivo con contenido distinto, así que no puede fusionarlas de forma automática. La palabra content especifica el tipo de conflicto: se refiere a un choque dentro del contenido del archivo, a diferencia de otros tipos de conflicto que Git también reporta, como cuando una rama borra un archivo y la otra lo modifica. Después de ese mensaje, Git no aborta el proceso completo: detiene únicamente la fusión de ese archivo puntual y sigue con los demás si los hay, así que un merge con varios archivos puede terminar con algunos ya combinados sin problema y otros marcados como conflicto. Por eso conviene correr git status inmediatamente después de ver el mensaje: ahí aparece la lista completa de archivos con conflicto bajo la sección Unmerged paths, con el estado both modified para los que, como en este caso, fueron modificados por las dos ramas. El mensaje no indica ningún error de tu parte ni un problema en el repositorio: es exactamente el comportamiento esperado de Git cuando dos historias de cambios se superponen en el mismo lugar, y la fusión queda en pausa hasta que resolvés manualmente ese archivo, lo marcás con git add y confirmás con un commit.
¿Cómo sé qué parte del código es mía y cuál de la otra rama?
Los marcadores que Git deja en el archivo siguen siempre el mismo orden, sin importar qué dos ramas estés fusionando. Todo lo que aparece entre la línea <<<<<<< HEAD y la línea ======= es la versión que ya tenía tu rama actual, es decir, la rama en la que estabas parado cuando ejecutaste git merge; HEAD es, en este contexto, un apodo para «donde estás vos ahora». Todo lo que aparece entre la línea ======= y la línea >>>>>>> nombre-rama es la versión que trae la rama que estás intentando fusionar, y Git escribe el nombre real de esa rama al lado de la marca de cierre para que sepas de dónde vino. Esta convención no cambia según la dirección del merge: si fusionás la rama B dentro de la rama A, el bloque de arriba (HEAD) siempre va a ser el contenido de A, y el de abajo, el de B, porque HEAD apunta a la rama donde estás parado, no a un lado fijo del conflicto. Tu tarea como persona es leer ambos bloques, decidir qué contenido final tiene sentido —puede ser uno de los dos, una combinación de ambos, o algo distinto a los dos— y dejar ese contenido en el archivo, borrando las tres líneas de marcadores, que no son código válido y romperían el archivo si quedaran ahí.
¿Cómo cancelo un merge si me arrepiento a mitad de camino?
Con git merge --abort, pero hay una condición temporal que conviene tener clara: ese comando solo funciona mientras el merge sigue en curso, es decir, mientras todavía no confirmaste la resolución con un commit. Ejecutarlo en ese momento deshace por completo el intento de fusión y devuelve tu rama exactamente al estado en el que estaba antes de correr git merge, como si nunca lo hubieras intentado; los cambios de la otra rama vuelven a quedar afuera, y podés retomarlo más tarde con calma. El problema aparece si ya resolviste los conflictos, hiciste git add y confirmaste con git commit (o con git merge --continue, que hace lo mismo): en ese punto el merge ya terminó, ya no hay nada «en curso» que abortar, y git merge --abort directamente no tiene efecto porque no hay ningún proceso de fusión pendiente al que aplicarse. Si te arrepentís después de ese commit, las herramientas cambian: si el commit todavía es local y no lo compartiste con nadie, git reset te permite mover tu rama a un punto anterior, aunque reescribe el historial local. Si ya lo subiste y otras personas pueden tener ese historial, la opción más segura es git revert, que no borra el commit de fusión sino que crea uno nuevo que anula sus cambios, preservando el historial tal como quedó. La clave para no llegar tarde es recordar: --abort sirve antes de confirmar, no después.
¿Qué hago si tengo el mismo conflicto una y otra vez en cada rebase?
Ese patrón es exactamente el que resuelve git rerere, que significa reuse recorded resolution (reutilizar una resolución grabada). Se activa con git config rerere.enabled true (o --global para que valga en todos tus repositorios), y a partir de ahí Git empieza a grabar cómo resolviste cada conflicto: guarda el estado del archivo con los marcadores tal como quedaron y el contenido final que dejaste después de resolverlo. La próxima vez que aparezca un conflicto con esa misma forma —algo muy habitual durante un rebase, porque un rebase reaplica cada commit uno por uno y puede chocar contra el mismo cambio en cada paso—, Git reconoce el patrón grabado y aplica automáticamente la misma resolución, sin que tengas que repetir el trabajo manual en cada commit del rebase. Es una herramienta que rinde muchísimo en rebases largos o que se repiten, porque evita resolver diez veces un conflicto que en el fondo es siempre el mismo. Tiene una limitación documentada que conviene conocer: rerere reconoce el conflicto por cómo quedan los marcadores en el archivo, así que si el conflicto cambia levemente de forma —otras líneas alrededor, un contexto distinto— puede no reconocerlo como el mismo caso y no aplicar nada, o aplicar una resolución que ya no es la correcta para ese contexto nuevo. Por eso conviene revisar igual el resultado antes de confirmar, en lugar de confiar en rerere a ciegas.
¿Se resuelven igual los conflictos en la terminal que en un pull request de GitHub?
Sí, es el mismo mecanismo de fusión de Git por debajo; lo único que cambia es la interfaz desde la que lo operás. Cuando una solicitud de cambios (pull request) en GitHub no se puede fusionar de forma automática porque hay conflictos, GitHub lo muestra con un aviso en la propia página de la solicitud, y para conflictos simples ofrece un editor web donde ves los mismos bloques delimitados por marcadores que verías en tu terminal, elegís qué contenido final dejar, y GitHub genera un commit de resolución sobre tu rama, igual que hubiera quedado si lo resolvías vos localmente y subías el resultado con push. La diferencia práctica es de alcance: el editor de conflictos de GitHub está pensado para casos acotados, con pocos archivos y cambios sencillos de decidir mirando el texto; si el conflicto es más complejo, involucra varios archivos, o preferís usar tu propio editor o una herramienta de fusión visual, la vía recomendada sigue siendo traer la rama a tu máquina, correr git merge o git pull en tu terminal, resolver ahí con las mismas herramientas de siempre (incluido git mergetool si lo tenés configurado) y subir el resultado con push, lo que actualiza automáticamente la solicitud de cambios en GitHub. En ningún caso GitHub inventa una forma distinta de fusionar: usa Git como motor, y la web es una capa de comodidad para resolver sin salir del navegador cuando el caso lo permite.
¿Qué herramienta visual conviene para no editar marcadores a mano?
Git no impone ninguna herramienta: el comando git mergetool abre la que tengas configurada en tu entorno, y sirve para no tener que leer los marcadores como texto plano y decidir a ojo. En lugar de eso, una herramienta de fusión visual te muestra habitualmente tres paneles —tu versión, la versión de la rama entrante y, en algunos casos, el ancestro común de las dos— y te deja elegir bloque por bloque cuál contenido final aplicar, o editar directamente un panel con el resultado, sin la sobrecarga de leer <<<<<<<, ======= y >>>>>>> a mano en cada conflicto. Muchos editores de código modernos, incluido Visual Studio Code, incorporan su propio editor de fusión de varios paneles y pueden configurarse como la herramienta que usa git mergetool, de modo que resolver un conflicto se sienta parte del mismo flujo de edición que ya usás para programar, en lugar de una tarea aparte. Sea cual sea la herramienta elegida, el mecanismo de fondo no cambia: al terminar, hay que marcar el archivo como resuelto con git add y confirmar con un commit, igual que si lo hubieras editado en un bloc de notas. La herramienta visual ahorra errores de lectura y hace más cómoda la decisión, pero no la reemplaza: elegir qué contenido final tiene sentido sigue siendo trabajo humano.
Fuentes
Documentación oficial consultada para esta guía. Fecha de consulta: 29 de julio de 2026.
Aportes de la comunidad Underc0de
Se buscó con varias variantes y no existe, al día de esta consulta, ningún hilo del foro ni artículo del blog dedicado específicamente a conflictos de merge en Git. La pieza interna relacionada es la guía ya publicada en este portal, Git y GitHub desde cero, que cubre el flujo básico pero no profundiza en conflictos: se enlaza como guía hermana a lo largo del texto, no como fuente de esta sección.
- Underc0de, foro. Sección Programación. No se encontró un hilo específico sobre conflictos de merge; se enlaza la sección general como referencia de la comunidad.
Documentación oficial
- Git. git-merge. Referencia del comando y del mensaje de conflicto.
- Git. git-status. La sección Unmerged paths y el estado both modified.
- Git. git-mergetool. Cómo se invoca una herramienta de fusión visual configurada.
- Git. git-rerere. Cómo se graban y reaplican resoluciones de conflictos.
- Git. Pro Git — Basic Branching and Merging. El flujo de ramas y fusión, con ejemplos de conflicto.
- GitHub. Resolving a merge conflict using the command line. Cómo se resuelve un conflicto de una solicitud de cambios desde la terminal.