git stash para coding agents: no es un worktree ni un backup
Resumen
git stash guarda working tree e index y deja el disco igual a HEAD. Sin args es stash push. pop aplica y borra; si hay conflictos no borra. -u mete untracked y corre git clean. -a mete ignorados. Un agente no hace stash en el checkout del humano ni stash clear.

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.
Un coding agent que corre git stash en tu checkout no “limpia el árbol”: te esconde el trabajo y lo deja en refs/stash, donde el siguiente agente puede hacer pop del stash equivocado. El manual de Git (2.55.0, 2026-06-29) es claro: stash grava working tree e index y revierte el disco a HEAD. No es un worktree. No es un backup de untracked. No es git clean.
Esta guía no sustituye worktrees ni gitignore. El contrato aquí: cuándo un agente puede stashear, qué flags están prohibidos, y por qué pop no es el default.
Qué guarda (oficial)
git stash sin argumentos = git stash push. El mensaje default es WIP on <rama>. El último stash vive en refs/stash; los anteriores, en el reflog: stash@{0} es el más reciente, stash@{1} el de antes. Un entero n equivale a stash@{n}. Si no pasas <stash>, Git asume stash@{0}.
Un stash es un commit merge: el árbol de W es el working tree; el primer padre es HEAD al crear; el segundo padre es el index. Por eso apply --index intenta devolver también el stage, y puede fallar si ya hay conflictos en el index.
git stash save está deprecado a favor de push. save no acepta pathspec: todo argumento no-opción se concatena como mensaje. Un agente que escribe git stash save src/foo.ts no stashea ese path: lo usa de mensaje.

Comandos que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
| Guardar edits trackeados y dejar HEAD limpio | git stash push -m "agent/<ticket>" | Sin -m sale WIP on …; imposible de filtrar después |
| Ver qué hay | git stash list / git stash show -u | show sin -u no lista untracked del stash |
| Aplicar sin borrar | git stash apply stash@{n} | Default es @{0}. Nombra el índice |
| Aplicar y borrar si ok | git stash pop | Si hay conflictos, no se borra. Hay que drop a mano |
| Aislar un stash que ya no aplica en esta rama | git stash branch agent/from-stash stash@{n} | Crea rama desde el commit original del stash, aplica, y si el ref es stash@{…} lo dropea |
| Sacar untracked también | git stash push -u -m "…" | Después corre git clean de untracked. No es un “extra flag inofensivo” |
| Sacar ignorados también | git stash push -a | Mete .env, secrets, build. Prohibido en harness autónomo |
pop: “Remove a single stashed state from the stash list and apply it”. El working directory debe coincidir con el index. Si aplicar falla por conflictos, sigue en la lista. El humano resuelve y llama git stash drop. Un agente que reintenta pop del mismo @{0} en un árbol sucio duplica conflictos.
apply es pop sin borrar. A diferencia de pop, <stash> puede ser cualquier commit que se vea como stash (push o create). Úsalo cuando no estás seguro de que este working tree es el dueño del stash.
clear borra todos los entries. El man avisa: quedan sujetos a prune y pueden ser irrecuperables. Un agente no corre clear. Tampoco drop sin el índice explícito que el humano pidió.
--keep-index (solo push/save): deja intacto lo ya staged. --patch implica --keep-index y es interactivo: no en headless.
Receta para un agente (60 segundos)
El default correcto no es stash. Es un worktree. Stash entra solo si el agente ya está en un path dedicado y necesita un árbol limpio dentro de ese path (por ejemplo, para git pull --ff-only o para correr tests sobre HEAD).
git status
git stash list
git stash push -m "agent/ticket-123 before pull"
git stash list # el nuevo es stash@{0}
# … pull / test sobre HEAD …
git stash apply stash@{0}
git status # si limpio:
git stash drop stash@{0}
apply + drop en dos pasos. Si apply deja conflictos, no hagas drop. No hagas pop “porque es más corto”.
Paths: git stash push -m "…" -- src/lib/foo.ts. El -- es obligatorio en modo corto (git stash sin push) para que un subcomando mal escrito no cree un stash.
Worktrees: el stash es por repositorio, no por worktree. refs/stash es compartido. El agente A en ../agent-login y el humano en el principal ven la misma pila. Por eso el mensaje lleva agent/<ticket> y el apply nombra stash@{n} leído de list, no “el último”.

Lo que el agente no corre
git stashen el checkout del humano. Ahí el aislamiento es worktree, no stash.git stash -a/--all. El man: stashea ignored y untracked y luegogit clean. Eso mete.envenrefs/stash.git stash clear.git stash dropsin índice (el default es@{0}, que puede ser el del humano).git stash popen un árbol con index sucio. El man exige working directory = index.git stash save. Deprecado; además se come el pathspec como mensaje.- Asumir que untracked sobrevivió un
stashsin-u. No. Solo working tree e index trackeados.
Untracked que el agente “perdió” no está en el stash: está en disco o lo borró un clean de -u. Revisa git status y gitignore antes de inventar un stash pop.
Checklist
- El agente no stashea en el principal del humano.
-
-mcon id de ticket. CeroWIP on. -
stash listantes de apply/pop/drop. - Apply nombra
stash@{n}. Drop solo sistatusquedó limpio. - Sin
-a.-usolo si el ticket pide mover untracked y no hay secrets en disco. - Sin
clear. Sinsave. - Si el stash ya no aplica en esta rama:
git stash branch …, no force-pop.
FAQ
¿Stash reemplaza un worktree? No. Worktree aísla HEAD e index. Stash comparte refs/stash entre todos los worktrees del repo.
¿pop es seguro si solo hay un stash? No. Otro proceso puede haber pusheado otro encima. Lista, nombra, apply.
¿-u borra untracked del disco? Sí: los stashea y luego git clean. Si el apply falla, el untracked está en el stash, no en disco.
¿Puedo recuperar un clear? El man dice que puede ser imposible. No lo corras.
¿--index? Solo pop/apply. Intenta devolver el stage. Falla si el index ya tiene conflictos.
El curso instalar un agente cubre el loop local. El aislamiento de red y secretos es sandboxing. Stash no es ninguna de las dos: es un cajón compartido con nombre feo por default.
Verificado 2026-09-03 contra https://git-scm.com/docs/git-stash (manual 2.55.0).
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git status para coding agents: porcelain, XY, no el long

Reusable workflows: workflow_call, no copies el YAML entre repos

schedule (cron) en GitHub Actions: UTC, no cada minuto
