Guía9 min

git shortlog para coding agents: recuento por autor, no dump de log

Resumen

git shortlog agrupa commits por autor y resume títulos. Un agente usa -sn con rango A..B. Cero historia completa. Cero --format que vuele el contexto. Distinto de git log y de git blame. Mailmap canónico; el agente no reescribe .mailmap. Git 2.50.1.

GitHub
Barras por autor: shortlog cuenta commits agrupados, no lista la historia

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 shortlog no es un git log corto. El man (git-shortlog(1); git-scm.com/docs/git-shortlog HTTP 200, verificado 2026-09-06; Git 2.50.1 / Apple Git-155): Summarizes git log output in a format suitable for inclusion in release announcements. Each commit will be grouped by author and title. Además, el prefijo [PATCH] se recorta del subject.

No sustituye git log (walk de parent links, conjuntos A..B / A...B) ni git blame (anota líneas). El contrato: agrupar. Contar. Recortar. Cero dump. Cero --format que vuele el contexto. Cero reescribir .mailmap.

Qué resume y qué no

Sin rango, el default es HEAD: toda la historia alcanzable. Un agente nunca corre git shortlog a pelo en un repo con miles de commits. El man documenta el rango: origin..HEAD = alcanzables desde HEAD que no lo son desde origin. Paths van detrás de --.

Si no pasas revisiones y (stdin no es un TTY o no hay rama actual), shortlog lee el log desde stdin sin mirar el repo. Eso es el modo tubería: git log --pretty=short | git shortlog. Un agente no alimenta esa tubería con git log -p ni con --pretty=fuller sin tope.

QuieroComandoTrampa
¿Quién metió commits en mi topic?git shortlog -sn origin/main..HEADgit shortlog sin rango
¿Cuántos, sin títulos?-s (--summary)omitir -s y volcar subjects
¿Orden por volumen, no alfabético?-n (--numbered)default alfabético
¿Email canónico?-etratar el email crudo como identidad legal
¿Solo este path?git shortlog -sn origin/main..HEAD -- src/foo.tsglob de shell sin --

-s suprime la descripción y deja el recuento. -n ordena por número de commits, no por nombre. Juntos (-sn) caben en un harness. Sin -s, cada autor arrastra todos sus subjects: eso es un changelog, no un recuento.

Grupos: author, committer, trailer

--group (default author) cambia qué identidad agrupa. El man:

--group=Qué cuenta
authorautor del commit (default)
committercommitter; alias -c
trailer:<field>trailer case-insensitive (Reviewed-by, Co-authored-by)
format:<fmt>cualquier --format de git log

Commits sin ese trailer no entran. Commits con varios trailers del mismo campo pueden contar más de una vez, una por valor único en ese commit. Varios --group cuentan bajo cada valor (una vez por valor único): git shortlog --group=author --group=trailer:co-authored-by suma autores y coautores.

El valor de un trailer se intenta parsear como Name <email>. Si cuadra, aplica mailmap y omite el email salvo -e. Si no, se toma literal. Un agente no inventa trailers ni reescribe mensajes para “arreglar” el recuento.

Grupos: author vs committer vs trailer; cada uno es un cubo distinto

--format sustituye el subject. El man admite cualquier pretty de git log (* [%h] %s). Cada línea se rewrappea. Un agente no usa %B, %N ni formatos que metan body/notes al contexto. Si necesita SHA+subject, -sn ya resolvió el recuento; el detalle vive en log con -n --oneline.

-w[<width>[,<indent1>[,<indent2>]] wrappea. Defaults 76, 6, 9. width=0 indenta sin wrap. Un agente no sube el ancho para “ver más”: el tope es el contexto, no la terminal.

Mailmap: canónico, no reescritura autónoma

gitmailmap(5) (git-scm.com/docs/gitmailmap HTTP 200, 2026-09-06): si existe .mailmap en la raíz del worktree —o mailmap.file / mailmap.blob en config— mapea nombres y emails a una identidad canónica. Match case-insensitive. Git no sigue symlinks al leer .mailmap del working tree.

Formas (man):

Proper Name <[email protected]>
<[email protected]> <[email protected]>
Proper Name <[email protected]> <[email protected]>
Proper Name <[email protected]> Commit Name <[email protected]>

Shortlog aplica el mailmap al agrupar. Por eso “Jane Doe” y “jane@laptop.(none)” pueden colapsar a una barra. Eso no autoriza al agente a editar .mailmap, ni a tocar mailmap.file vía git config (--local ya es el techo; --global está vetado). Identidades rotas se reportan; el humano decide el mapa.

Tampoco es autoría legal. El recuento es “cuántos commits quedaron agrupados bajo esta identidad después del mailmap”, no “quién es dueño del código” ni a quién pinguear. Eso se parece al error de blame: anotar ≠ culpar.

Mailmap colapsa aliases a una identidad; el agente no reescribe el archivo

Stdin, TTY y el repo actual

El man: si no hay revisiones en argv y (stdin no es terminal o no hay current branch), shortlog resume el log leído de stdin sin referenciar el repo. En un cron, un pipe o un harness sin TTY, git shortlog -sn sin rango no camina HEAD: espera un log por stdin. Si el pipe está vacío, el recuento es vacío. Si el pipe es un git log enorme, el contexto explota antes del resumen.

Contrato del agente:

  1. Pasa siempre un rango (origin/main..HEAD, v1.2.0..HEAD, -n no limita shortlog igual que log: -n aquí es --numbered, no --max-count).
  2. Para tope de commits, usa las opciones de Commit Limiting heredadas de log (--since, --author, --grep) con el rango, no un git log | head.
  3. No pipes git log -p ni --pretty=full a shortlog.
  4. No uses --all / --branches / --reflog autónomos: caminan refs de más.

-n en shortlog ordena. --max-count / -n <número> en log recorta. Mezclarlos de memoria es el bug clásico: git shortlog -n 20 no son 20 commits; es “numerar autores”. El synopsis de log (-<number>, --max-count) vive en la sección Commit Limiting que shortlog reexporta, pero la flag corta -n ya está tomada por --numbered. Un agente que quiere tope escribe --max-count=50, nunca -n 50.

Checklist

  • Rango explícito (origin/main..HEAD o tag..HEAD). Nunca shortlog a pelo.
  • -sn para recuento. Subjects solo si el humano pidió changelog.
  • -- antes de paths.
  • --group=trailer:… solo con el campo real del repo; commits sin trailer no cuentan.
  • Cero --format con body/notes. Cero pipe de git log -p.
  • Cero editar .mailmap / mailmap.file. Reportar aliases, no “arreglarlos”.
  • -n = numbered, no max-count. Tope = --max-count.
  • No tratar el recuento como blame, owners ni CODEOWNERS.

FAQ

¿Puedo usar shortlog para “quién tocó este archivo”? Solo como recuento de commits que explican ese path (-- path). La línea concreta es blame. Un shortlog de src/ entero sin rango es un dump.

¿--group=committer es más verdad que author? No. Author es quién se atribuye el cambio; committer es quién lo aplicó (rebase, cherry-pick, am). En un topic rebased, el committer suele ser el agente o el humano que reescribió. Elige el grupo; no mezcles los cubos.

¿Por qué Jane aparece dos veces? Mailmap incompleto o emails que no matchean. Reporta las dos barras. No reescribas .mailmap.

¿Shortlog reemplaza el changelog del release? El man dice suitable for inclusion in release announcements, con subjects. Un agente que publica un release no inventa el texto: corre -sn para el recuento y deja los subjects a un humano, o usa format-patch cuando el artefacto es un mbox.

Más piezas de decisión en comparativas y decisiones. Si estás armando el loop del agente, el curso parte de /curso/instalar-agente.