git rm para coding agents: index y disco, no /bin/rm
Resumen
git rm quita paths del index y, salvo --cached, también del working tree. El man exige que coincidan con el tip de la rama y no estén staged, salvo -f. Un agente nombra paths, corre --dry-run primero y no usa -r, -f ni globs sin comillas. 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 rm no es /bin/rm. El man (git-rm(1), Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-rm HTTP 200, last updated in 2.50.0; 2.50.1 → 2.55.0 sin cambios) quita paths del index, o del index y del working tree. No hay flag para borrar solo el disco y dejar el path en el index: para eso el man manda /bin/rm. El inverso —sacar del index y dejar el archivo— es --cached.
GitHub Docs (Deleting files in a repository, HTTP 200 2026-09-04): en la UI hace falta permiso de escritura; si no lo tienes, GitHub te ofrece fork + PR. Borrar el archivo no lo saca del historial. Si el path tenía un secreto, sigue en Git. Contrato: paths nombrados, -n primero, commit nuevo, cero -f/-r autónomo.
Esta guía no sustituye clean (untracked) ni restore (copiar un path desde una fuente). El contrato: qué forma corre un agente, qué flags están prohibidas, y por qué rm de disco no es git rm.
Index y disco no son lo mismo
Sin --cached, el path tiene que coincidir con el tip de la rama y no tener updates staged. El man: ese check se salta con -f. Con --cached, el staged tiene que coincidir con el tip o con el disco; el working tree no se toca.
git rm solo conoce paths que Git rastrea. Un untracked no entra. Un directorio líder (dir) exige -r explícito para borrar dir/file1, dir/file2 y subdirectorios. El glob cruza fronteras: git rm 'd*' también pega a d2; git rm 'd/*' no.
Sparse-checkout: el man solo quita paths dentro del cone. --sparse actualiza entradas fuera. Un agente no ensancha el cone “para que el rm pase”.

Lo que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
| Quitar un path tracked | git rm -- path/to/file.ts | /bin/rm y luego esperar que el commit lo note |
| Dejar el archivo, sacarlo del index | git rm --cached -- path | --cached sobre un dir sin -r |
| Ver qué haría | git rm -n -- path | -n + -f “porque el check molesta” |
| Untracked | clean -n | git rm de un path que Git no conoce |
Prohibido en autónomo:
-f/--force. El man: override the up-to-date check. Si el path no coincide con el tip o hay staged,-fborra igual. Un agente no descarta edits locales para “limpiar”.-rsobre un directorio líder. Recursivo a todos los tracked debajo. Ungit rm -r srcno es “el file del ticket”.- Globs sin comillas. El ejemplo oficial
git rm Documentation/\*.txtcita el asterisco para que Git expanda.git rm -f git-*.shdeja que el shell liste; no borrasubdir/git-foo.sh. Un glob mal citado se come el vecino. --ignore-unmatchpara silenciar un path que no existe. Exit 0 con cero matches esconde un typo. Si el path no está, el agente para.--pathspec-from-file=-leyendo un dump enorme. Pathspecs por stdin no son un “rm masivo” de sesión.--sparsepara forzar entradas fuera del cone.git ls-files -z | xargs -0 rm -fdel apartado vendor drop del man. Eso vacía el working tree. No es el ticket.git add -A/git commit -a“para que Git note los deletes”. El man los cita como atajo humano. Un agente nombra paths (add) y commitea el index (commit).- Submodule
git rmautónomo. El man: solo gitfile (≥ 1.7.8) sale del work tree; un.gitde submodule se mueve al superproject para no tirar historia. Ignored files are deemed expendable y no bloquean. Checkout local sin commit =git submodule deinit, nogit rm. - Reescribir historia para “borrar de verdad”. GitHub Docs (Removing sensitive data from a repository, HTTP 200 2026-09-04): el delete de un file no saca el blob de Git. Primero revoca o rota el secreto. La herramienta documentada es
git-filter-repo. Un agente no filtra el historial ni hace force-push.
-q / --quiet oculta la línea rm por archivo. En headless quieres verla.
Receta (60 segundos)
Solo en un worktree propio:
git status -sb
git rm -n -- src/lib/foo.ts
git rm -- src/lib/foo.ts
git diff --cached --stat
Si el archivo debe quedar en disco (dejar de trackear un .env que ya está ignorado):
git rm --cached -- .env.local
# el file sigue; el index ya no lo tiene
Si el path ya desapareció del disco (/bin/rm de un humano) y solo falta el index:
git diff --name-only --diff-filter=D
git rm --cached -- path/que/ya/no/está
El man documenta exactamente ese pipeline (git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached). Un agente no encadena xargs; nombra el path que vio.
Cierre = commit + PR. Cero push a main.

UI de GitHub vs clone local
GitHub Docs (Deleting files in a repository): puedes borrar un file o un directorio entero desde el repo en la web. Eso crea un commit en GitHub, no en tu worktree. Un agente que “ya lo borró en la UI” deja el clone sucio al revés: el path sigue en disco hasta el próximo fetch/pull.
Si el path tenía datos sensibles, la misma página reenvía a Removing sensitive data from a repository. El dato sigue en history, forks, PRs cacheados y clones ajenos. Rotar primero. git rm del tip no es un purge.
Untracked se borra con clean (-n primero; nunca -fdx). Restore copia un path; no lo saca del index. git rm --cached es el unstage que deja disco.
Verificado 2026-09-04 en esta máquina (Git 2.50.1 / Apple Git-155): git rm -n -- README.md lista el path y no lo borra (exit 0). git rm -n -- no-such-file-xyz falla con did not match any files (exit 128). --ignore-unmatch convertiría eso en 0: por eso está prohibido.
Checklist
- Worktree propio.
git status -sb. Paths del ticket, no el árbol. -
git rm -n -- <path>antes del rm real. - Cero
-f, cero-rde directorio, cero glob sin comillas, cero--ignore-unmatch, cero--sparse. -
--cachedsolo si el disco debe quedarse. - Untracked → clean, no
git rm. - Secreto filtrado: rotar primero, no
git rm+ force-push. - Index staged → commit + PR.
FAQ
¿rm archivo y luego commit? El man: git commit -a y git add -u notan deletes de tracked. Un agente no usa -a. Si el disco ya no tiene el path: git rm --cached -- path (o git rm -- path si aún está).
¿git rm .? Pathspec . con tracked en la raíz, y -r si apuntas a un dir. No. Nombra el file.
¿--cached deshace un add? Saca el path del index. Si el contenido staged no coincide con tip ni disco, el man se niega (salvo que encaje una de las dos). No es restore --staged: restore copia desde una fuente; rm --cached elimina la entrada.
¿Borra el historial? No. El blob vive en commits viejos. GitHub Docs: hay que sacar el file de la historia del repo; git rm del tip no alcanza.
El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. git rm no es clean: borra tracked del index, no untracked del disco.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git describe para coding agents: nombre legible, no un Release

git merge-base para coding agents: ancestro común, no folklore

git check-ignore para coding agents: regla ganadora, no adivinar
