git check-attr para coding agents: qué attr gana, no leer .gitattributes a ojo
Resumen
git check-attr resuelve un pathname contra gitattributes. Un attr: path COLON SP attr COLON SP info. --all omite unspecified. --cached ignora el working tree. --source mira un tree-ish. Cero dump de .gitattributes. No es check-ignore. 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 check-attr resuelve atributos de gitattributes sobre un pathname. El man (git-check-attr(1); git-scm.com/docs/git-check-attr 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) imprime path COLON SP attr COLON SP info. HEAD, index y working tree no se mueven. No reescribe archivos.
Eso no es check-ignore. Ignore responde si un path está excluido. check-attr responde cómo Git trata ese path: text, eol, diff, binary, linguist-generated. Leer .gitattributes a ojo pierde macros (binary), líneas posteriores que pisan y el working tree sucio.
GitHub Docs (Customizing how changed files appear on GitHub, HTTP 200 2026-09-04) documenta linguist-generated. No sustituye este comando: Linguist corre en github.com. Aquí preguntas el clone.
Contrato: un attr o --all, paths explícitos, ramificar set / unset / valor / unspecified, cero --stdin al LLM.
Un path, un attr, cuatro infos
OUTPUT del man: <path> COLON SP <attribute> COLON SP <info> LF. Verificado con od sobre -z: NUL entre los tres campos, no dos puntos. Sin -z, hay espacio después de cada dos puntos.
| Pregunta | Comando | Qué imprime |
|---|---|---|
¿Este path tiene diff? | git check-attr diff -- path | path: diff: java o unspecified |
| ¿Varios attrs? | git check-attr crlf diff myAttr -- path | una línea por attr |
| ¿Todos los que aplican? | git check-attr --all -- path | solo asociados; sin unspecified |
| ¿Index, no disco? | git check-attr --cached text -- path | attrs del blob en el index |
| ¿En un commit? | git check-attr --source=HEAD text -- path | attrs del tree-ish |
El man: si no usas --stdin, --all ni --, el primer argumento es el attr y el resto son paths. Con --, lo de atrás son paths. Un agente que pone el path primero (git check-attr README text) trata README como nombre de atributo.
<info> (man):
unspecified— el attr no está definido para ese path.unset— definido como falso (-crlf,-text).set— definido como verdadero (myAttr,binary).- un valor —
eol=lf,diff=java,linguist-generated=true.
Verificado 2026-09-04 (Git 2.50.1 / Apple Git-155), repo con el .gitattributes del man (*.java diff=java -crlf myAttr, NoMyAttr.java !myAttr, README caveat=unspecified) más *.png binary, *.sh text eol=lf, pnpm-lock.yaml linguist-generated=true:
git check-attr diff MyClass.java→MyClass.java: diff: java, 0.git check-attr crlf diff myAttr -- MyClass.java→crlf: unset,diff: java,myAttr: set, 0.--all -- MyClass.java: las mismas tres; no listatextniidentsi no aplican. Tras añadir* text=autoen el working tree,--alltambién imprimetext: auto.git check-attr myAttr -- MyClass.java NoMyAttr.java→setyunspecified.!myAttrno imprimeunset: el man del ejemplo saleunspecified.git check-attr caveat README→README: caveat: unspecified. Escribircaveat=unspecifieden el archivo sigue siendo unspecified. El man lo marca como valor ambiguo.- Attr que no existe:
git check-attr foo README→foo: unspecified, 0. No es error. pic.png:binary: set,text: unset.--allañadediff: unsetymerge: unset(macrobinaryde gitattributes).run.sh:text: set,eol: lf.pnpm-lock.yaml:linguist-generated: true(valor, noset).- Path inexistente que matchea
*.java:no-such.javarecibediff: java. El archivo no tiene que existir. - Untracked
extra.txtcon* text=autoen el working tree:text: auto, 0. --cacheddespués de editar.gitattributessingit add: working tree dicetext: auto;--cachedy--source=HEADdicenunspecified.--source=deadbeef: not a valid tree-ish source, 128.- Sin args: No attribute specified, 129.
--allsin path: No file specified, 129. -zsin--stdinsí funciona (a diferencia de check-ignore):README\0text\0auto\0.

Lo que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
| ¿Este lockfile es generated? | git check-attr linguist-generated -- pnpm-lock.yaml | Abrir .gitattributes y “parece que sí” |
¿Este script es eol=lf? | git check-attr eol -- run.sh | dos2unix a ciegas |
| ¿El PNG es binary? | git check-attr binary -- pic.png | Reformatear bytes |
| ¿El index, no el disco sucio? | --cached --all -- path | Confiar en un .gitattributes unstaged |
¿En main publicado? | --source=origin/main --all -- path | Asumir que HEAD local es github.com |
Prohibido en autónomo:
- Dump de
.gitattributesal LLM. El man resuelve macros y precedencia. El archivo crudo no. --stdin/-z --stdinsobrefindogit ls-files. Eso es el dump. Pregunta un path, o un lote acotado que el agente ya tiene.- Tratar
unspecifiedcomo error. Default 0. El 129 es usage. El 128 es tree-ish inválido. - Tratar
caveat=unspecifieden el archivo como un valor. El man: no todos los valores son igual de unívocos; saleunspecified. - Confundir
!myAttrconunset. Verificado:NoMyAttr.javaimprimemyAttr: unspecified, nounset.-crlfsí esunset. - Usar
check-attrpara saber si un path está ignorado. Eso es check-ignore. Un untracked puede tenertext: autoy seguir fuera del index. - Escribir
linguist-generatedcreyendo que Git lo aplica en el clone. Git almacena el attr; GitHub Linguist lo lee al pintar el PR.check-attrsolo te dice el valor local. --allsobre la raíz del repo “por si acaso”. Pide el path del archivo que vas a tocar.
Receta (60 segundos)
Solo en un worktree propio:
git status -sb
git check-attr --all -- "$path"
git check-attr --cached --all -- "$path"
Si el ticket es “¿puedo correr prettier / dos2unix aquí?”: text, eol, binary. binary: set o text: unset → no toques el archivo como texto.
Si el ticket es “¿oculto el diff del lockfile?”: linguist-generated. Si sale unspecified, no inventes que GitHub lo va a colapsar.
Cero --stdin masivo. Cero reescritura de .gitattributes para “pasar” el check.

check-attr vs check-ignore vs el archivo
check-attr responde cómo se trata un path trackeable. check-ignore responde si el exclude lo cubre. gitignore es el archivo de exclude. gitattributes es el archivo de attrs: check-attr es la pregunta, no la receta de qué escribir.
ls-files lista el index. No resuelve eol=lf. Un agente que “lee el .gitattributes y actúa” se salta macros (binary ⇒ -diff -merge -text) y el --cached vs disco.
Checklist
- Worktree propio.
git status -sb. Un path por pregunta. - Attr concreto o
--all. Paths detrás de--. -
set/unset/ valor /unspecified.unspecifiedes 0. - Disco sucio:
--cachedo--source=<tree-ish>. - Cero
--stdinal LLM. Cero dump del archivo. - Ignore = check-ignore. Generated en GitHub = valor local, no Linguist remoto.
FAQ
¿--all me lista todo lo posible? No. El man: no incluye unspecified. Verificado: sin * text=auto, --all -- MyClass.java no imprime text. Pregunta el attr si lo necesitas.
¿El path tiene que existir? No. Verificado: no-such.java hereda *.java. check-attr no es lstat.
¿-z exige --stdin? En check-ignore, sí (128). Aquí no. Verificado: git check-attr -z text -- README sale 0 con NULs.
El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. check-attr no es check-ignore: resuelve attrs, no exclude.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git apply para coding agents: pega el parche, no crea el commit

git check-ref-format para coding agents: el nombre es válido, no que la rama exista

git name-rev para coding agents: SHA a nombre, no a describe
