Guía9 min

git mergetool para coding agents: GUI humana, no resolver conflictos

Resumen

git mergetool lanza un programa gráfico o vimdiff sobre archivos en conflicto. Sin merge.tool avisa y prueba fallbacks. Cero -y/--gui autónomo. Distinto de merge, merge-tree, rerere y difftool. Git 2.50.1.

GitHub
Tres paneles LOCAL BASE REMOTE frente a un archivo MERGED; el agente no abre la GUI

Qué resuelve

Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.

git mergetool abre un programa de resolución sobre archivos con conflicto. El man (git-mergetool(1); git-scm.com/docs/git-mergetool HTTP 200, last-modified 2026-08-31; pie del man local Git 2.50.1.428.g0e8243, 2025-07-22; binario Git 2.50.1 / Apple Git-155): Run merge conflict resolution tools to resolve merge conflicts. SYNOPSIS: git mergetool [--tool=<tool>] [-y | --[no-]prompt] [<file>...]. DESCRIPTION: It is typically run after git merge.

Contrato para un coding agent: no lo lances. Es una GUI o un editor interactivo (opendiff, vscode, vimdiff). Necesita TTY, DISPLAY y un humano que elija el contenido final. Ante UU, aborta el merge. No -y. No --gui. No merge.tool global. No vuelques $LOCAL/$BASE/$REMOTE/$MERGED al contexto.

No es merge: merge une historias y, si choca, para. El mergetool es el siguiente paso humano. No es merge-tree: merge-tree simula en seco y no toca el índice. No es rerere: rerere reusa una resolución ya grabada; mergetool pide una nueva. No es git difftool: difftool es frontend de diff y no resuelve un merge.

Qué hace (y qué no)

Si pasas <file>, corre el tool solo en esos paths con conflicto y salta los que no tienen. Un directorio incluye los unresolved de esa ruta. Sin paths, recorre todos los archivos en conflicto.

Sin conflictos, sale 0 y dice No files need merging. Verificado 2026-09-06 en un worktree limpio: git mergetool → ese mensaje, exit 0. --tool=notatool sin conflicto también 0: Git ni valida el tool. Con conflicto real, --tool=notatoolerror: mergetool.notatool.cmd not set for tool 'notatool', exit 1.

Sin merge.tool, avisa y prueba fallbacks. Verificado: This message is displayed because 'merge.tool' is not configured. Luego: 'git mergetool' will now attempt to use one of the following tools: opendiff tortoisemerge emerge vimdiff nvimdiff. En este Mac, --tool-help lista disponibles opendiff, vimdiff/vimdiff1-3, vscode. El resto (meld, kdiff3, nvimdiff, gvimdiff…) aparece como valid, but not currently available.

--tool-help imprime la lista y sale 0. Úsalo para diagnosticar, no para elegir un tool y lanzarlo.

Tres paneles LOCAL, BASE y REMOTE frente al archivo MERGED

GitHub Docs (/en/pull-requests/reference/merge-conflicts, canónico 2026-09-06 tras 301 desde About merge conflicts): un PR con conflicto no se mergea hasta que alguien elija el contenido. El botón de GitHub no es mergetool. Un agente que “resuelve” abriendo FileMerge no cierra el PR.

Flags que un agente no toca

Flag / configManAgente
-t / --tool=<tool>Usa ese programa. Con tool explícito, -y es el defaultCero. Abre GUI o vim
--tool-helpLista tools válidosSí, solo lectura
-y / --no-promptNo pregunta antes de cada archivoCero autónomo
--promptPregunta para poder saltar el pathCero
-g / --guiLee merge.guitool en vez de merge.toolCero. Quiere DISPLAY
--no-guiFuerza merge.toolCero
-O<orderfile>Orden de globs; -O/dev/null anula diff.orderFileCero autónomo. Verificado: -O /dev/nulloutside repository

-y no apaga el prompt si merge.tool no está. Verificado en un merge con UU: git mergetool -y aún imprimió Hit return to start merge resolution tool (opendiff) y dejó f_BACKUP_*, f_BASE_*, f_LOCAL_*, f_REMOTE_* untracked. No asumas que -y = no interactivo.

Custom tool: mergetool.<tool>.cmd corre en shell con BASE, LOCAL, REMOTE, MERGED. trustExitCode=true usa el exit del programa; si no, Git mira el timestamp de MERGED o pregunta. Un cmd que cat los temporales al stdout filtra el conflicto al LLM. Prohibido.

Config que no pisa un agente

El man incluye el bloque de git-config(1) (git-scm.com/docs/git-config HTTP 200, last-modified 2026-08-31):

  • merge.tool / merge.guitool: cuál programa. Un agente no hace git config --global merge.tool. Eso es config local, y global queda fuera.
  • mergetool.<tool>.path / .cmd / .trustExitCode / .hideResolved: por tool.
  • mergetool.hideResolved (default false): si true, $LOCAL y $REMOTE solo muestran lo no resuelto. No lo actives a ciegas: escondes contexto que el humano necesita.
  • mergetool.keepBackup (default true): deja archivo.orig con markers. El man TEMPORARY FILES: safe to remove once a file has been merged. false borra el backup al resolver. No lo cambies.
  • mergetool.keepTemporaries (default false): si el custom tool falla, conserva BASE/LOCAL/REMOTE. true ensucia el worktree.
  • mergetool.writeToTemp (default false): temporales fuera del worktree. No lo prendas autónomo.
  • mergetool.guiDefault: true--gui; auto mira DISPLAY. Default false.
  • mergetool.prompt: prompt por archivo.
  • mergetool.meld.useAutoMerge / hasOutput: solo Meld.
  • mergetool.vimdiff.layout (y gvimdiff/nvimdiff): ventanas LOCAL,BASE,REMOTE / MERGED. Layout default 4 paneles. Variantes vimdiff1 = @LOCAL,REMOTE, 2 = tres columnas, 3 = solo MERGED.

vimdiff escribe en MERGED. El man: guarda y :wq; aborta con :cq. Un agente no abre Vim para “terminar el merge”.

Flujo seguro

  1. status porcelain: UU / AA / DU. Hay conflicto.
  2. No git mergetool. No git add del archivo a medias. No -X ours (eso es merge, no este verbo).
  3. Si el merge lo empezaste tú: git merge --abort. Si era rebase: git rebase --abort.
  4. Si el humano pide ver el choque sin GUI: merge-tree --quiet. Exit 0/1. Cero dump del conflicto al prompt.
  5. Si el repo tiene rerere y ya resolvió esa huella, rerere puede reaplicar. Eso no es mergetool.
  6. Resolución de verdad: humano con mergetool o el editor del PR en GitHub. Después, tests y un commit nuevo. Nunca amend + force.

El agente aborta el merge; la GUI queda para el humano

Checklist:

  • merge.tool no lo seteas tú.
  • Cero -y, --gui, --tool=vimdiff autónomo.
  • Cero mergetool.*.cmd que imprima BASE/LOCAL/REMOTE.
  • *.orig y *_LOCAL_* no se commitean. No git add ..
  • Conflicto = abortar o pedir humano. No “resolver” con el LLM.

FAQ

¿Puedo usar mergetool en CI? No. No hay DISPLAY ni humano. CI usa merge-tree o deja el job rojo.

¿Es lo mismo que el editor de conflictos de VS Code / Cursor? El tool vscode de --tool-help requires a graphical session. El agente CLI no es esa sesión. No lo dispares con -y.

¿Y si el humano ya tiene merge.tool=opendiff? Sigue sin lanzarlo. FileMerge espera un clic. Tu trabajo es reportar UU y parar.

¿difftool resuelve? No. git-difftool(1) (HTTP 200, last-modified 2026-08-31): frontend to git diff. Muestra cambios. No marca el path como resuelto.

¿Qué hago con los f_LOCAL_*.txt que dejó un mergetool a medias? Son untracked. No los agregues. El humano borra o termina la sesión. keepBackup deja .orig; tampoco va al commit.

Si estás armando el agente desde cero, el curso de instalar un agente cubre el loop y las tools. Esta guía es la regla de oro cuando Git ya paró: el conflicto no se “autocompleta”.