git maintenance para coding agents: housekeeping programado, no gc a pelo
Resumen
git maintenance run orquesta tareas de object database (commit-graph, prefetch, loose-objects, incremental-repack) sin mover HEAD. --auto --quiet es el contrato. Cero start/register/unregister (tocan config global y el scheduler). Cero --task=gc en el clone del humano. Cero mezclarlo con git gc. Distinto de prune y de count-objects. Git 2.50.1.

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 maintenance corre tareas para optimizar los datos del repositorio: acelera otros comandos Git y reduce el almacenamiento. El man (git-maintenance(1); git-scm.com/docs/git-maintenance; man local Git 2.54.0, 2026-04-19; binario Git 2.50.1 / Apple Git-155): Run tasks to optimize Git repository data, speeding up other Git commands and reducing storage requirements for the repository. SYNOPSIS: git maintenance run [<options>] · git maintenance start [--scheduler=<scheduler>] · git maintenance (stop|register|unregister) [<options>].
Porcelain que escribe (git add, git fetch) no se toma el tiempo de compactar: esa escala con el repo entero. maintenance es el orquestador. Por default, solo maintenance.gc.enabled es true. El resto de tareas se enciende con --task= o con maintenance.<task>.enabled.
No es gc. gc es una tarea cara: repacks all Git objects into a single pack-file y can also be disruptive. El man de maintenance lo dice explícito: no combines git gc con git maintenance run. Si hace falta gc, git maintenance run --task=gc — y un agente no lo corre en el clone del humano.
Tampoco es prune ni count-objects. prune borra sueltos. count-objects mira. maintenance programa y ejecuta housekeeping.
Contrato: git maintenance run --auto --quiet. Cero start / register / unregister / stop. Cero --task=gc autónomo. Cero mezclarlo con git gc. Cero reescribir maintenance.*.
La regla de oro: run, no el scheduler
run ejecuta una o más tareas ahora, en este repo, y toma lock del object database. start y register escriben config global (maintenance.repo en ~/.gitconfig) y instalan un scheduler (crontab / systemd-timer / launchctl / schtasks). Un agente no toca la máquina del humano.
register además pone maintenance.strategy=incremental si no existía y apaga el auto-gc de primer plano con maintenance.auto=false en el repo actual. Ese flag sobrevive a unregister. Un agente que “registra para ayudar” deja el clone sin auto-gc.
start = register + scheduler horario. En macOS usa launchctl (plist en ~/Library/LaunchAgents/org.git-scm.git*), no crontab: crontab no tiene contexto de usuario y los credential helpers fallan. Un agente no crea ni pisa esos plist.

Tareas (qué corre, qué no)
El man lista las tareas aceptadas por --task=. Estrategia incremental (la de register): gc deshabilitado; commit-graph y prefetch hourly; loose-objects e incremental-repack daily; pack-refs weekly.
| Tarea | Qué hace | Agente |
|---|---|---|
commit-graph | Escribe commit-graph incremental y verifica. No expira .graph del chain anterior. | --task=commit-graph --quiet OK |
prefetch | git fetch por remoto hacia refs/prefetch/. No mueve remote-tracking ni tags. | OK; no es un fetch del humano |
loose-objects | Dos pasos: borra sueltos ya empaquetados; packea un lote (loose-, default 50k). | --auto sí; no a pelo en clone ajeno |
incremental-repack | multi-pack-index expire + repack de packs chicos. | --auto sí |
pack-refs | Junta refs sueltos en un archivo. | --auto / weekly |
gc | El gc completo. Caro y disruptivo. | Cero autónomo |
reflog-expire | Recorta reflog. Ver reflog. | Cero acortar gracia |
rerere-gc | gc del rr-cache. Ver rerere. | Solo si --auto lo pide |
worktree-prune | Borra worktrees stale. Ver worktrees. | Cero now sobre worktrees ajenos |
El man: it is not advisable to enable both the loose-objects and gc tasks at the same time — gc suelta inalcanzables para que loose-objects los limpie después; juntos se pisan.
--auto (con run): corre solo si hay umbral. maintenance.commit-graph.auto default 100 commits fuera del graph; loose-objects.auto 100 sueltos; incremental-repack.auto 10 packs fuera del midx. Cero --schedule a mano (eso es del cron de start). --quiet no reporta progreso a stderr.
Verificado 2026-09-06 (Git 2.50.1 / Apple Git-155). Repo mínimo, un commit, working tree limpio:
git maintenance run --task=commit-graph --quiet: 0.rev-parse HEADigual.status -sbsin cambios.git maintenance run --auto --quiet: 0. Repo chico: umbrales no se cumplen; no hay trabajo. HEAD igual.git maintenance run --task=prefetch --quiet: 0. Sin remotos: no hay fetch. HEAD igual.git maintenance run --task=pack-refs --quiet: 0.git maintenance run --task=loose-objects --quiet: 0.git maintenance run --task=worktree-prune --quiet: 0.git maintenance run --task=rerere-gc --quiet: 0.--task=foo: 129, error: 'foo' is not a valid task.- Fuera de un repo: 128, not a git repository.
Lo que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
| ¿Hay housekeeping pendiente? | git maintenance run --auto --quiet | git gc a pelo “porque está lento” |
| Commit-graph al día | git maintenance run --task=commit-graph --quiet | start para “dejarlo programado” |
| Ver presión de sueltos | git count-objects -v | --task=gc o git gc --aggressive |
| ¿Sigue vivo un SHA? | git cat-file -e <sha> | reflog-expire / prune a mano |
Prohibido en autónomo:
git maintenance start/stop/register/unregister. Tocan~/.gitconfig(maintenance.repo), launchctl/crontab/schtasks y, enregister,maintenance.auto=falsedel repo. El humano no pidió un daemon.--task=gcen el clone del humano o enmain. El man: gc can be expensive for large repositories y disruptive. El contrato de gc sigue:--auto --quiet, cero--aggressive/--prune=now.git gcygit maintenance runen el mismo tick. El man: gc no toma el lock igual que maintenance; pueden corromper el object database. If possible, usegit maintenance run --task=gcinstead ofgit gc. Un agente no elige ese “if”.- Encender
loose-objectsygca la vez (maintenance.*.enabled). El man lo desaconseja. - Reescribir
maintenance.strategy,maintenance.<task>.enabled,maintenance.<task>.schedule,maintenance.auto. Son perillas del clone. - Confundir prefetch con fetch. prefetch escribe
refs/prefetch/; no actualizaorigin/*ni tags. Ungit pullposterior del humano sigue siendo su fetch. unregister --forcepara “limpiar” un register que el agente no debería haber hecho.- Correr maintenance en el worktree del humano. Solo worktree propio.
Receta (60 segundos)
Solo en un worktree propio, y solo si el disco o count-objects -v lo pide:
git status -sb
git maintenance run --auto --quiet
echo $?
git rev-parse HEAD
0y HEAD igual: listo. Reporta “maintenance --auto” y para.128: no hay repo. No reintentes constart.129: tarea u opción desconocida. No inventes un--task.
Cierre = el exit code. Cero commit. Cero push a main. Cero “ahora lo registro en launchctl”.

maintenance vs gc vs prune vs count-objects
gc es el housekeeping monolítico. --auto --quiet; cero --aggressive; cero --prune=now. maintenance lo puede invocar como tarea, pero la estrategia incremental lo apaga a propósito: prefiere commit-graph + loose-objects + incremental-repack, que no borran datos.
prune: -n primero; cero a pelo / --expire=now. No es el orquestador.
count-objects: -v para leer count / size / in-pack. Diagnóstico. Cero repack / prune-packed “porque el número es alto”.
rerere: rerere-gc es una tarea de maintenance (gracia 15/60 días). Un agente no corre git rerere gc a mano para “vaciar el cache”.
Lock: cada git maintenance run toma lock del object database. Dos runs concurrentes en el mismo repo: uno no corre. El man: si el lote horario de varios repos tarda más de una hora, chocan. Un agente no lanza maintenance en background (--detach no aplica aquí; eso es de gc) ni en paralelo sobre el mismo .git.
El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. maintenance no es gc: es el scheduler de tareas incrementales; el agente solo pulsa run --auto.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git hooks para coding agents: listar, no instalar ni --no-verify

git credential para coding agents: helpers, no tokens en el prompt

git verify-tag para coding agents: ningún release sin firma válida
