Comando Git para mostrar qué archivos específicos son ignorados por .gitignore

646

Me estoy mojando los pies con Git y tengo el siguiente problema:

El árbol fuente de mi proyecto:

/
|
+--src/
+----refs/
+----...
|
+--vendor/
+----...

Tengo un código (actualmente MEF) en mi sucursal de proveedor que compilaré allí y luego moveré las referencias a /src/refsdonde es donde el proyecto los recoge.

Mi problema es que tengo mi .gitignoreconjunto para ignorar *.dlly *.pdb. Puedo hacer una git add -f bar.dllpara forzar la adición del archivo ignorado, lo cual está bien, el problema es que no puedo encontrar una lista de los archivos que se ignoran.

Quiero enumerar los archivos ignorados para asegurarme de no olvidar agregarlos.

He leído la página de manual git ls-filesy no puedo hacer que funcione. Me parece que git ls-files --exclude-standard -idebería hacer lo que quiero. ¿Qué me estoy perdiendo?

Andrew Burns
fuente
12
En estos días, no
usarías
77
Les suplico que verifiquen que la respuesta de Riad sea correcta, ya que es la única que admite que no hay una forma garantizada de hacerlo utilizando solo los comandos git (incluido el git cleantruco) como se demuestra aquí . Además, recomiendo contra el ejemplo "excluir de" en su resumen ya que de hecho no presta atención a ningún archivo .gitignore. Pregunto esto especialmente porque esta página es la principal respuesta de Google.
Alexander Bird
Punto rápido sobre "Resumen de lo que funciona": la página del manual "Git ls-files" explica que "-i" significa incluir archivos excluidos para la salida ls. Tuve el mismo malentendido, hasta que leí "lentamente". ;-)
será
2
Las respuestas deben ir en una publicación de respuesta y no en una edición de la pregunta.
Flimm
Tengo git config --global alias.ls ls-files --exclude-standard, y eso hace que la respuesta a esta pregunta git ls -i.
jthill

Respuestas:

662

Notas:


También interesante (mencionado en la respuesta de qwertymk ), también puede usar el comando, al menos en Unix ( no funciona en una sesión CMD de Windows )git check-ignore -v

git check-ignore *
git check-ignore -v *

El segundo muestra la regla real .gitignoreque hace que un archivo sea ignorado en su repositorio de git.
En Unix, usando " ¿Qué se expande a todos los archivos en el directorio actual de forma recursiva? " Y un bash4 +:

git check-ignore **/*

(o un find -execcomando)

Nota: https://stackoverflow.com/users/351947/Rafi B. sugiere en los comentarios para evitar el (arriesgado) globstar :

git check-ignore -v $(find . -type f -print)

Sin .git/embargo, asegúrese de excluir los archivos de la subcarpeta.


Respuesta original 42009)

git ls-files -i

debería funcionar, excepto que su código fuente indica:

if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);

exc_given ?

Resulta que necesita un parámetro más después de la -ilista para realmente enumerar cualquier cosa:

Tratar:

git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore

(pero eso solo enumeraría su objeto en caché (no ignorado), con un filtro, por lo que no es exactamente lo que desea)


Ejemplo:

$ cat .git/ignore
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
$ git ls-files --ignored \
    --exclude='Documentation/*.[0-9]' \
    --exclude-from=.git/ignore \
    --exclude-per-directory=.gitignore

En realidad, en mi archivo 'gitignore' (llamado 'excluir'), encuentro una línea de comando que podría ayudarlo:

F:\prog\git\test\.git\info>type exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

Entonces....

git ls-files --others --ignored --exclude-from=.git/info/exclude
git ls-files -o -i --exclude-from=.git/info/exclude

git ls-files --others --ignored --exclude-standard
git ls-files -o -i --exclude-standard

debería hacer el truco.

Como se menciona en la página de manual de ls-files , --otherses la parte importante para mostrarle archivos no almacenados en caché, no comprometidos y normalmente ignorados.

--exclude_standardno es solo un atajo, sino una forma de incluir todas las configuraciones estándar de "patrones ignorados".

exclude-standard
Añadir las exclusiones estándar git: .git/info/exclude, .gitignoreen cada directorio, y el user's global exclusion file.

VonC
fuente
@VocC, desde mi comprensión de estas pruebas , la respuesta que recomienda en la parte superior simplemente puede tener grandes fallas. Es por eso que normalmente recomendaría la respuesta de Riad en su lugar.
Alexander Bird
2
Desde el lanzamiento de Git v2.13.2: git status --ignoredparece que también muestra archivos sin seguimiento
Pau
1
wow, git check-ignore -v *funciona muy bien, ya que muestra dónde se aplicó la configuración. Gracias.
Hoang Tran
@MikeD Para que el * / funcione (o en realidad, solo puedes hacer **) necesitas que se establezca globstar shopt -s globstardespués de eso, debería funcionar.
Veda
Sin habilitar (arriesgado) globstar:git check-ignore -v $(find . -type f -print)
rafi
484

Hay una manera mucho más simple de hacerlo (git 1.7.6+):

git status --ignored

Ver ¿Hay alguna manera de decirle a git-status que ignore los efectos de los archivos .gitignore?

Penghe Geng
fuente
3
¿Qué versión de git estás usando? El mío (1.7.0.4) dice error: unknown option 'ignored'. Incluso agregar -scomo se sugiere en la publicación vinculada no funcionó.
Alexander Bird
3
Mi versión es 1.7.6. Otra versión 1.7.5.1 es la que requiere -s. Puede intentar git status -hver si --ignoredes compatible
Penghe Geng
1
Supongo que simplemente todavía no es compatible con 1.7.0.4. Mi otra computadora tiene 1.7.9 y la bandera ignorada está allí
Alexander Bird
44
Intenté todas las soluciones en esta página. Ésta es la mejor. Muestra archivos y directorios. Esta característica probablemente no estaba disponible cuando esta pregunta se hizo originalmente. (Por cierto, todas las soluciones no funcionará correctamente con una nueva marca "git init" hasta que haya al menos por etapas cambios.)
wisbucky
12
Esto es ciertamente mucho mejor que la respuesta aceptada. También es mucho más seguro que la git clean -ndXsolución, porque la rara situación en la que uno olvida por error las banderas tendrá un efecto irrevocable en el repositorio, ya que se eliminan los archivos no rastreados. Entonces es peligroso. Por el contrario, git status --ignoredsiempre es seguro, incluso cuando se escribe erróneamente y es natural recordarlo.
Ioannis Filippidis
400

Otra opción que es bastante limpia (sin juego de palabras):

git clean -ndX

Explicación:

$ git help clean

git-clean - Remove untracked files from the working tree
-n, --dry-run - Don't actually remove anything, just show what would be done.
-d - Remove untracked directories in addition to untracked files.
-X - Remove only files ignored by Git.

Nota: Esta solución no mostrará los archivos ignorados que ya se han eliminado.

ma11hew28
fuente
Nifty ... sin embargo, la razón por la que hice la pregunta original fue para poder asegurarme de que los archivos del proveedor (* .dll) que se suponía que estaban allí ... así que eliminarlos no sería el resultado deseado. SIN EMBARGO: es bueno saberlo, ya que he cambiado mi estrategia de ignorar * .dll a ignorar mi carpeta de salida de compilación (pero no las carpetas de mi proveedor). Esta sería una buena alternativa make cleany muy útil en un servidor de compilación.
Andrew Burns
2
Estoy usando git versión 1.7.0.4, y los dos comandos ('git ls-files -o -i --exclude-standard', 'git clean -dXn') no son equivalentes. El primero me muestra 4 archivos, y el segundo solo dos. (.gitignore ~, index.php ~, sql / create_users.sql ~, www / index.php ~) (Eliminaría .gitignore ~, Eliminaría index.php ~). ¿Estoy perdiendo algo aquí?
Cesar
@VonC, dulce! ¡Gracias! @ César, no estoy seguro. No estoy tan familiarizado git ls-files -o -i --exclude-standard. git clean -dXnsiempre ha sido lo que quería, pero no muestra los archivos ignorados que ya se han eliminado. git ls-files -o -i --exclude-standardpodría hacer eso. Entonces, eso podría ser lo que está causando la diferencia.
ma11hew28
3
Una pequeña cosa: puede ser una buena idea escribir la nprimera, menos posibilidades de eliminar accidentalmente de esa manera; git clean -ndX
Tobias Cohen
1
@TobiasCohen bien! Actualicé la respuesta con su sugerencia. Es más seguro. Aunque, si deja de lado el n, Git por defecto es fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean. Todavía es bastante seguro, ¡pero escribir el nprimero es aún más seguro! :)
ma11hew28
39

Si bien generalmente la solución es correcta, no funciona en todas las circunstancias. Supongamos un directorio de repositorio como este:

# ls **/*                                                                                                       
doc/index.html  README.txt  tmp/dir0/file0  tmp/file1  tmp/file2

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

y un .gitignore como este:

# cat .gitignore
doc
tmp/*

Esto ignora el docdirectorio y todos los archivos a continuación tmp. Git funciona como se esperaba, pero el comando dado para enumerar los archivos ignorados no lo hace. Echemos un vistazo a lo que git tiene que decir:

# git ls-files --others --ignored --exclude-standard                                                            
tmp/file1
tmp/file2

Observe que docfalta en la lista. Puedes conseguirlo con:

# git ls-files --others --ignored --exclude-standard --directory                                                
doc/

Observe la --directoryopción adicional .

Que yo sepa, no hay un solo comando para enumerar todos los archivos ignorados a la vez. Pero no sé por qué tmp/dir0no aparece en absoluto.

Riad
fuente
2
Esto me dio lo que quería, mientras que los otros no (para mi caso particular) ... ¡gracias! Es frustrante tener que ejecutar dos comandos, pero con un directorio ignorado, la opción --directory al menos me encuentra eso, y puedo canalizar eso en un comando find para encontrar los archivos. ¡Gracias!
lindes
Esto lo hace todo a la vez y expande los directorios:(git ls-files -oi --exclude-standard; git ls-files -oi --exclude-standard --directory) | perl -nle '$seen{$_}++||next;if(-d){system"find",$_,"-type","f"}else{print}'
Dee Newcum
17

Git ahora tiene esta funcionalidad incorporada

git check-ignore *

Por supuesto, puedes cambiar el globo a algo como **/*.dllen tu caso

Referencia de Git

qwertymk
fuente
77
git check-ignore **/*incluir archivos en subdirectorios
mzimmer
esto solo enumera los diccionarios de nivel superior.
Radon8472
13

Debería ser suficiente para usar

git ls-files --others -i --exclude-standard

ya que eso cubre todo lo cubierto por

git ls-files --others -i --exclude-from=.git/info/exclude

Por lo tanto, este último es redundante.


Puede hacer esto más fácil agregando un alias a su ~/.gitconfigarchivo:

git config --global alias.ignored "ls-files --others -i --exclude-standard"

Ahora puede escribir git ignoredpara ver la lista. Mucho más fácil de recordar y más rápido de escribir.

Si prefiere la visualización más sucinta de la solución de Jason Geng, puede agregar un alias para eso como este:

git config --global alias.ignored "status --ignored -s"

Sin embargo, la salida más detallada es más útil para solucionar problemas con sus archivos .gitignore, ya que enumera todos los archivos de selección de algodón que se ignoran. Normalmente, canalizaría los resultados greppara ver si un archivo que espera ignorar está allí, o si un archivo que no desea ignorar está allí.

git ignored | grep some-file-that-isnt-being-ignored-properly

Luego, cuando solo desea ver una pantalla corta, es bastante fácil de recordar y escribir

git status --ignored

( -sNormalmente se puede dejar).

iconoclasta
fuente
Esto nunca funcionó para mí, porque tienes que enumerar manualmente esos archivos. git status --ignoredfunciona en Debian sid pero puede ser muy nuevo ... pero aparentemente se agregó debido a la demanda popular ;-)
mirabilos
1
Por "funciona en Debian sid" ¿Supongo que quiere decir "funciona con la versión de Git instalada por defecto en Debian sid"? Realmente deberías evitar dejarte como rehén por las versiones de utilidades incluidas en tu distribución. Puede actualizarlos independientemente de la distribución en sí.
iconoclasta
12

Aquí le mostramos cómo imprimir la lista completa de archivos en el árbol de trabajo que coinciden con los patrones ubicados en cualquier lugar de las múltiples fuentes de gitignore de Git (si está usando GNU find):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose

Verificará todos los archivos en la rama actual del repositorio (a menos que los haya eliminado localmente).

E identifica las líneas de origen de gitignore particulares, también.

Git continúa rastreando los cambios en algunos archivos que coinciden con los patrones de gitignore, simplemente porque esos archivos ya se agregaron. Útilmente, el comando anterior también muestra esos archivos.

Los patrones negativos de gitignore también se corresponden. Sin embargo, estos son fácilmente distinguibles en la lista, porque comienzan con !.

Si está utilizando Windows, Git Bash incluye GNU find(como lo revela find --version).

Si la lista es larga (y la tiene rev), también puede mostrarlos por extensión (algo):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose \
| rev | sort | rev

Para más detalles, ver man find, man git-check-ignore, man rev, y man sort.

El punto de todo este enfoque es que Git (el software) está cambiando rápidamente y es altamente complejo. Por el contrario, los GNU findson extremadamente estables (al menos, en sus características utilizadas aquí). Por lo tanto, cualquiera que desee ser competitivo al mostrar su profundo conocimiento de Git responderá la pregunta de una manera diferente.

¿Cuál es la mejor respuesta? Esta respuesta minimiza deliberadamente su dependencia del conocimiento de Git, para lograr el objetivo de estabilidad y simplicidad a través de la modularidad (aislamiento de la información), y está diseñado para durar mucho tiempo.

MarkDBlackwell
fuente
¡Muchas gracias! Había estado luchando por descubrir por qué algunos de mis nuevos archivos fuente a veces faltaban en mis confirmaciones. Resulta que tenía un patrón: bin *, que pensé que coincidiría solo con los nombres de archivos / directorios que comienzan con bin, ¡pero en cambio coincide con cualquier cosa que incluya bin en la ruta completa de un archivo / directorio! Supongo que mi problema proviene de un malentendido de la semántica precisa de la coincidencia de patrones en .gitignore. ¡Tu guión de 2 líneas me ayudó a encontrar este error!
Nicolas Rouquette
1

(extendiendo las otras respuestas)

Tenga en cuenta que git check-ignoreusa el comprometido .gitignorey no el que está en su árbol de trabajo. Para jugar con él sin contaminar su historial de git, puede intentar editarlo libremente y luego comprometerse con a git commit --amend.

Este problema ocurre principalmente si necesita una solución alternativa del problema, que git no sigue directorios. Ingrese en .gitignore:

dirtokeep/**
!dirtokeep/.keep

.keepdebería ser un archivo de longitud cero dirtokeep.

El resultado será que todo lo que en dirtokeepserán ignorados, excepto dirtokeep/.keep , que dará como resultado que también el dirtokeepdirectorio será construido sobre clon / salida.

peterh - Restablece a Monica
fuente
0

Suponiendo que hay algunos directorios ignorados, ¿por qué no usar "git status node / logs /" que le dirá qué archivos se agregarán? En el directorio tengo un archivo de texto que no es parte de la salida de estado, por ejemplo:

En la sucursal maestra
Su sucursal está actualizada con 'origen / maestro'.
Archivos sin seguimiento:
(use "git add ..." para incluir en lo que se confirmará)

    node/logs/.gitignore 

.gitignore es:

*

! .gitignore

pikknz
fuente