Guía9 min

git am para coding agents: mailbox a commits, no un diff suelto

Resumen

git am parte un mbox de format-patch, aplica y committea con autor y Subject. ORIG_HEAD antes. Conflicto: --abort, no --continue a ciegas. Cero --3way/--reject/--signoff/--no-verify autónomo. Git 2.50.1.

GitHub
Un mailbox se convierte en commits; HEAD avanza, ORIG_HEAD queda en la punta previa

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 am aplica una serie de parches de un mailbox y crea commits. El man (git-am(1); git-scm.com/docs/git-am HTTP 200, last-modified 2026-08-31, last updated in 2.55.0; pie del man local Git 2.54.0, 2026-04-19; binario Git 2.50.1 / Apple Git-155): Splits mail messages in a mailbox into commit log messages, authorship information, and patches, and applies them to the current branch. Es el reverso de git format-patch en historia lineal. SEE ALSO: git-apply(1), git-format-patch(1).

No es cherry-pick. Cherry-pick copia un objeto commit del grafo. am lee un mbox. Tampoco git apply: apply pega bytes y no committea. El man de apply: This command applies the patch but does not create a commit.

Contrato: mbox de format-patch, worktree limpio, 0 = commits hechos, 128 = sesión abierta → --abort. Cero --3way / --reject / --signoff / --no-verify / --continue autónomo.

Qué hace (y qué no)

Antes de aplicar, el man pone ORIG_HEAD en la punta actual. Autor = From:. Fecha de autor = Date:. Título = Subject: sin el prefijo [PATCH …]. El cuerpo hasta el diff es el mensaje. Committer = tú, ahora.

Verificado 2026-09-04 (Git 2.50.1 / Apple Git-155), repo de un archivo f.txt y git format-patch -1 --stdout de feat: change b:

  • Worktree limpio, padre igual al del parche: git am file.patch0, Applying: feat: change b. HEAD avanza. Autor t <t@t>, subject feat: change b. ORIG_HEAD = SHA previo.
  • En rama topic desde el mismo padre: 0, SHA nuevo (c755325 ≠ original df69ff6). Mismo árbol y mensaje no reutilizan el objeto.
  • Serie format-patch -2: 0, dos Applying: seguidos, dos commits.
  • Stdin (git am < two.patch): 0, igual.
  • git apply del mismo mbox: 0, status M f.txt, log no avanza.
  • Ya aplicado: patch does not apply, 128, sesión en .git/rebase-apply. --abort0, log intacto.
  • Working tree sucio (f.txt ≠ índice): does not match index, 128, sesión abierta. --abort.
  • Conflicto (línea local bX vs parche b2): 128, status limpio salvo la sesión. --show-current-patch=diff imprime el hunk. --continue sin resolver: No changes - did you forget to use 'git add'?, 128. --abort0, log en local diverge.
  • --3way en el mismo conflicto: Falling back to patching base and 3-way merge, CONFLICT (content), UU f.txt, marcadores <<<<<<<. 128. --abort restaura bX (man: Revert the contents of files involved).
  • --signoff: 0, trailer Signed-off-by: t <t@t>.
  • --no-verify: 0 (salta pre-applypatch / applypatch-msg; el man: post-applypatch no se salta).
  • Archivo vacío: Patch format detection failed., 128.
  • Mail sin diff (--empty=stop, default): Patch is empty., 128, sesión. --empty=drop0, Skipping, sin commit. --empty=keep0, commit vacío con el Subject.
  • --reject: 128, deja f.txt.rej.
  • --quiet: 0, sin Applying:.
  • --skip tras conflicto: 0, el parche no entra, HEAD sigue en el diverge.
  • --quit tras conflicto: 0, sesión muere, HEAD e índice intactos (man: keep HEAD and the index untouched).

am exige un repo. Apply sin --index no.

am avanza HEAD; apply deja el working tree sucio

Lo que el agente sí / no corre

QuieroComandoTrampa
Traer commits de un mboxgit am -- "$mbox"git apply del mismo archivo
Ver el parche trabadogit am --show-current-patch=diffvolcar el mbox al LLM
Salir del 128git am --abort--continue / --skip / --quit a ciegas
Copiar un SHA del grafocherry-pickam de un diff inventado
Pegar bytes sin commitgit apply --check luego git applycreer que apply ya committeó
Cerrar el cambiostatus -sb + PRpush a main

Prohibido en autónomo:

  • --3way / --ours / --theirs. El default falla si no pega limpio (am.threeWay default false). --3way deja conflict markers. Resolución a ciegas no.
  • --reject. Pasa --reject a apply. Verificado: *.rej y 128.
  • --continue. El man: el índice debe guardar el resultado a mano. Sin git add, 128.
  • --skip / --quit. --skip tira el parche. --quit deja el árbol a medias. El default de salida es --abort.
  • --signoff. Añade tu identidad al mensaje. Un agente no firma DCO por Marco.
  • --no-verify / -n. El man corre pre-applypatch y applypatch-msg por default.
  • --committer-date-is-author-date / --ignore-date. El man: allows the user to lie sobre fechas. El walker asume timestamps no decrecientes.
  • --interactive. Pide TTY.
  • --directory, -p, --include / --exclude, --whitespace=fix. Cambian dónde o qué pega.
  • --empty=keep / --allow-empty. Inventan commits vacíos.
  • Tratar SHA coincidente como “el mismo objeto”. Verificado: en rama, SHA nuevo.

El mbox se genera con git format-patch. Un agente que fabrica el From: / hunk y lo pasa a am está un paso más allá de este comando.

Receta (60 segundos)

Solo en un worktree propio, árbol limpio:

git status -sb
git am -- "$mbox" || { git am --abort; exit 1; }
git status -sb
git log --oneline ORIG_HEAD..HEAD

Si sale 128: --abort. Cero --3way, cero --reject, cero --continue. Reporta el error y para.

Si el árbol queda mal: --abort primero. No reset --hard ni restore a ciegas con sesión abierta.

Cierre = PR. Cero push a main.

128 abre sesión; --abort vuelve a ORIG_HEAD

am vs apply vs cherry-pick

am parte correo, aplica y committea. apply pega el diff; HEAD quieto. cherry-pick replaya un commit del objeto store.

Un agente que “aplica el PR” con git apply de un git diff no replica autor ni mensaje. Si el ticket es “trae estos commits de un format-patch”, este comando. Si el ticket es “pega este diff en el disco”, apply. Si el ticket es “trae el SHA abc que ya está en el clone”, cherry-pick.

El man (CAVEATS): un diff sin indentar en el mensaje de commit puede aplicarse como parche o tumbar am. Un Markdown con fence de diff es un caso. No “arreglar” el mbox a ciegas.

am se niega a leer otro mailbox hasta cerrar la sesión. El man: si vas a empezar de cero, --abort antes.

Checklist

  • Worktree propio. git status -sb limpio. Un mbox de format-patch.
  • git am -- "$mbox". 0 = commits. 128 = --abort.
  • Cero --3way / --reject / --continue / --skip / --signoff / --no-verify.
  • ORIG_HEAD..HEAD con log --oneline. No dump -p.
  • Cierre = PR, no push a main.

FAQ

¿git am es lo mismo que git apply? No. Apply no crea commit (man apply). Verificado: apply deja M f.txt; am avanza HEAD.

¿El SHA se conserva? No. Verificado en rama: SHA nuevo. Autor y mensaje sí vienen del mbox.

¿--3way “por si acaso”? No. Default falla limpio. Con el flag, UU y marcadores. Nunca en autónomo.

¿--abort o --quit? --abort. El man restaura rama y archivos. --quit deja HEAD/índice.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. am no es cherry-pick: lee mailbox, no un SHA del grafo.