Guía9 min

git name-rev para coding agents: SHA a nombre, no a describe

Resumen

git name-rev nombra un commit-ish con la ref más cercana hacia atrás. Un arg: SHA y nombre. --name-only omite el SHA. undefined sale 0. --all y --annotate-stdin no van al LLM. No es git describe. Git 2.50.1.

GitHub
Un SHA se nombra con la ref más cercana hacia atrás; el working tree no se mueve

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 name-rev busca un nombre simbólico digerible para revisiones que acepta rev-parse. El man (git-name-rev(1); git-scm.com/docs/git-name-rev 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) imprime el commit-ish, un espacio y el nombre. HEAD, index y working tree no se mueven.

Eso no es describe. Describe cuenta commits encima de un tag (tag-N-gSHA). name-rev nombra commits que son ancestros de una ref (tags/v1~N, feat). Un commit adelante del tag, con --tags, sale undefined.

GitHub Docs (REST API endpoints for commits, HTTP 200 2026-09-04): Get a commit mira github.com. No nombra un SHA local.

Contrato: un commit-ish, --name-only si no hace falta el SHA, ramificar undefined / 128, cero dump.

Un SHA, un nombre hacia atrás

OUTPUT del man (un commit-ish): el token que pasaste, un espacio, el nombre. Verificado con od: espacio, no TAB. --name-only deja solo el nombre. Con --tags, --name-only omite el prefijo tags/, como dice el man para acercarse a describe.

PreguntaComandoQué imprime
¿Dónde cae HEAD?git name-rev HEADHEAD feat
¿Solo el nombre?git name-rev --name-only HEADfeat
¿Solo tags?git name-rev --tags HEADHEAD tags/lw o HEAD undefined
¿Exigir nombre?git name-rev --no-undefined HEADel nombre, o fatal 128
¿Patrón de refs?git name-rev --refs='refs/heads/*' HEADsolo heads

Verificado 2026-09-04 (Git 2.50.1 / Apple Git-155), repo main → tag anotado v1 → lightweight lw → rama feat un commit más:

  • Attached en feat: HEAD feat, 0. --name-onlyfeat, 0. Detached en el mismo commit: igual, HEAD feat.
  • --tags en feat (adelante del tag): HEAD undefined, 0. --name-only --tagsundefined. describe --tags en el mismo tip: lw-1-g….
  • Commit del lightweight: SHA + tags/lw. --tags --name-onlylw (sin tags/).
  • Ancestro del anotado: SHA + tags/v1~1. --tags --name-onlyv1~1. El tag mismo: v1 tags/v1. v1^{commit}: tags/v1^0.
  • --refs='refs/tags/*' en feat: undefined. --refs='refs/heads/*': feat. Varios --refs: union. --exclude='refs/heads/*' en feat: undefined. --exclude='refs/tags/*' en el commit de lw: nombra main.
  • Blob HEAD:f y tree HEAD^{tree}: undefined, 0. --no-undefined en el blob: cannot describe, 128.
  • SHA inexistente: Could not get object for … Skipping., 0. --no-undefined / --always no lo convierten en 128.
  • --no-undefined --tags en feat: cannot describe el SHA, 128.
  • --always --tags en feat: sigue undefined, 0. El man promete SHA abreviado de fallback; en este binario no sustituyó undefined de un commit existente.
  • Sin args: stdout vacío, 0. --all y un commit-ish juntos: Specify either a list, or --all, not both!, 129.
  • --annotate-stdin: solo sustituye hex de 40 caracteres. Un SHA de 12 se queda igual. --name-only deja el nombre y quita el hex. --stdin (viejo): deprecated. Please use --annotate-stdin; sigue funcionando.
  • --all en ese repo: 4 líneas (commits alcanzables desde las refs). --all --name-only omite los SHA.

--tags nombra ancestros del tag; un commit adelante sale undefined

Lo que el agente sí / no corre

QuieroComandoTrampa
¿En qué ref cae este SHA?git name-rev --name-only -- <sha>git log al LLM
¿Es un tag, no una rama?git name-rev --tags --name-only -- <sha>asumir que default ignora branches
¿Fallar si no hay nombre?git name-rev --no-undefined --name-only -- <sha>parsear el string undefined
¿Versión SemVer / tag-N-g?describename-rev como release
¿SHA de HEAD?rev-parse --verify --quiet HEADname-rev creyendo que da SHA

Prohibido en autónomo:

  • --all. El man: lista commits alcanzables desde todas las refs. Un clone real son miles de líneas. No es “contexto”.
  • --annotate-stdin / --stdin sobre log -p o un diff. El man lo enseña con git log \| git name-rev --annotate-stdin. Eso es el dump. --stdin además está deprecado.
  • Tratar undefined como error. Default 0. El 128 aparece con --no-undefined cuando el objeto existe y no hay nombre. Un SHA missing es Skipping., 0, también con --no-undefined.
  • Usar --always como garantía de SHA. Verificado: --always --tags en un commit adelante del tag sigue undefined.
  • Confundir tags/v1~N (N padres hacia atrás) con v1-N-g de describe (N commits encima). No son el mismo eje.
  • --tags --name-only como SemVer. Omite tags/ y puede devolver v1~1 o lw. No es un Release.
  • Get a commit / list commits en GitHub. Eso es el remoto. name-rev es local.

Receta (60 segundos)

Solo en un worktree propio:

git status -sb
git name-rev --name-only HEAD
git name-rev --no-undefined --name-only -- "$sha"; echo $?

Si el ticket es “¿cerca de qué tag está?”: --tags --name-only. Si sale undefined, el commit no es ancestro de un tag; no inventes tag-N-g.

Si el ticket es “versión del checkout”: describe, no name-rev.

Cero --all. Cero --annotate-stdin. Cero REST.

--all lista cada commit alcanzable; un agente pregunta un SHA

name-rev vs describe vs SHA

name-rev responde hacia atrás desde una ref. describe responde hacia adelante desde un tag. rev-parse da el SHA; no busca nombre. show-ref pregunta si una ref existe, no dónde cae un commit.

log --oneline no sustituye un name-rev de un SHA. tag crea refs/tags/; aquí solo lees.

Checklist

  • Worktree propio. git status -sb. Un commit-ish por pregunta.
  • Nombre: --name-only. Tags: --tags. Fallar: --no-undefined (128 ≠ missing).
  • Cero --all. Cero --annotate-stdin. Cero --stdin.
  • undefined es 0. Missing también. No parsees Skipping.
  • Versión = describe. SHA = rev-parse.
  • Cero Get a commit en GitHub para “nombrar” un SHA local.

FAQ

¿Por qué --tags en el tip de una rama sale undefined y describe --tags imprime lw-1-g…? Porque name-rev solo nombra ancestros de las refs elegidas. Un commit encima del tag no es tags/lw~N. Verificado.

¿--always me salva el undefined? El man: fallback a SHA abreviado. Verificado en Git 2.50.1 / Apple Git-155: --always --tags en un commit no nombrable sigue undefined, 0. No lo uses como contrato.

¿--annotate-stdin sirve para un SHA corto? No. El man: sustituye hex de 40 caracteres. Verificado: 12 hex no cambian.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. name-rev no es describe: nombra hacia atrás; no arma tag-N-gSHA.