Para resolver conflictos de merge con IA de forma segura, primero haz que el conflicto sea legible, luego dale a un agente de código la intención de ambos lados y reglas claras, y acepta el resultado solo cuando git confirme que no quedan marcadores de conflicto y tus tests pasen. Agentes como Claude Code y Codex son realmente útiles aquí: leen las dos versiones, el ancestro común y el código de alrededor más rápido que tú, y pueden combinar dos cambios en lugar de elegir uno. Su fallo típico es igual de claro: cuando la intención de un lado no está clara, se quedan con el lado que compila y descartan el otro sin decir nada.
Esta guía cubre por qué aparecen los conflictos (y por qué los agentes en paralelo los vuelven más frecuentes), un flujo paso a paso de git status a git merge --continue, una plantilla de prompt, rebase frente a merge, git rerere, una comprobación previa al merge y cómo evitar la mayoría de conflictos desde el principio. Los comandos de Git están contrastados con la documentación oficial de git-scm.com a octubre de 2026.
Por qué aparecen los conflictos de merge
Cuando Git fusiona dos ramas, compara ambas con su ancestro común. Los cambios en zonas distintas de un archivo se combinan solos. Cuando los dos lados cambiaron la misma zona, Git no puede elegir, así que se detiene y escribe ambas versiones en el archivo entre marcadores de conflicto. Eso es un conflicto textual.
Los tipos más habituales:
- Conflicto de contenido: las dos ramas editaron las mismas líneas del mismo archivo.
- Modificar/borrar: una rama cambió un archivo y la otra lo borró o lo movió.
- Archivos generados: lockfiles, snapshots, salida compilada o paquetes de traducción que ambas ramas regeneraron.
Hay además un conflicto que Git no ve: el conflicto semántico. Dos ramas tocan archivos distintos, se fusionan sin problemas y aun así se rompen entre sí; por ejemplo, una cambia la firma de una función y la otra añade una nueva llamada. Solo los tests sobre el resultado fusionado lo detectan; el artículo sobre la cola de merge lo explica con un ejemplo.
Por qué los agentes en paralelo multiplican los conflictos
Varios agentes a la vez, cada uno en su propio git worktree, no se pisan los archivos mientras trabajan. Pero eso no evita el conflicto: lo traslada al momento del merge. Cada agente trabaja desde la base con la que empezó y nunca ve lo que cambiaron los demás. Algunos archivos atraen conflictos una y otra vez:
- tablas de rutas, configuraciones de inyección de dependencias y otros registros donde cada funcionalidad añade una línea,
- archivos barrel (
index.ts) y tipos compartidos, package.jsony su lockfile,- archivos de traducción, changelogs y archivos de configuración.
La minuciosidad de los agentes también juega en contra: reformatean un archivo que solo debían tocar, renombran un helper “ya que estaban” o arreglan un aviso de lint ajeno. Cada uno de esos cambios amplía la zona que ambas ramas han modificado.
Paso 1: para y mira antes de nada
Cuando un merge o un rebase se detiene, averigua dónde estás antes de pedirle a nadie, humano o agente, que lo arregle:
git status # qué operación, qué archivos están "both modified"
git diff --name-only --diff-filter=U # solo los archivos sin fusionar
--diff-filter=U selecciona las rutas sin fusionar, lo que te da una lista limpia para pasarle al agente. Ten presentes también las salidas. Si el conflicto es mayor de lo esperado, todavía no se ha perdido nada:
git merge --abort # volver al estado anterior al merge
git rebase --abort # volver a donde estaba la rama antes del rebase
La documentación de Git recomienda hacer commit o stash de tus cambios antes de ejecutar git merge, porque --abort no siempre puede reconstruir el trabajo sin commitear. Lo mismo vale para el worktree de un agente: deja que haga commit antes de fusionar nada en él.
Paso 2: cambia a zdiff3 para ver la base
Por defecto, Git solo muestra los dos lados:
<<<<<<< HEAD
const timeout = config.timeout ?? 30_000;
=======
const timeout = getTimeout(config);
>>>>>>> feature/retry
Con esto no sabes cómo era la línea original, así que tampoco sabes qué pretendía cada lado. Cambia el estilo de conflicto a zdiff3 (llegó en Git 2.35; en versiones anteriores usa diff3):
git config --global merge.conflictStyle zdiff3
Ahora el conflicto incluye el ancestro común tras un marcador |||||||:
<<<<<<< HEAD
const timeout = config.timeout ?? 30_000;
||||||| base
const timeout = config.timeout;
=======
const timeout = getTimeout(config);
>>>>>>> feature/retry
Ahora sí se entiende: un lado añadió un valor por defecto y el otro movió la lectura a una función. La resolución correcta probablemente conserva ambos, por ejemplo poniendo el valor por defecto dentro de getTimeout. Según la documentación de git-config, zdiff3 es como diff3 pero saca de la zona en conflicto las líneas coincidentes del principio y del final, así que los fragmentos quedan pequeños.
Si el merge ya está en curso, puedes regenerar los marcadores de un archivo con el nuevo estilo:
git checkout --conflict=zdiff3 src/http/client.ts
Esto importa aún más para un agente que para ti. Sin la base, el modelo tiene que adivinar qué lado cambió qué, y es justo al adivinar cuando empieza la pérdida silenciosa de datos.
Paso 3: dale al agente el contexto que necesita
Los marcadores muestran las líneas. El agente también necesita saber por qué cada lado las cambió. Git puede mostrar el historial de ambos lados para un archivo:
git log --merge -p src/http/client.ts # primero los diffs del lado HEAD, luego los de MERGE_HEAD
git show :1:src/http/client.ts # ancestro común
git show :2:src/http/client.ts # HEAD (ours)
git show :3:src/http/client.ts # MERGE_HEAD (theirs)
Añade el contexto humano: la descripción de la tarea o del pull request de cada rama. Después usa un prompt como este:
Estamos en mitad de un git merge de feature/retry en main. Estos archivos
tienen conflictos (merge.conflictStyle es zdiff3, así que se ve la base):
<salida de git diff --name-only --diff-filter=U>
Intención de main: <una o dos frases, o la descripción del PR>
Intención de feature/retry: <una o dos frases, o la descripción del PR>
Para cada archivo en conflicto:
1. Lee las secciones ours, base y theirs y di en una línea qué cambió
cada lado respecto a la base.
2. Escribe una resolución que conserve las dos intenciones. Si de verdad
se contradicen, no elijas: para y pregúntame.
3. Edita solo los fragmentos en conflicto. Nada de reformatear, renombrar
ni arreglos ajenos.
4. No edites tests para que pasen y no borres código que no entiendas.
Para package-lock.json / pnpm-lock.yaml: resuelve solo package.json y luego
regenera el lockfile con el gestor de paquetes.
Al terminar: que no quede ningún marcador, ejecuta el chequeo de tipos y los
tests, y dame un resumen por archivo de qué conservaste de cada lado.
No ejecutes git add, git commit ni git merge --continue.
La última línea deja el paso final en tus manos. El resumen por archivo agiliza la revisión: comparas cada afirmación con el diff en lugar de leer cada línea desde cero.
Paso 4: un archivo cada vez, con reglas claras
Unas pocas reglas marcan la diferencia entre un merge limpio y una regresión silenciosa:
- Nada de
--ourso--theirsen bloque.git checkout --ours <ruta>toma un lado entero del archivo y descarta el otro. Úsalo solo cuando sepas que un lado debe ganar, como un archivo generado que vas a regenerar de todos modos. - Ojo con la inversión en el rebase. La documentación de Git señala que durante
git rebaseygit pull --rebase,--ourses la rama sobre la que haces rebase y--theirses tu propio trabajo que se reaplica. Los agentes lo confunden con sorprendente frecuencia, así que nómbrales cada rama por su nombre. - Los archivos generados se regeneran, no se fusionan. Lockfiles, snapshots y salida de build deben salir de la herramienta que los genera, después de resolver los archivos fuente.
- Modificar/borrar exige una decisión. Si una rama borró un archivo que la otra cambió, el agente debe avisar y preguntar, no restaurarlo ni borrarlo por su cuenta.
- Los conflictos grandes se dividen. Si un archivo tiene decenas de fragmentos, pide al agente que lo resuelva y explique por partes, o da un paso atrás y replantea el orden de los merges.
Paso 5: verifica antes de continuar
Que un agente diga “resuelto” es una afirmación, no una prueba. Compruébalo:
git diff --check # avisa de marcadores de conflicto olvidados (y errores de espacios)
git diff # revisa la resolución
pnpm typecheck && pnpm test # o el chequeo de tu proyecto
git diff --check sale con un código distinto de cero cuando los cambios introducen marcadores de conflicto, así que es un filtro barato para pasar siempre. En versiones recientes de Git, git diff AUTO_MERGE muestra solo los cambios hechos hasta ahora para resolver los conflictos textuales: una vista centrada en exactamente lo que escribió el agente.
Después, termina la operación tú mismo:
git add src/http/client.ts
git merge --continue # o: git rebase --continue
Nunca aceptes a ciegas: señales de alarma en una resolución
| Señal de alarma | Lo que suele significar |
|---|---|
| El cambio de un lado ha desaparecido sin más | El agente eligió un lado en vez de combinarlos |
| Ha cambiado un test o una aserción | La resolución rompió un comportamiento y se ajustó el test |
| Cambiaron archivos fuera de la lista de conflictos | Se amplió el alcance: reformateos o “arreglos” que necesitan su propia revisión |
| Hay código duplicado | Se conservaron los dos lados tal cual, sin fusionarlos |
Quedan marcadores o un ======= suelto en un archivo que no es código | Nadie ejecutó git diff --check |
Si ves alguna, pide al agente que explique ese fragmento o rehaz el archivo a mano. Una revisión de código con IA del resultado es un segundo par de ojos útil, pero no sustituye a ejecutar los tests.
Rebase o merge cuando hay conflictos a la vista
Los dos funcionan; fallan de forma distinta.
| Merge | Rebase | |
|---|---|---|
| Dónde resuelves | Una vez, en el commit de merge | Commit a commit, al reaplicar cada uno |
| El mismo conflicto dos veces | No | Posible, en varios commits |
--ours / --theirs | Tu rama / la otra rama | Invertidos: el destino / tu propio trabajo |
| Historial | Conserva un commit de merge | Lineal, reescribe los commits de la rama |
| Seguro en ramas compartidas | Sí | Solo si nadie más trabaja sobre esa rama |
Para ramas de agentes de vida corta que solo usas tú, hacer rebase sobre main a menudo suele ser el hábito más cómodo: los conflictos aparecen pronto, cuando aún son pequeños. Para ramas largas o compartidas, usa merge. Durante un rebase, git rebase --skip descarta por completo el commit actual; úsalo solo si estás seguro de que ese commit no hace falta.
Que Git lo recuerde: rerere
Si haces rebase de la misma rama una y otra vez, resolverás el mismo conflicto más de una vez. git rerere (“reuse recorded resolution”) guarda cómo resolviste un conflicto y lo vuelve a aplicar cuando el mismo conflicto reaparece:
git config --global rerere.enabled true
Una vez activado, git merge y git commit lo ejecutan automáticamente. Comandos útiles:
git rerere status # rutas cuya resolución se va a registrar
git rerere diff # cómo va la resolución actual
git rerere remaining # conflictos que rerere no pudo resolver
git rerere forget src/http/client.ts # olvidar una resolución mal registrada
Dos cosas que conviene saber. rerere no toca el índice, así que sigues revisando el resultado y haciendo git add, y eso es bueno, porque una resolución errónea se repite con la misma fidelidad que una correcta. Además, git rerere gc poda los registros antiguos: por defecto, los no resueltos a los 15 días y los resueltos a los 60.
Comprueba los conflictos antes del merge
No hace falta empezar un merge para saber si tendrá conflictos. Desde Git 2.38, git merge-tree --write-tree hace el merge sin tocar tu árbol de trabajo ni el índice:
git merge-tree --write-tree --name-only main feature/retry
echo $? # 0 = limpio, 1 = conflictos
Con --name-only, la sección de conflictos lista solo los nombres de archivo. La documentación de Git aconseja fiarse del código de salida y no de una lista de archivos vacía. Es un buen primer encargo para un agente antes de que toque nada: “comprueba si feature/retry se fusiona limpia en main y, si no, lista los archivos en conflicto y qué cambió cada lado”.
Prevención: menos conflictos con agentes en paralelo
El conflicto más barato es el que nunca ocurre:
- Tareas pequeñas. Un agente que cambia cinco archivos choca menos que uno que cambia cincuenta. Divide los trabajos grandes por zonas.
- Un dueño por zona. Decide qué agente puede cambiar el router, el esquema, los tipos compartidos, y dilo en las instrucciones de cada agente.
- Merge o rebase frecuente. Una rama que vive una hora rara vez tiene conflictos; una que vive una semana casi siempre.
- Nada de cambios de paso. Pide a los agentes que no reformateen, renombren ni arreglen nada fuera de su tarea.
- Un cambio de lockfile cada vez. Deja que una sola rama añada dependencias, o regenera el lockfile tras cada merge.
- Una cola de merge. Las ramas aterrizan de una en una sobre la última punta, con tests sobre el resultado fusionado, así que también se detectan los conflictos semánticos.
Para la parte de configurar agentes en carpetas separadas, consulta Git worktrees para agentes en paralelo.
Cómo ayuda AgentVera
AgentVera es una app de escritorio que ejecuta CLIs de agentes de código como Claude Code y Codex en paralelo, con git integrado. Estas funciones encajan en el flujo anterior:
- Worktrees y el panel de Git. Crea un worktree por funcionalidad y arranca un agente en él; prepara cambios por archivo, haz commit, fetch, pull y push, y lee los diffs al estilo GitHub, unificados o divididos.
- Avisos tempranos. Por defecto, AgentVera ejecuta
git fetchen segundo plano cada 5 minutos. Cuando llegan commits nuevos a tu rama, un aviso te deja hacer fast-forward con un clic, o rebase si ambos lados tienen commits. Cuando dos agentes del mismo proyecto editan el mismo archivo, la coordinación de agentes te avisa; si están en worktrees distintos, indica que el merge puede tener conflictos. - Propiedad de archivos. Con la propiedad de archivos asignas a un agente rutas o globs como
src/api/**. Mientras se ejecuta, los agentes de Claude Code se detienen antes de editar esos archivos y se les indica que pregunten al dueño; Codex y otras CLIs reciben las reglas en sus instrucciones. - Equipo en paralelo. Un equipo en paralelo (Pro) divide un trabajo en partes que se ejecutan cada una en su propio worktree y se fusionan en una rama de integración. Si un merge da conflicto o falla la comprobación final, interviene un agente de integración.
- Cola de merge. La cola de merge (Pro) fusiona las ramas de una en una sobre la última punta del destino. Un agente de Claude resuelve los conflictos, la comprobación se ejecuta sobre el resultado fusionado con hasta 2 rondas de arreglo y la rama que no se puede arreglar se devuelve. Por defecto, el aterrizaje espera tu aprobación.
Si trabajas solo y en una rama cada vez, git a secas con zdiff3 y rerere es todo lo que necesitas. Estas herramientas compensan cuando varios agentes producen ramas al mismo tiempo.
Errores comunes
- Resolver sin la base. El estilo de conflicto por defecto oculta cómo era el código antes; activa
zdiff3. - “Arregla los conflictos” como prompt completo. Sin la intención de cada rama, el agente elige el lado que parece más completo.
- Dejar que el agente ejecute
git addy--continue. Guarda el paso final para después degit diff --checky los tests. - Fusionar lockfiles a mano. Resuelve el manifiesto y luego regenera.
- Hacer rebase de una rama compartida. Todos los que trabajaban sobre ella tendrán que desenredar commits reescritos.
En resumen
Resolver conflictos de merge con IA funciona cuando el agente ve el panorama completo y la prueba queda de tu lado: marcadores zdiff3 que muestran la base, un prompt que expone ambas intenciones y prohíbe atajos, git diff --check y la suite de tests antes de git add, y rerere para los conflictos que se repiten. La prevención hace el resto: tareas pequeñas, propiedad de archivos clara y ramas que aterrizan de una en una.
Para probarlo con tus propios agentes, descarga AgentVera.