Wyjaśnij, która reguła gitignore ignoruje mój plik

310

Czy jest jakiś sposób, aby dowiedzieć się, dlaczego git ignoruje jakiś plik (tj. Która reguła w .gitignorepliku powoduje ignorowanie pliku)?

Wyobraź sobie, że mam ten (lub znacznie bardziej złożony scenariusz, z setkami folderów i dziesiątkami .gitignoreplików:

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

Jeśli uruchomię git add folder/subfolder/file.txtgit, może narzekać, że jest ignorowany:

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

Czy jest jakiś sposób, aby dowiedzieć się, który ze wszystkich możliwych .gitignorema regułę, aby zignorować ten plik, a także pokazać regułę? Lubić:

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.

Lub tylko:

$ git why-is-ignored folder/subfolder/file.txt
folder/.gitignore:12:*.txt
Carlos Campderrós
źródło
4
Uwaga: git check-ignorewkrótce (git1.8.5 / 1.9) będzie miał --no-indexopcję. Zobacz moją odpowiedź poniżej
VonC
Uwaga: GIT_TRACE_EXCLUDE=1 git statuswkrótce będzie dodatkowym sposobem debugowania .gitignorereguł. Zobacz moją zredagowaną odpowiedź poniżej
VonC
Odpowiedni post na blogu: danielcompton.net/2016/04/21/… .
krlmlr

Odpowiedzi:

643
git check-ignore -v filename

Zobacz stronę podręcznika, aby uzyskać więcej informacji.

Oryginalna odpowiedź brzmi:

git obecnie nie zapewnia czegoś takiego. Ale po zobaczeniu twojego pytania zrobiłem trochę googlingu i odkryłem, że w 2009 roku ta funkcja była wymagana i częściowo zaimplementowana . Po przeczytaniu wątku zdałem sobie sprawę, że nie będzie to zbyt wiele pracy, aby zrobić to poprawnie, więc zacząłem pracę nad łatką i mam nadzieję, że skończę ją następnego lub dwóch dni. Zaktualizuję tę odpowiedź, gdy będzie gotowa.

AKTUALIZACJA: Wow, to było o wiele trudniejsze niż się spodziewałem. Wewnętrzne gitwykluczenia obsługi są dość tajemnicze. W każdym razie oto prawie skończony szereg zatwierdzeń , które mają zastosowanie do dzisiejszego upstream mastergałęzi. Pakiet testowy jest w 99% kompletny, ale nie skończyłem jeszcze obsługi tej --stdinopcji. Mam nadzieję, że poradzę sobie w ten weekend, a następnie prześlę łatki na listę mailingową git.

Tymczasem zdecydowanie chętnie przeprowadzę testy od każdego, kto może to zrobić - po prostu klonuj mojego gitwidelca , sprawdź check-ignoregałąź i skompiluj ją jak zwykle.

AKTUALIZACJA 2: Gotowe! Najnowsza wersja znajduje się na github, jak wyżej, i przesłałem serię poprawek na listę mailingową git do przeglądu. Zobaczmy, co myślą ...

AKTUALIZACJA 3: Po kilku miesiącach hakowania / recenzji łatek / dyskusji / oczekiwania, jestem zachwycony, że mogę powiedzieć, że ta funkcja dotarła teraz do masteroddziału git i będzie dostępna w następnej wersji (1.8.2, spodziewana ósma Marzec 2013). Oto check-ignorestrona podręcznika . Uff, to było o wiele więcej pracy, niż się spodziewałem!

AKTUALIZACJA 4: Jeśli jesteś zainteresowany pełną historią o tym, jak ta odpowiedź ewoluowała i funkcja została wprowadzona w życie, sprawdź odcinek # 32 podcastu GitMinutes .

Adam Spiers
źródło
2
Używam 1.8.2 i git check-ignorenic nie robię.
zakdances
3
@twoja friendzak Bez cienia wątpliwości git check-ignorejest obecna i działa w 1.8.2. Jeśli zachowanie nie jest zgodne z oczekiwaniami, sugeruję (ponownie) przeczytać stronę podręcznika, a jeśli nadal tak nie jest, prześlij odpowiedni raport o błędach na liście mailingowej git. Samo powiedzenie, że nic nie robi, nie jest zbyt pomocne. Spodziewam się, masz prawdopodobnie uruchomić go na plik non-ignorowane i są nieprawidłowo oczekując jakieś wyjście (choć zapewne dodać wsparcie --show-unmatcheddla --verbosetrybu wyjściowego w przyszłości).
Adam Spires,
1
@AdamSpiers masz rację. Powinienem był określić, że kiedy wykonuję polecenie, nic nie jest drukowane. Brak komunikatu o błędzie, brak komunikatu o powodzeniu, brak informacji. Pojawi się następny pusty monit. Czy więc mam rację, zakładając, że „brak danych wyjściowych” jest oczekiwanym zachowaniem w pewnych okolicznościach?
zakdances
1
@AdamSpiers bardzo za to dziękuję! Po 3 dniach śledztwa pomogłeś mi właśnie wyśledzić przyczynę zepsucia kompilacji z powodu globalnie ignorowanego pliku w .gitignore_global! Nawet nie wiedziałem, że to była rzecz!
BenBtg
3
Nie codziennie zdarza się, że programista przepełnienia stosu wprowadza tak wiele zmian w celu wdrożenia funkcji programistycznej. Wow i szacunek.
user3613932,
18

Zaktualizuj git 2.8 (marzec 2016):

GIT_TRACE_EXCLUDE=1 git status

Zobacz „ Sposób sprawdzania poprawności .gitignorepliku

Jest to komplementarne do git check-ignore -vopisanego poniżej.


Oryginalna odpowiedź: wrzesień 2013 (git 1.8.2, a następnie 1.8.5+):

git check-ignorepoprawia ponownie w git 1.8.5 / 1.9 (IV kwartał 2013) :

git check-ignore” podlega tej samej zasadzie co „ git add” i „ git status”, ponieważ mechanizm ignorowania / wykluczania nie działa na ścieżki, które są już śledzone.
Za pomocą --no-indexopcji „ ” można diagnozować, które ścieżki, które powinny zostać zignorowane, zostały omyłkowo dodane do indeksu .

Zobacz commit 8231fa6 z https://github.com/flashydave :

check-ignoreobecnie pokazuje, w jaki sposób .gitignorereguły będą traktować nieśledzone ścieżki. Śledzone ścieżki nie generują użytecznych wyników.
Zapobiega to debugowaniu przyczyny nieoczekiwanego śledzenia ścieżki, chyba że ścieżka ta zostanie najpierw usunięta z indeksu za pomocągit rm --cached <path> .

Opcja --no-index każe komendzie ominąć sprawdzanie ścieżki znajdującej się w indeksie, a zatem umożliwia sprawdzenie ścieżek śledzonych.

Chociaż zachowanie to odbiega od cech charakterystycznych, git adda git statusjego przypadek użycia raczej nie spowoduje zamieszania wśród użytkowników.

Skrypty testowe są rozszerzane, aby porównać tę opcję ze standardowymi ignorowaniami, aby zapewnić prawidłowe zachowanie.


--no-index::

Nie sprawdzaj indeksu podczas przeprowadzania kontroli.
Można to wykorzystać:

  • do debugowania, dlaczego ścieżka została śledzona przez np. git add .i nie została zignorowana przez reguły zgodnie z oczekiwaniami użytkownika lub
  • podczas opracowywania wzorców, w tym negacji w celu dopasowania do ścieżki poprzednio dodanej git add -f.
VonC
źródło
4

Nie mogę znaleźć niczego na stronie podręcznika, ale oto szybki i brudny skrypt, który sprawdzi twój plik w każdym katalogu nadrzędnym, aby sprawdzić, czy można go dodać. Uruchom go w katalogu zawierającym plik problemu jako:

test-add.sh STOP_DIR FILENAME

gdzie STOP_DIRjest katalogiem najwyższego poziomu projektu Git i FILENAMEnazwą pliku problemu (bez ścieżki). Tworzy pusty plik o tej samej nazwie na każdym poziomie hierarchii (jeśli nie istnieje) i próbuje git add -nsprawdzić, czy można go dodać (czyści po sobie). Wyprowadza coś takiego:

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

Scenariusz:

#!/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
źródło
1

Aby dodać do głównej odpowiedzi dotyczącej używania git check-ignore -v filename(dzięki BTW), stwierdziłem, że mój plik .gitignore blokuje wszystko, ponieważ po znaku wieloznacznym pojawiła się nowa linia, więc miałem:

* .sublime-project

jako przykład. Właśnie usunąłem nową linię i voila! Zostało to naprawione.

rekordboy
źródło