# Cómo resolver conflictos de merge en Git y GitHub

**Categoría:** Programación · **Nivel:** Intermedio · **Lectura:** 16 min
**Publicada:** 2026-07-29 · **Actualizada:** 2026-07-29 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/programacion/resolver-conflictos-de-merge-en-git/

## Respuesta rápida

> 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, conviene repasar antes [Git y GitHub desde cero](../git-y-github-desde-cero/index.md): esta guía asume esos conceptos y se concentra solo en los conflictos.

## 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.

> **Un conflicto no es un error tuyo.** 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.

```bash
$ 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.

```text
<<<<<<< HEAD
precio = 100;
=======
precio = 120;
>>>>>>> feature/precio-nuevo
```

- **HEAD.** Todo lo que está entre `<<<<<<< HEAD` y `=======`: la versión que ya tenía tu rama actual, donde estabas parado cuando corriste el merge.
- **La rama entrante.** 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

1. **Intentás la fusión.** Con `git merge nombre-rama`. Si Git puede combinar todo solo, termina ahí; si no, avisa el conflicto y pausa.
2. **Revisás qué quedó sin fusionar.** Con `git status` ves la sección *Unmerged paths* y el archivo marcado `both modified`.
3. **Editás el archivo y decidís el contenido final.** Leés los dos bloques delimitados por los marcadores y dejás el contenido correcto, borrando las tres marcas.
4. **Marcás el archivo como resuelto.** Con `git add archivo`. Si te arrepentís antes de confirmar, `git restore --staged archivo` deshace ese paso.
5. **Confirmás la resolución.** Con `git commit` (Git ya prepara un mensaje de fusión) o con `git merge --continue`, que hace lo mismo.

```bash
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—.

```bash
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

![Cómo se produce y se resuelve un conflicto de merge en Git. Primero, dos ramas —tu rama actual (HEAD) y la rama que fusionás— modifican la misma línea de un archivo con valores distintos, y esas dos versiones convergen en un conflicto que Git no puede resolver solo. Segundo, cómo queda el archivo con los marcadores de conflicto: la etiqueta de apertura <<<<<<< HEAD, debajo tu versión, luego una línea de ======= como separador, después la versión de la rama que fusionás, y por último la etiqueta de cierre >>>>>>> con el nombre de esa rama; todo lo que está entre la apertura y el separador es tu versión, y todo lo que está entre el separador y el cierre es la versión de la otra rama. Tercero, el flujo de resolución en cinco pasos: git merge combina la rama, Git detiene el proceso y avisa el conflicto, se edita el archivo borrando los marcadores y dejando el contenido final, se marca como resuelto con git add, y se confirma con git commit o con git merge --continue. Debajo se muestra la salida de emergencia: git merge --abort cancela el merge y vuelve al estado previo, pero solo funciona antes de confirmar ese commit; después de confirmarlo ya no sirve, y hay que usar git reset o git revert para deshacer.](../../assets/img/guias/git-conflicto-merge.svg)

*El mismo mecanismo de siempre: dos ramas chocan, Git marca el archivo con tres marcadores, y se resuelve editando, con git add y un commit. La salida de emergencia solo funciona antes de confirmarlo.*

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 --abort` después de confirmar el commit.** Ya no tiene efecto; a esa altura hay que usar `git reset` o `git 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 mergetool` resuelve 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](../git-y-github-desde-cero/index.md), 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.

1. **Underc0de, foro.** [Sección Programación](https://underc0de.org/foro/programacion/). 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

2. **Git.** [git-merge](https://git-scm.com/docs/git-merge). Referencia del comando y del mensaje de conflicto.
3. **Git.** [git-status](https://git-scm.com/docs/git-status). La sección Unmerged paths y el estado both modified.
4. **Git.** [git-mergetool](https://git-scm.com/docs/git-mergetool). Cómo se invoca una herramienta de fusión visual configurada.
5. **Git.** [git-rerere](https://git-scm.com/docs/git-rerere). Cómo se graban y reaplican resoluciones de conflictos.
6. **Git.** [Pro Git — Basic Branching and Merging](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging). El flujo de ramas y fusión, con ejemplos de conflicto.
7. **GitHub.** [Resolving a merge conflict using the command line](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line). Cómo se resuelve un conflicto de una solicitud de cambios desde la terminal.

## Guías relacionadas

- [Git y GitHub desde cero](../git-y-github-desde-cero/index.md)
- [Cómo crear pipelines CI/CD con GitHub Actions](../../devops-cloud/como-crear-pipelines-ci-cd-con-github-actions/index.md)
- [Clean code](../clean-code-codigo-limpio-y-mantenible/index.md)
- [Pruebas automáticas con GitHub Actions](../../testing/pruebas-automaticas-con-github-actions/index.md)

URL canónica: https://underc0de.org/guias/programacion/resolver-conflictos-de-merge-en-git/
