Guía9 min

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.

GitHub
Pila de stashes junto a un working tree que volvió a HEAD, con el agente aislado en otro path

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.

Pila refs/stash: el tope es stash@0, el disco volvió a HEAD

Comandos que el agente sí / no corre

QuieroComandoTrampa
Guardar edits trackeados y dejar HEAD limpiogit stash push -m "agent/<ticket>"Sin -m sale WIP on …; imposible de filtrar después
Ver qué haygit stash list / git stash show -ushow sin -u no lista untracked del stash
Aplicar sin borrargit stash apply stash@{n}Default es @{0}. Nombra el índice
Aplicar y borrar si okgit stash popSi hay conflictos, no se borra. Hay que drop a mano
Aislar un stash que ya no aplica en esta ramagit 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éngit stash push -u -m "…"Después corre git clean de untracked. No es un “extra flag inofensivo”
Sacar ignorados tambiéngit stash push -aMete .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”.

apply nombra el índice; drop solo si el árbol quedó limpio

Lo que el agente no corre

  • git stash en el checkout del humano. Ahí el aislamiento es worktree, no stash.
  • git stash -a / --all. El man: stashea ignored y untracked y luego git clean. Eso mete .env en refs/stash.
  • git stash clear.
  • git stash drop sin índice (el default es @{0}, que puede ser el del humano).
  • git stash pop en 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 stash sin -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.
  • -m con id de ticket. Cero WIP on.
  • stash list antes de apply/pop/drop.
  • Apply nombra stash@{n}. Drop solo si status quedó limpio.
  • Sin -a. -u solo si el ticket pide mover untracked y no hay secrets en disco.
  • Sin clear. Sin save.
  • 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).