Guía9 min

git reflog para coding agents: tips locales, no historia publicada

Resumen

git reflog lista tips locales de una ref, no la historia publicada. show equivale a git log -g. HEAD@{n} es el valor n-ésimo previo. expire toma gc.reflogExpire (90 días) y gc.reflogExpireUnreachable (30). Un agente lista con -n; no corre expire, drop ni delete. Git 2.50.1.

GitHub
Una cadena local de tips HEAD@{n} junto a un remoto que no se entera

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 reflog no recupera un commit que ya empujaste. El man (git-reflog(1), Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-reflog HTTP 200, last updated in 2.51.1; 2.51.2 → 2.55.0 sin cambios) administra reference logs: cada vez que el tip de una rama u otra ref se mueve en este clone, Git anota el valor anterior. HEAD@{2} es “donde HEAD estuvo hace dos movimientos”; master@{one.week.ago} es “dónde apuntaba master hace una semana aquí”. El remoto no tiene esa bitácora.

Esta guía no sustituye reset (mueve HEAD) ni log (walk de parent links). El contrato: qué subcomando corre un agente, qué selector de revisiones usa, y por qué expire/drop/delete están prohibidos.

show es el default; no es git log

Sin subcomando, o con show, lista el reflog de la ref (default HEAD). El man: git reflog show es alias de git log -g --abbrev-commit --pretty=oneline. Acepta las mismas opciones que log. El reflog de HEAD también registra cambios de rama.

list imprime las refs que tienen reflog. exists <ref> sale 0 si hay reflog, distinto de 0 si no. Verificado 2026-09-04 en esta máquina (Git 2.50.1 / Apple Git-155): git reflog exists HEAD → exit 0; git reflog exists refs/heads/no-such-branch-xyz → exit 1. gc.reflogExpire y gc.reflogExpireUnreachable no están seteados aquí (git config --get exit 1): aplican los defaults del man.

Un agente no pagina. -n / --oneline / --format recortan. -g en git log es el mismo walk; no vuelques -p.

show lista movimientos locales de HEAD; el remoto no aparece

Lo que el agente sí / no corre

QuieroComandoTrampa
Ver últimos tips de HEADgit reflog show -n 20 --onelinegit reflog sin tope (el pager y el dump al LLM)
SHA de hace N movimientosgit rev-parse --verify 'HEAD@{N}'HEAD@{N} sin comillas en un shell que come {}
¿Hay reflog?git reflog exists HEADasumir que un SHA huérfano vive para siempre
Listar refs con bitácoragit reflog listdrop --all “para limpiar”

Prohibido en autónomo:

  • expire. El man: recorta entradas más viejas que expire, o más viejas que expire-unreachable y no alcanzables desde el tip. Si no pasas --expire, usa gc.reflogExpire (default 90 días, git-gc(1) HTTP 200, last updated in 2.52.0). --expire-unreachable usa gc.reflogExpireUnreachable (default 30 días). --expire=all / --expire=now (en gc: now) tira sin mirar edad. --expire=never apaga el recorte de alcanzables. Un agente no decide la retención del clone del humano.
  • drop. Borra el reflog entero de las refs. Contrasta con expire/delete, que quitan entradas y dejan el archivo. --all (con o sin --single-worktree) es irreversible para esa bitácora.
  • delete <ref>@{specifier}. Quita una entrada exacta (master@{2}), no el reflog. El man: no es comando de usuario típico. Un agente no reescribe la bitácora.
  • write. En 2.51.1 el man documenta git reflog write <ref> <old-oid> <new-oid> <message>: append de una entrada; ref fully-qualified; OIDs sin abreviar, objetos existentes. Fabricar un movimiento es mentir al historial local.
  • --updateref / --rewrite / --stale-fix. Mueven la ref al @{0} que quede, reescriben el SHA “old” de la entrada siguiente, o recorren todos los objetos alcanzables (coste de git prune) para tirar commits rotos. Eso es reparación de corrupción, no undo de un agente.
  • expire / drop --all sobre worktrees ajenos. --single-worktree limita al árbol actual; el default de --all toca todos. Un agente vive en worktree propio y no limpia el del humano.

--dry-run / -n en expire y delete solo muestra. Verificado aquí: git reflog expire --dry-run --verbose HEAD imprime keep en cada entrada reciente; no borra. Sirve para leer, no para “probar a ver”.

Receta (60 segundos)

Solo en un worktree propio, y solo para leer:

git reflog exists HEAD
git reflog show -n 20 --oneline
git rev-parse --verify 'HEAD@{1}'

Si el humano pide “el commit de antes del reset”:

git reflog show -n 30 --oneline
git rev-parse --verify 'HEAD@{1}'   # o el índice que coincida
# luego: commit nuevo / PR. Cero reset --hard, cero expire.

gitrevisions(7) (HTTP 200): <ref>@{<n>} es el n-ésimo valor previo de esa ref (master@{1} = inmediato anterior). <ref>@{<date>} usa la bitácora local (HEAD@{5 minutes ago}). @{<n>} sin ref = reflog de la rama actual. @{-<n>} es la n-ésima rama/commit checkout antes, no un SHA del reflog de HEAD. No los mezcles.

Un SHA que solo vive en el reflog no está en el remoto. Empujarlo es publicar historia que el humano quizá no quería. Cierre = PR, no force-push.

expire y drop recortan o borran la bitácora; un agente no los corre

Reflog local vs GitHub

El reflog no viaja en fetch/push. Si el tip se reescribió y el objeto ya no es alcanzable, git gc puede tirarlo cuando vence la gracia. git-gc(1): gc.reflogExpire default 90 días; gc.reflogExpireUnreachable default 30 (más agresivo, porque esas entradas ya no cuelgan del tip). gc.pruneExpire (default 2 weeks) es otra perilla: objetos sueltos, no el reflog. Un expire --expire=now local no limpia GitHub.

GitHub Docs (Deleting and restoring branches in a pull request, HTTP 200 2026-09-04): puedes restaurar la head branch de un PR cerrado con Restore branch al pie del PR. No hay reflog del servidor en tu clone. Si el branch nunca tuvo PR, esa UI no aplica.

Borrar un secreto no es reflog delete. GitHub Docs (Removing sensitive data from a repository): primero revoca o rota el secreto; reescribir historia es opcional y pide coordinación. La herramienta documentada es git-filter-repo con --sensitive-data-removal (versión ≥ 2.47). Un force-push no borra forks, PRs cacheados ni clones ajenos; Support solo ayuda si rotar no basta. Un agente no reescribe historia ni llama a Support.

stash usa el reflog de refs/stash (stash@{n}). No corras expire sobre stash “para ordenar”.

Checklist

  • Worktree propio. Leer, no podar.
  • show -n / --oneline. Cero dump, cero pager.
  • Selectores: HEAD@{n} entre comillas. No @{-n} si buscas un SHA.
  • Cero expire, drop, delete, write, --updateref, --rewrite, --stale-fix, --all.
  • SHA recuperado → commit nuevo o PR. Cero reset --hard autónomo. Cero force-push.
  • Secreto filtrado: rotar primero, no reflog delete.

FAQ

¿HEAD@{1} es el padre del commit? No. Es el tip anterior de HEAD (un checkout, un reset, un commit). El padre es HEAD^.

¿git reflog deshace un --hard? Muestra el SHA que HEAD tenía. Recuperar el árbol es otra operación (reset / restore), y --hard autónomo sigue prohibido.

¿Puedo expire --expire=now en CI para “no dejar rastro”? El reflog es local. Eso no borra el remoto. En un clone efímero da igual; en el disco del humano, no.

¿exists vs show? exists es un sí/no (exit 0/≠0). show lista. Si exists falla, no hay bitácora que consultar.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. Reflog no es log: recorre movimientos de una ref, no parent links.