git merge-base para coding agents: ancestro común, no folklore
Resumen
git merge-base elige el mejor ancestro común para un merge a 3 vías. Un agente usa --is-ancestor (0/1); no compara SHA a mano ni --fork-point + rebase autónomo. Git 2.50.1.

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 merge-base no fusiona. El man (git-merge-base(1), Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-merge-base HTTP 200, last-modified 2026-08-31; last updated in 2.43.0, 2.43.1 → 2.55.0 sin cambios) find as good common ancestors as possible for a merge: elige el mejor ancestro común para un merge a 3 vías. Un ancestro es mejor que otro si el segundo es ancestro del primero. Puede haber más de uno. HEAD, index y working tree no se mueven.
Esta guía no sustituye merge (el commit de fusión) ni diff (A...B usa el merge-base). El contrato: nombrar el ancestro, preguntar ancestría con exit 0/1, y parar en 128/129.
GitHub Docs (Branches, HTTP 200 2026-09-04; la URL vieja About comparing branches in pull requests redirige aquí): un PR muestra three-dot — git diff A...B = merge-base de ambas ramas contra el tip del topic. Two-dot (A..B) compara tips y cambia cuando avanza la base aunque el topic no se haya tocado. Un agente que quiere “qué introduce el PR” pide el merge-base; no inventa el SHA del compare de github.com.

Lo que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
| Ancestro de dos tips | git merge-base origin/main HEAD | git log --oneline y adivinar |
| ¿A es ancestro de B? | git merge-base --is-ancestor A B | test "$(git merge-base A B)" = "$(git rev-parse A)" |
| Diff del PR | git diff origin/main...HEAD --stat | two-dot origin/main..HEAD |
| Todos los bases (criss-cross) | git merge-base --all A B | --all volcado al LLM “por si acaso” |
Prohibido en autónomo:
--fork-point+git rebase --onto. El man: mira el reflog de<ref>. Sigit gcexpiró el tip viejo, falla a propósito (no devuelve el padre aleatorio que daría sin--fork-point). Un rebase autónomo reescribe SHA; ver rebase.- Más de dos commits sin
--octopus. El man: el primero vs un commit hipotético que fusiona el resto. Verificado 2026-09-04:merge-base C B A(C encima de A; B diverge) imprimió A, no el ancestro de los tres.--octopus C B Así imprimió el ancestro común de todos. - Tratar exit 1 de
--is-ancestorcomo fallo de Git. El man: 0 = sí es ancestro; 1 = no; otro ≠0 (p. ej. 128) = error. - El idiom viejo
A=$(git rev-parse --verify A); test "$A" = "$(git merge-base A B)". El man lo deja para scripts antiguos; in modern git es--is-ancestor. --independent“para ver qué no está contenido”. El man: subconjunto mínimo de los commits dados que no se alcanzan entre sí. Dump de tips, no un ancestro.- Sustituir el SHA local por el compare de GitHub. Three-dot en github.com mira el remoto; tu worktree puede estar en otra base.
Sin args o un solo commit (modo default / --is-ancestor): 129 y usage. Verificado: git merge-base, git merge-base HEAD, git merge-base --is-ancestor HEAD → 129. Nombre inválido: 128, Not a valid object name. Fuera de un repo: 128, not a git repository.
Receta (60 segundos)
Solo en un worktree propio, con fetch si el ticket nombra el remoto:
git merge-base --is-ancestor origin/main HEAD # 0 = HEAD está encima; 1 = divergió
git merge-base origin/main HEAD # SHA del ancestro
git diff origin/main...HEAD --stat # lo que el topic introduce
--is-ancestor A B no imprime SHA. Verificado: ancestro real → 0 y stdout vacío; tips divergentes → 1 silencioso; NOPE HEAD → 128.
Si el ticket pide “¿puedo fast-forward B con A?”: --is-ancestor A B (A ancestro de B). No compares strings de SHA.

Más de dos commits y criss-cross
El man (OPERATION MODES): con dos commits, el merge-base es entre esos dos. Con más, el primero vs un merge hipotético del resto. No está necesariamente contenido en cada argumento. Eso no es git show-branch --merge-base.
--octopus: mejor ancestro común de todos. En el diagrama del man (A, B, C con 2 más antiguo que 1): merge-base A B C → 1; merge-base --octopus A B C → 2.
-a / --all: todos los best merge bases. En criss-cross (el man: 1 y 2, ninguno mejor), sin --all no está especificado cuál se imprime. Un agente que necesita ambos pide --all y parsea líneas; no asume unicidad.
--independent: no imprime bases. Lista, de los commits dados, los que no se alcanzan desde otro. Verificado: tras dos merges --no-ff cruzados, --independent M1 M2 SHA1 imprimió solo el tip que contenía al resto.
--fork-point <ref> [<commit>]: no es merge-base origin/main topic. El man: si origin/master se rebobinó (B0→B1→B2→B) y tu topic nació en B0, el merge-base normal incluye B0 (commit ajeno que la otra punta descartó). --fork-point busca B0 en el reflog. Si el reflog ya no lo tiene, falla. Un agente no “arregla” eso con el padre de B0.
Checklist
- Worktree propio. 128 fuera del repo = para.
- Dos commits para el ancestro;
--octopussi son N-way. - Ancestría con
--is-ancestor(0/1). Cero comparación de SHA. - Diff de PR =
A...B(three-dot), no two-dot. - Cero
--fork-point+ rebase autónomo. Cero--all/--independental prompt. - 129 = usage (faltan args). 128 = objeto o repo inválido.
FAQ
¿git merge-base A B C es el ancestro de los tres? No. El man: A vs merge hipotético de B y C. Para los tres: --octopus.
¿--all siempre imprime varios? No. Si hay un único best, una línea. En criss-cross, varios; sin --all cuál de ellos es unspecified.
¿Esto reemplaza log? No. A...B en log es la diferencia simétrica. merge-base nombra un commit (o varios con --all). No camina historia.
El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. merge-base no es merge: nombra el ancestro; no crea el commit de fusión.
Verificado 2026-09-04 contra git-merge-base(1) (Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-merge-base HTTP 200, last-modified 2026-08-31), GitHub Docs “Branches” (HTTP 200; three-dot = merge-base…topic) y git-merge(1). En esta máquina: dos tips divergentes → SHA del padre común; --is-ancestor 0/1/128; sin octopus tres commits → el hipotético, no el de los tres; 0 args o 1 arg → 129; fuera del repo → 128.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git cat-file para coding agents: tipo y talla, no el blob al LLM

git ls-tree para coding agents: tree object, no el disco

git submodule para coding agents: gitlink 160000, no un clone extra
