git update-index para coding agents: plumbing del index, no add
Resumen
git update-index registra paths en el index. El contrato autónomo es no usarlo: add para stagear, ls-files para leer bits, sparse-checkout para skip-worktree. Cero assume-unchanged, cacheinfo, --force-remove o --index-info. Distinto de add, ls-files y sparse-checkout. Git 2.50.1, man local verificado.

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 update-index modifica el index. El man (git-update-index(1); git-scm.com/docs/git-update-index HTTP 200, last-modified 2026-08-31; pie del man local Git 2.50.1.428.g0e8243, 2025-07-22; binario Git 2.50.1 / Apple Git-155): Register file contents in the working tree to the index. SYNOPSIS mezcla --add/--remove, --cacheinfo, --chmod, --assume-unchanged, --skip-worktree, --index-info, --stdin y <file>.... Un solo verbo, demasiados contratos.
El propio man remite a git add: See also git-add(1) for a more user-friendly way to do some of the most common operations on the index. Add es porcelain. update-index es plumbing. El agente autónomo no entra al plumbing.
Contrato: no corras git update-index autónomo. Stagear = git add path. Inspeccionar bits = ls-files -v / -t. Sparse = sparse-checkout, no --skip-worktree a mano. Cero --assume-unchanged para “ignorar” un tracked. Cero --cacheinfo. Cero --index-info. Cero --force-remove. Cero --replace. Cero --chmod headless. Cero --stdin.
Qué hace (y qué no)
Modifies the index. Each file mentioned is updated into the index and any unmerged or needs updating state is cleared. Sin flags extra, lee el working tree y escribe el blob + stat en el index. Default: ignora un path nuevo (--add hace falta) e ignora un path borrado del disco (--remove hace falta). No es un “add silencioso”.
No es add. Add pide paths explícitos, respeta ignore, tiene --dry-run y -p. update-index no confirma y sí mete un blob ausente (--cacheinfo).
No es ls-files. ls-files lee. -v marca H/S/M para assume-unchanged y skip-worktree. update-index escribe esos bits.
No es sparse-checkout. El man de skip-worktree lo dice en una frase larga y luego se retracta: The update-index flags and the read-tree capabilities relating to the skip-worktree bit predated git-sparse-checkout(1)… we strongly encourage the use of git-sparse-checkout(1) in preference to the low-level update-index and read-tree primitives.
No es gitignore. Ignore cubre untracked. El NOTES del man: Users often try to use the assume-unchanged and skip-worktree bits to tell Git to ignore changes to files that are tracked. This does not work as expected… Git does not provide a way to ignore changes to tracked files.
Tampoco es status. Status consulta el index; update-index lo muta. --refresh a ciegas puede borrar un unmerged.

Tabla: flag vs daño autónomo
| Flag | Qué hace el man | Agente autónomo |
|---|---|---|
| (paths) | Actualiza el index desde el working tree | No. Usa add con paths nombrados |
--add | Mete un path que no estaba | No. Add ya lo hace y respeta ignore |
--remove / --force-remove | Saca el path del index; force aunque el archivo siga en disco | Nunca. Force-remove implica --remove y deja el archivo huérfano en el árbol |
--refresh / --really-refresh | Re-mata stat(); really ignora assume-unchanged | No a ciegas. --refresh does not calculate a new sha1 |
--assume-unchanged | Promete que el archivo no cambia; Git omite lstat | Nunca para “ocultar” un config local |
--skip-worktree | Sparse: no escribir el archivo; ausencia ≠ delete | No a mano. Sparse-checkout es el porcelain |
--cacheinfo <mode>,<object>,<path> | Mete mode+SHA sin el archivo en el disco | Nunca. Es merge mínimo, no un stage |
--index-info | Lee stdin en 3 formatos (ls-tree / ls-files --stage) | Nunca. Scripts, no un turno de agente |
| `--chmod=(+ | -)x` | Cambia el bit ejecutable en el index |
--replace | Borra la entrada que choca (path vs path/file) | Nunca. Pierde el otro lado |
--stdin / -z | Paths por LF o NUL | No. Un path por argv, y ni eso autónomo |
--split-index / --untracked-cache / --fsmonitor | Extensiones del index | Config (core.*), no un flag por turno |
El man de --cacheinfo: used to register a file that is not in the current working directory. Eso no es “stagear un fix”. Es fingir un checkout. --index-info acepta tres formatos (ls-tree, ls-files --stage, legado); para meter stage 1/2 hay que borrar primero con mode=0. Un agente que pega eso mezcla un conflicto a mano.
assume-unchanged no es .gitignore
Sección USING “ASSUME UNCHANGED” BIT: en filesystems con lstat(2) caro (ejemplo del man: cifs), el bit evita el check. It makes Git to omit any checking and assume it has not changed. Si el archivo sí cambió, Git puede seguir sin enterarse. git ls-files -v marca esos paths con letra minúscula.
El man advierte el malentendido. assume-unchanged: el archivo sigue en el árbol; Git finge que no cambió. skip-worktree: Git evita escribirlo y trata su ausencia como “no es un delete”. Ninguno ignora un tracked.
NOTES, otra vez: alternate solutions are recommended. Config de ejemplo en el repo + copia a un nombre ignored. No bits mágicos.
Si un merge necesita tocar el path, Git will fail (gracefully). --assume-unchanged en package.json convierte el próximo pull en un conflicto manual.
skip-worktree: usa sparse-checkout
Tell git to avoid writing the file to the working directory when reasonably possible, and treat the file as unchanged when it is not present. Not all git commands will pay attention to this bit.
Comandos como switch/pull/merge evitan escribir esos paths, salvo conflictos. git add -u y commit -a no stagean el delete. Si el archivo aparece en un sparse checkout, Git limpia el bit. Un --skip-worktree suelto no sobrevive.
La guía de sparse-checkout fija cone, set + list, cero --no-cone. update-index no sustituye ese flujo.

Si el humano insiste
Un solo path, un solo flag, dry-run mental primero. Nunca HEAD. Nunca .. Nunca --stdin.
git ls-files -v -- path/to/file
git status --porcelain=v1 -- path/to/file
--refresh después de un read-tree que el humano pidió, no como “limpia el status”:
git update-index --ignore-missing --refresh
El man: --refresh does not calculate a new sha1 file or bring the index up to date for mode/content changes. Solo re-mata stat. Si el contenido cambió, esto no lo stagea.
--chmod=+x solo si el humano pide el bit ejecutable en el index y core.filemode miente. El man: you may need to use git update-index --chmod=.
--no-assume-unchanged path / --no-skip-worktree path para quitar un bit que alguien dejó. Quitar es más seguro que poner. Confirma con git ls-files -v -- path.
Cero --cacheinfo. Cero --info-only. Cero --unresolve autónomo.
Checklist
- ¿El objetivo es stagear un path? → add con el path, no update-index.
- ¿Quieres ver bits? →
git ls-files -v -- path, no mutar. - ¿Working tree grande? → sparse-checkout, no
--skip-worktreesuelto. - ¿Un tracked “que no se commitee”? → no hay API. Sample + ignore, no assume-unchanged.
- ¿Status raro post-merge? → no
--refresh -q --unmerged. Eso traga el error. - ¿Paths por stdin / NUL / cacheinfo? → no. Plumbing de script, no de turno.
- ¿
--force-removeporque el archivo “sigue ahí”? → no. Eso es borrar del index a propósito. - ¿
--replaceporque path vs path/file chocan? → no. Pierdes una de las dos entradas. - Extensiones (
split-index, untracked cache, fsmonitor) →git config, no un flag por PR. - Después de cualquier excepción humana:
git status --porcelain=v1ygit diff --cached --stat.
El curso instalar un agente no cubre el index. Esta guía y add sí.
FAQ
¿Por qué Git se niega a add y el agente piensa en update-index? Porque el path está ignored, es un conflicto o choca path/path/file. update-index --add no arregla ignore; --replace borra el otro lado. Lee status y gitignore.
¿Puedo usar --assume-unchanged en .env.local tracked? No. NOTES: Git no ignora cambios a tracked. El bit se cae en merge. Copia desde un sample ignored.
¿--skip-worktree para no bajar node_modules versionado? No. Eso es sparse-checkout o dejar de trackear el directorio. El bit no es un linter de “archivos pesados”.
¿--cacheinfo para stagear un blob que el agente ya hasheó? No. Salta el working tree. hash-object tampoco escribe el index sin -w, y -w autónomo está vetado.
¿--refresh o --index-version 4? Refresh no recalcula SHA; con --unmerged traga el conflicto. v4 comprime pathnames: no cambies el on-disk format del repo del humano.
Fuentes
- git-update-index(1), git-scm.com/docs/git-update-index — HTTP 200, last-modified 2026-08-31; man local Git 2.50.1.428.g0e8243 (2025-07-22).
- git-add(1) — porcelain del index; paths explícitos, no
.. - git-ls-files(1)
-v— lectura de assume-unchanged / skip-worktree. - git-sparse-checkout(1) — porcelain que sustituye skip-worktree a mano.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git checkout-index para coding agents: index al disco, no checkout

git mktree para coding agents: tree desde ls-tree, no desde el index

git commit-tree para coding agents: commit sin mover HEAD
