Explicar qué regla de gitignore está ignorando mi archivo

310

¿Hay alguna manera de ver por qué git ignora algún archivo (es decir, qué regla de un .gitignorearchivo está haciendo que se ignore)?

Imagine que tengo esto (o un escenario mucho más complejo, con cientos de carpetas y decenas de .gitignorearchivos:

/
-.gitignore
-folder/
    -.gitignore
    -subfolder/
              -.gitignore
              -file.txt

Si ejecuto git add folder/subfolder/file.txtgit puede quejarme de que se ignore:

The following paths are ignored by one of your .gitignore files:
folder/subfolder/file.txt
Use -f if you really want to add them.

¿Hay alguna manera de saber cuál de todas las posibles .gitignoretiene una regla para ignorar este archivo y también mostrar la regla? Me gusta:

The following paths are ignored by your folder/.gitignore file (line 12: *.txt)
folder/subfolder/file.txt
Use -f if you really want to add them.

O solo:

$ git why-is-ignored folder/subfolder/file.txt
folder/.gitignore:12:*.txt
Carlos Campderrós
fuente
44
Nota: git check-ignorepronto (git1.8.5 / 1.9) tendrá una --no-indexopción. Vea mi respuesta a continuación
VonC
Nota: GIT_TRACE_EXCLUDE=1 git statuspronto habrá una forma adicional de depurar las .gitignorereglas. Vea mi respuesta editada a continuación
VonC
Publicación de blog relevante: danielcompton.net/2016/04/21/… .
krlmlr

Respuestas:

643
git check-ignore -v filename

Vea la página del manual para más detalles.

La respuesta original sigue:

Actualmente, git no proporciona nada como esto. Pero después de ver su pregunta, busqué en Google y descubrí que en 2009 esta característica fue solicitada y parcialmente implementada . Después de leer el hilo, me di cuenta de que no sería demasiado trabajo hacerlo correctamente, así que comencé a trabajar en un parche y espero terminarlo en el siguiente día o dos. Actualizaré esta respuesta cuando esté lista.

ACTUALIZACIÓN: Wow, eso fue mucho más difícil de lo que esperaba. Las entrañas del gitmanejo excluyente son bastante crípticas. De todos modos, aquí hay una serie casi completa de confirmaciones que se aplican a la masterrama ascendente de hoy . El conjunto de pruebas está completo al 99%, pero aún no he terminado de manejar la --stdinopción. Espero que lo logre este fin de semana y luego envíe mis parches a la lista de correo de git.

Mientras tanto, definitivamente agradecería las pruebas de cualquiera que pueda hacerlo: solo clone de mi gittenedor , revise la check-ignorerama y compílelo como de costumbre.

ACTUALIZACIÓN 2: ¡ Ya está hecho! La última versión está en github según lo anterior, y he enviado la serie de parches a la lista de correo de git para su revisión por pares. Veamos qué piensan ...

ACTUALIZACIÓN 3: Después de varios meses más de pirateo / revisiones de parches / discusiones / espera, estoy encantado de poder decir que esta característica ahora ha llegado a la mastersucursal de git y estará disponible en la próxima versión (1.8.2, se espera que sea el 8 Marzo de 2013). Aquí está la check-ignorepágina del manual . ¡Uf, eso fue mucho más trabajo de lo que esperaba!

ACTUALIZACIÓN 4: Si está interesado en la historia completa sobre cómo evolucionó esta respuesta y cómo se implementó la función, consulte el episodio # 32 del podcast GitMinutes .

Adam Spires
fuente
2
Estoy usando 1.8.2 y git check-ignoreno hago nada.
zakdances
3
@yourfriendzak Sin lugar a dudas, git check-ignoreestá presente y trabajando en 1.8.2. Si el comportamiento no es lo que espera, le sugiero que (re) lea la página del manual y, si aún no lo es, envíe un informe de error adecuado en la lista de correo de git. Solo decir que no hace nada no es muy útil. Espero que probablemente lo haya ejecutado en un archivo no ignorado y espere incorrectamente alguna salida (aunque probablemente agregaré soporte para --show-unmatchedel --verbosemodo de salida en el futuro).
Adam Spires
1
@AdamSpiers tienes razón. Debería haber especificado que cuando ejecuto el comando, no se imprime nada. Sin mensaje de error, sin mensaje de éxito, sin información. Solo aparece el siguiente mensaje en blanco. Entonces, ¿estoy en lo cierto al suponer que "sin salida" es un comportamiento esperado en ciertas circunstancias?
zakdances
1
@AdamSpiers muchas gracias por esto! ¡Después de 3 días de investigación, me ha ayudado a localizar la causa de una compilación defectuosa debido a un archivo globalmente ignorado en .gitignore_global! ¡Ni siquiera sabía que era una cosa!
BenBtg
3
No todos los días se ve que un desarrollador de Stack Overflow realice tantos cambios para implementar una función de desarrollador. Guau y respeto.
user3613932
18

Actualización git 2.8 (marzo de 2016):

GIT_TRACE_EXCLUDE=1 git status

Consulte " Una forma de validar el .gitignorearchivo "

Eso es complementario a lo que se git check-ignore -vdescribe a continuación.


Respuesta original: septiembre de 2013 (git 1.8.2, luego 1.8.5+):

git check-ignoremejora nuevamente en git 1.8.5 / 1.9 (cuarto trimestre de 2013) :

" git check-ignore" sigue la misma regla que " git add" y " git status" en que el mecanismo de ignorar / excluir no tiene efecto en las rutas que ya están rastreadas.
Con la --no-indexopción " ", se puede utilizar para diagnosticar qué rutas que deberían haberse ignorado se han agregado por error al índice .

Ver commit 8231fa6 de https://github.com/flashydave :

check-ignoreactualmente muestra cómo las .gitignorereglas tratarían las rutas no rastreadas. Las rutas rastreadas no generan resultados útiles.
Esto evita la depuración de por qué una ruta se rastreó inesperadamente a menos que esa ruta se elimine primero del índice con git rm --cached <path>.

La opción --no-indexle dice al comando que omita la verificación de la ruta que está en el índice y, por lo tanto, también permite verificar las rutas rastreadas.

Mientras que este comportamiento se desvía de las características de git addy git statuses poco probable que cause cualquier confusión del usuario su caso de uso.

Las secuencias de comandos de prueba se aumentan para verificar esta opción frente a los ignorados estándar para garantizar un comportamiento correcto.


--no-index::

No mire en el índice cuando realice los controles.
Esto se puede usar:

  • para depurar por qué una ruta se rastreó, por ejemplo, git add .y no fue ignorada por las reglas como lo esperaba el usuario o
  • al desarrollar patrones que incluyen la negación para que coincida con una ruta previamente agregada git add -f.
VonC
fuente
4

No puedo encontrar nada en la página de manual, pero aquí hay un script rápido y sucio que verificará su archivo en cada directorio principal para ver si se puede agregar git. Ejecútelo en el directorio que contiene el archivo del problema como:

test-add.sh STOP_DIR FILENAME

donde STOP_DIRes el directorio de nivel superior del proyecto Git y FILENAMEes el nombre del archivo del problema (sin una ruta). Crea un archivo vacío del mismo nombre en cada nivel de la jerarquía (si no existe) e intenta git add -nver si se puede agregar (se limpia después de sí mismo). Produce algo como:

FAILED:    /dir/1/2/3
SUCCEEDED: /dir/1/2

La secuencia de comandos:

#!/usr/bin/env bash
TOP=$1
FILE=$2
DIR=`pwd`
while : ; do
  TMPFILE=1
  F=$DIR/$FILE
  if [ ! -f $F ]; then
    touch $F
    TMPFILE=0
  fi
  git add -n $F >/dev/null 2>&1
  if [ $? = 0 ]; then
    echo "SUCCEEDED: $DIR"
  else
    echo "FAILED:    $DIR"
  fi
  if [ $TMPFILE = 0 ]; then
    rm $F
  fi
  DIR=${DIR%/*}
  if [ "$DIR" \< "$TOP" ]; then
    break
  fi
done 
edoloughlin
fuente
1

Para agregar a la respuesta principal del uso git check-ignore -v filename(gracias, por cierto), descubrí que mi archivo .gitignore estaba bloqueando todo porque había una nueva línea después de un comodín, así que tuve:

* .sublime-project

como ejemplo. Acabo de quitar la nueva línea, y listo! Fue arreglado.

rekordboy
fuente