Guía9 min

git grep para coding agents: tracked, pathspec y techo de líneas

Resumen

git grep busca un patrón en tracked del work tree, en el index o en un tree. Un agente usa -n -F, pathspec y -m; nunca -O, patrón vacío ni --untracked de ignorados. Git 2.50.1.

GitHub
Un patrón se busca en blobs tracked; el pathspec recorta el árbol y el pager no se abre

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 grep no es grep -r ni la búsqueda de GitHub. El man (git-grep(1), Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-grep HTTP 200, last-modified 2026-08-31) busca patrones en tracked del work tree, blobs del index (--cached) o blobs de <tree>.... Sin tree ni --cached: working tree tracked. HEAD, index y working tree no se mueven.

GitHub Docs (Searching code (legacy), HTTP 200 2026-09-04): la UI/API indexa solo la default branch, files < 384 KB, repos con < 500 000 files. No es git grep. Un agente que quiere “dónde está este símbolo en este worktree” corre git grep; el que quiere “en GitHub.com” usa la UI o gh, no este comando.

Esta guía no sustituye status (XY del árbol) ni diff (parche). El contrato: qué forma corre un agente, qué flags fuerzan, y por qué el default no es un dump al LLM.

Tres superficies, un comando

SuperficieFlag / argsVe unstagedVe untracked
Work tree trackeddefaultno
Index--cachednono
Tree (HEAD, SHA)<tree>nono
Untracked--untrackeduntracked no ignorados
Ignorados--untracked --no-exclude-standardtambién .gitignore
Fuera de Git--no-indexn/ael cwd; incompatible con --cached/--untracked

Verificado 2026-09-04: un .env en .gitignore no sale con git grep TOKEN (exit 1) ni con --untracked (exit 1). Sale con --untracked --no-exclude-standard. Unstaged extra sí sale en default; --cached y HEAD no. Pathspec inexistente → exit 1. Tree inventado con --unable to resolve revision, exit 128.

El man: una cadena vacía como patrón casa todas las líneas. Verificado: git grep -e '' -- src/a.ts imprime el file entero.

pathspec recorta; -n numera; el árbol no se vuelca

Lo que el agente sí / no corre

QuieroComandoTrampa
¿Dónde está el símbolo?git grep -n -F -e foo -- src/git grep foo del repo entero al LLM
¿Qué files?git grep -l -F -e foo -- src/-c de todo el árbol “para ver”
¿Hay match?git grep -q -F -e foo -- src/-O “para abrir el file”
Literal con -git grep -F -e --flag -- src/patrón suelto que Git toma por opción
Index, no discogit grep --cached -n -F -e foo -- src/default (ve unstaged)
Tree commiteadogit grep -n -F -e foo HEAD -- src/HEAD + path sin --

Prohibido en autónomo:

  • -O / --open-files-in-pager. El man abre los files en el pager (less/vi). Un agente no interactúa con pager. El man: --threads se ignora si hay -O.
  • Patrón vacío (-e ''). El man: matches all lines. Dump del file.
  • --untracked --no-exclude-standard. El man: ignora .gitignore. Verificado: saca .env. gitignore no es sandbox; este flag lo empeora.
  • -a / --text sobre binarios. Default: Binary file X matches. -a imprime bytes con NUL al prompt. -I los salta (exit 1 si solo había binario).
  • -C/-A/-B/-W/-p anchos “por contexto”. El man imprime hunks; -W la función entera. Un agente acota con -m y pathspec, no con un radio de 50.
  • -P si el Git no se compiló con PCRE. El man: providing this option will cause it to die. Aquí 2.50.1 sí corre -P; no lo asumas en el VPS.
  • Varios <tree> a ciegas. Cada tree prefixea output (HEAD:path).
  • --no-index dentro del repo “porque grep del sistema”. El man: ignoring that the current directory is managed by Git. Mezcla untracked e ignorados según --exclude-standard.
  • Pager. Fija GIT_PAGER=cat o --no-pager.
  • Sustituir esto por la búsqueda de GitHub. Legacy code search no ve tu branch de feature.

Exit: 0 hay match, 1 no hay, 128 revisión inválida. -q no imprime; 0/1 igual. -m 0 sale ya con no-cero (verificado: exit 1). -m -1 = ilimitado (el default).

Receta (60 segundos)

Solo en un worktree propio:

git grep -n -F --max-count=20 -e "$pat" -- src/
git grep -l -F -e "$pat" -- src/

Si el humano pidió un file:

git grep -n -F -e "$pat" -- "$path"

Si solo hace falta sí/no:

git grep -q -F -e "$pat" -- src/

-e siempre si el patrón puede empezar por -. -- delante de pathspec (gitglossary(7), HTTP 200). Globs del man: git grep 'time_t' -- '*.[ch]'.

binario: default avisa; -a vuelca NUL al prompt

grep vs GitHub vs grep(1)

PreguntaComandoNo
¿En este clone, este path?git grep -n -F -e pat -- pathgrep -r del cwd
¿En el commit?git grep -n -F -e pat HEAD -- pathdefault (unstaged)
¿En GitHub default branch?UI / Code Searchgit grep del feature
¿Untracked a propósito?--untracked sin --no-exclude-standardvolcar .env

Booleanos del man: --or es default; --and tiene más precedencia; todos los patrones van con -e. --all-match: files que tienen ambas expresiones, no la misma línea. Verificado: git grep -e hello --and -e world -- src/a.ts casa la línea que tiene las dos.

--full-name: paths desde la raíz aunque el cwd sea un subdir. Un agente que parsea lo deja puesto.

Checklist

  • Worktree propio. Patrón del ticket, no “buscar por si acaso”.
  • -n -F -e + pathspec detrás de --. -l o -m si el hit-set puede ser grande.
  • Cero -O, patrón vacío, -a, --untracked --no-exclude-standard.
  • Cero pager. Cero GitHub search como si fuera el worktree.
  • 1 = no hay match (para). 128 = tree malo (para). No reintentes con otro SHA.

FAQ

¿git grep foo sin pathspec? El man recorre tracked del work tree. En un monorepo es un dump. Nombra src/, *.ts o el file del ticket.

¿--cached vs default? Default ve el disco (incluye unstaged). --cached ve el index. Para “¿ya está staged?” usa --cached; para “¿lo estoy editando?” el default.

¿Por qué no salió .env? Está ignorado. Default y --untracked lo respetan. No “arregles” con --no-exclude-standard.

¿-E o -F? -F si el símbolo es literal (useStore). -E si el humano pidió regex POSIX. Default del man: basic regexp (-G), no extended.

El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. git grep no es log: busca contenido, no historia.

Verificado 2026-09-04 contra git-grep(1) (Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-grep HTTP 200, last-modified 2026-08-31), gitglossary(7) pathspec (HTTP 200) y GitHub Docs “Searching code (legacy)” (HTTP 200; default branch, 384 KB). En esta máquina: no match exit 1; tree inválido con -- exit 128; .env ignorado salvo --untracked --no-exclude-standard; patrón vacío imprime todas las líneas; binario default no vuelca bytes; -a sí; -m 0 exit 1.