Guía9 min

git prune para coding agents: plumbing, no housekeeping

Resumen

git prune borra objetos sueltos inalcanzables. Diagnóstico con -n. Cero --expire=now. Cero sin dry-run. No es gc ni clean. Git 2.50.1.

GitHub
Objetos sueltos inalcanzables: prune los borra; HEAD y el working tree no se mueven

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 prune borra objetos sueltos inalcanzables del object database. El man (git-prune(1); git-scm.com/docs/git-prune HTTP 200, last-modified 2026-08-31; pie del man local Git 2.54.0, 2026-04-19; binario Git 2.50.1 / Apple Git-155): Prune all unreachable objects from the object database. SYNOPSIS: git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...].

No es gc. gc es porcelain: empaqueta, recorta reflog y ya llama prune con gracia (gc.pruneExpire, default 2 weeks). El man de prune lo dice al inicio: In most cases, users should run git gc, which calls git prune.

Tampoco es clean. clean borra untracked del working tree. prune no lista untracked. No toca el índice ni HEAD.

Contrato: git prune -n. Cero prune a pelo. Cero --expire=now. Cero -v volcado al LLM. Housekeeping = gc --auto --quiet.

Qué hace (y qué no)

Sin -n, prune escribe: corre git fsck --unreachable con las refs de refs/, tira sueltos inalcanzables y llama git prune-packed (sueltos que ya están en un pack). También limpia entradas de .git/shallow que ninguna ref alcanza.

El man: unreachable, packed objects will remain. Si quieres tirar packed, eso es git-repack(1), no prune. Un agente no encadena prune + repack.

--expire <time>: solo sueltos más viejos que esa fecha. Sin --expire, no hay gracia. Verificado abajo: un blob dangling recién creado desaparece con git prune a pelo. gc pasa --expire 2.weeks.ago. Por eso el man manda a gc.

-n / --dry-run: Do not remove anything; just report what it would remove. Ese es el único modo autónomo.

-v reporta cada objeto y lo borra si no hay -n. --progress es chatty. Heads extra en la línea: keep objects reachable from listed heads además de refs/. Un agente no pasa SHAs ajenos para “conservar”.

NOTES: users will not need to call git prune directly. Para qué objetos cuenta como unreachable, el man remite a git fsck --unreachable.

Verificado 2026-09-06 (Git 2.50.1 / Apple Git-155). Repo mínimo, un commit, working tree limpio:

  • git prune: 0. rev-parse HEAD igual. status -sb sin cambios en tracked.
  • git prune -n: 0. No borra.
  • git prune -v: 0. Silencio si no hay sueltos.
  • git prune --expire=now: 0. HEAD igual.
  • git prune --expire=2.weeks.ago: 0.
  • Blob suelto (hash-object -w, nadie lo referencia): git prune 0 y cat-file -e 1 (ya no existe).
  • El mismo blob fresco + git prune --expire=2.weeks.ago: cat-file -e 0. La gracia lo deja.
  • El mismo blob fresco + git prune -n --expire=now: imprime el SHA y el tipo; cat-file -e 0. Dry-run no borra.
  • --foo: 129, unknown option `foo'.
  • Fuera de un repo: 128, not a git repository.

prune -n lista sueltos; sin -n el default no tiene gracia de 2 semanas

Lo que el agente sí / no corre

QuieroComandoTrampa
¿Qué se iría?git prune -ngit prune a pelo “para limpiar”
Housekeepinggc --auto --quiet--expire=now para “asegurarme”
¿Sigue vivo un SHA?cat-file -e-v al LLM y luego borrar
Untrackedclean -nprune no lista el working tree

Prohibido en autónomo:

  • git prune sin -n. Borra sueltos ahora. No es el default de gc.
  • --expire=now. El man de gc: sube el riesgo si otro proceso escribe. prune directo ni siquiera espera 2 weeks.
  • -v sin -n. Reporta y borra. Cierre = dry-run, no dump.
  • Encadenar git repack porque el man dijo que packed queda. Eso es otro comando, otro contrato.
  • Confundirlo con gc. gc orquesta prune con gracia. prune suelto salta la gracia.
  • Confundirlo con clean. clean opera untracked. prune no.
  • Correrlo en el worktree del humano o en main. Solo worktree propio.
  • Tratar prune como undo. No mueve HEAD. Recuperar un commit es reflog.
  • Pasar heads extra (git prune $(git rev-parse --all)) en un clone que no es laboratorio. El EXAMPLE del man es para alternates, no para un agente.

Receta (60 segundos)

Solo en un worktree propio, y solo si un comando ya habló de objetos sueltos o el disco lo pide:

git status -sb
git prune -n
echo $?
git rev-parse HEAD
  • 0, stdout vacío, HEAD igual: nada que tirar. Reporta “prune dry-run vacío” y para.
  • 0 y lista SHA + tipo: hay sueltos inalcanzables. No corras prune sin -n. Si el disco lo pide, gc --auto --quiet.
  • 128: no hay repo. No reintentes con --expire=now.
  • 129: opción desconocida. No añadas flags de clean.

Cierre = el dry-run. Cero commit. Cero push a main. Cero “ahora sin -n”.

--expire=now salta la gracia; packed inalcanzable se queda; housekeeping es gc --auto

prune vs gc vs clean vs cat-file

gc es housekeeping: --auto --quiet. Cero --aggressive. Cero --prune=now. El man de prune: en la mayoría de casos corre gc.

clean opera el working tree. git clean -n primero; nunca -fdx. prune no lista untracked.

cat-file -e pregunta un SHA: 0 existe, 1 no. prune recorre inalcanzables sueltos. No intercambies uno por el otro.

reflog mantiene vivos commits locales. prune no es reflog expire. Un agente no acorta esa gracia para “hacer sitio”.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. prune no es gc: plumbing que borra sueltos, no housekeeping con gracia.