Polecenie Git, aby pokazać, które konkretne pliki są ignorowane przez .gitignore

645

Mam mokre stopy z Git i mam następujący problem:

Drzewo źródeł mojego projektu:

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

Mam kod (obecnie MEF) w mojej gałęzi dostawcy, którą tam skompiluję, a następnie przeniosę referencje, do /src/refsktórych projekt je pobiera.

Moim problemem jest to, że mam .gitignorezestaw do zignorowania *.dlli *.pdb. Mogę zrobić, git add -f bar.dllaby wymusić dodanie zignorowanego pliku, co jest w porządku, problem polega na tym, że nie mogę wymyślić listy istniejących plików, które są ignorowane.

Chcę wyświetlić listę ignorowanych plików, aby upewnić się, że nie zapomnę ich dodać.

Przeczytałem stronę podręcznika użytkownika git ls-filesi nie mogę jej uruchomić . Wydaje mi się, że git ls-files --exclude-standard -ipowinienem robić to, co chcę. czego mi brakuje?

Andrew Burns
źródło
12
W dzisiejszych czasach nie używałbyś git-ls-files, a raczej „git ls-files”
wojo
7
Błagam cię, byś sprawdził poprawność odpowiedzi Riyada, ponieważ jest to jedyna, która przyznaje, że nie ma gwarantowanego sposobu, aby to zrobić za pomocą tylko poleceń git (w tym git cleansztuczki), jak pokazano tutaj . Ponadto odradzam przykład „wykluczenia z” w podsumowaniu, ponieważ w rzeczywistości nie zwraca on uwagi na żadne pliki .gitignore. Pytam o to szczególnie, ponieważ ta strona jest najlepszą odpowiedzią Google.
Alexander Bird
Szybki punkt na temat „Podsumowanie tego, co działa”: strona podręcznika „Git ls-files” wyjaśnia, że ​​„-i” oznacza dołącz wykluczone pliki dla wyjścia ls. Miałem to samo nieporozumienie, dopóki nie przeczytałem „powoli”. ;-)
będzie
2
Odpowiedzi powinny znajdować się w poście z odpowiedzią, a nie w edycji pytania.
Flimm
Mam git config --global alias.ls ls-files --exclude-standardi to stanowi odpowiedź na to pytanie git ls -i.
jthill

Odpowiedzi:

662

Uwagi:


Również ciekawe (wymienione w qwertymk „s odpowiedź ), można również użyć git check-ignore -vpolecenia, przynajmniej na Unix ( nie działa w CMD systemu Windows sesji)

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

Drugi wyświetla rzeczywistą regułę, .gitignorektóra powoduje, że plik jest ignorowany w twoim repozytorium git.
W systemie Unix za pomocą „ Co rekurencyjnie rozszerza się na wszystkie pliki w bieżącym katalogu? ” I bash4 +:

git check-ignore **/*

(lub a find -exec polecenie)

Uwaga: https://stackoverflow.com/users/351947/Rafi B. sugeruje w komentarzach, aby uniknąć (ryzykownej) globstar :

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

Pamiętaj jednak, aby wykluczyć pliki z .git/podfolderu.


Oryginalna odpowiedź 42009)

git ls-files -i

powinien działać, z wyjątkiem tego , że kod źródłowy wskazuje:

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

exc_given ?

Okazuje się, że potrzebuje jeszcze jednego parametru po -i aby cokolwiek wyświetlić:

Próbować:

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

(ale wyświetliłoby to tylko twój buforowany (niezignorowany) obiekt z filtrem, więc nie jest to dokładnie to, czego chcesz)


Przykład:

$ 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

Właściwie w moim pliku „gitignore” (zwanym „exclude”) znajduję wiersz poleceń, który może ci pomóc:

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]
# *~

Więc....

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

powinien załatwić sprawę.

Jak wspomniano na stronie podręcznika ls-files , --othersjest to ważna część, aby pokazać ci pliki niebuforowane, niezaangażowane, normalnie ignorowane.

--exclude_standardto nie tylko skrót, ale sposób na dołączenie wszystkich standardowych ustawień „ignorowanych wzorców”.

exclude-standard
Dodaj standardowe wyłączenia git: .git/info/exclude, .gitignorew każdym katalogu, a user's global exclusion file.

VonC
źródło
@ VocC, z mojego zrozumienia tych testów , odpowiedź, którą polecasz u góry, może mieć po prostu duże wady. Dlatego normalnie poleciłbym zamiast tego odpowiedź Riyada .
Alexander Bird
2
Od wydania Git v2.13.2: git status --ignoredwygląda na to, że wyświetla także nieśledzone pliki: github.com/git/git/blob/master/Documentation/RelNotes/...
Pau
1
wow, git check-ignore -v *działa świetnie, ponieważ pokazuje, gdzie zastosowano konfigurację. Dziękuję Ci.
Hoang Tran
@MikeD Aby * / działał (a właściwie możesz po prostu zrobić **), musisz ustawić globstar shopt -s globstar, a potem powinien on działać.
Veda
Bez aktywacji (ryzykownej) globstar:git check-ignore -v $(find . -type f -print)
rafi
481

Jest na to znacznie prostszy sposób (git 1.7.6+):

git status --ignored

Zobacz Czy istnieje sposób, aby powiedzieć git-status, aby ignorował efekty plików .gitignore?

Penghe Geng
źródło
3
Jakiej wersji git używasz? Mój (1.7.0.4) mówi error: unknown option 'ignored'. Nawet dodanie -szgodnie z sugestią w łączonym poście nie działało.
Alexander Bird,
3
Moja wersja to 1.7.6. Inna wersja 1.7.5.1 jest tą, która wymaga -s. Możesz spróbować git status -hsprawdzić, czy --ignoredjest obsługiwany
Penghe Geng
1
Myślę, że po prostu nie jest jeszcze obsługiwany w wersji 1.7.0.4. Mój drugi komputer ma wersję 1.7.9 i jest tam
Alexander Bird
4
Próbowałem każdego rozwiązania na tej stronie. To jest najlepsze. Pokazuje zarówno pliki, jak i katalogi. Ta funkcja prawdopodobnie nie była dostępna, kiedy pierwotnie zadano to pytanie. (Nawiasem mówiąc, wszystkie rozwiązania nie będą działały poprawnie z nowym „git init”, dopóki przynajmniej nie wprowadzisz zmian.)
Wisbucky
12
Jest to z pewnością znacznie lepsze niż zaakceptowana odpowiedź. Jest to również znacznie bezpieczniejsze niż git clean -ndXrozwiązanie, ponieważ rzadka sytuacja, gdy ktoś omyłkowo zapomina flagi, będzie miał nieodwracalny wpływ na repozytorium, ponieważ nieśledzone pliki zostaną usunięte. To jest niebezpieczne. Wręcz przeciwnie, git status --ignoredjest zawsze bezpieczny, nawet gdy jest błędnie wpisany i naturalne jest, aby pamiętać.
Ioannis Filippidis,
400

Inna opcja, która jest dość czysta (nie ma sensu).

git clean -ndX

Wyjaśnienie:

$ 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.

Uwaga: to rozwiązanie nie wyświetla ignorowanych plików, które zostały już usunięte.

ma11hew28
źródło
Fajne ... jednak powodem, dla którego zadałem oryginalne pytanie, było upewnienie się, że pliki dostawcy (* .dll), które powinny tam być, były ... więc usunięcie ich nie byłoby pożądanym rezultatem. JEDNAK: warto o tym wiedzieć, ponieważ zmieniłem strategię z ignorowania * .dll na ignorowanie mojego folderu wyjściowego kompilacji (ale nie folderów mojego dostawcy). Byłaby to dobra alternatywa make cleani bardzo pomocna na serwerze kompilacji.
Andrew Burns
2
Używam git w wersji 1.7.0.4, a dwa polecenia („git ls-files -o -i --exclude-standard”, „git clean -dXn”) nie są równoważne. Pierwszy pokazuje mi 4 pliki, a drugi tylko dwa. (.gitignore ~, index.php ~, sql / create_users.sql ~, www / index.php ~) (Usunąłby .gitignore ~, usunąłby index.php ~). Czy coś tu brakuje?
Cesar
@VonC, kochanie! Dzięki! @Cesar, nie jestem pewien. Nie znam się tak dobrze git ls-files -o -i --exclude-standard. git clean -dXnzawsze był tym, czego chciałem, ale nie pokazuje ignorowanych plików, które zostały już usunięte. git ls-files -o -i --exclude-standardmoże to zrobić. Więc to może być różnica.
ma11hew28,
3
Jedna drobna rzecz - dobrym pomysłem może być wpisanie npierwszej, mniejszej szansy na przypadkowe usunięcie w ten sposób; git clean -ndX
Tobias Cohen
1
@TobiasCohen nice! Zaktualizowałem odpowiedź z twoją sugestią. To jest bezpieczniejsze. Chociaż, jeśli npominiesz, Git domyślnie przyjmuje wartość fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean. Wciąż dość bezpieczne, ale wpisanie npierwszego jest jeszcze bezpieczniejsze! :)
ma11hew28,
39

Chociaż ogólnie poprawne rozwiązanie nie działa we wszystkich okolicznościach. Załóżmy katalog repo w ten sposób:

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

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

i .gitignore, takie jak:

# cat .gitignore
doc
tmp/*

To ignoruje dockatalog i wszystkie pliki poniżejtmp . Git działa zgodnie z oczekiwaniami, ale podane polecenie do wyświetlenia listy zignorowanych plików nie działa. Rzućmy okiem na to, co mówi git:

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

Zauważ, że docbrakuje na liście. Możesz to uzyskać za pomocą:

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

Zwróć uwagę na dodatkową --directoryopcję.

Z mojej wiedzy nie ma jednego polecenia, aby wyświetlić listę wszystkich ignorowanych plików jednocześnie. Ale nie wiem, dlaczego w tmp/dir0ogóle się nie pojawia.

riyad
źródło
2
To dało mi to, czego chciałem, podczas gdy inni nie (w moim konkretnym przypadku) ... dzięki! To frustrujące, że trzeba uruchamiać dwie komendy, ale przy zignorowanym katalogu opcja --directory przynajmniej mnie to odnajduje i mogę połączyć to z poleceniem find, aby znaleźć pliki. Dzięki!
Lindes
To wszystko naraz, i rozszerza katalogi:(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 ma teraz tę funkcję wbudowaną

git check-ignore *

Oczywiście możesz zmienić glob na coś takiego jak **/*.dllw twoim przypadku

Git Reference

qwertymk
źródło
7
git check-ignore **/*dołączyć pliki do podkatalogów
mzimmer
zawiera tylko listę artykułów najwyższego poziomu.
Radon8472,
13

Powinien wystarczyć do użycia

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

ponieważ obejmuje to wszystko objęte

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

dlatego ten drugi jest zbędny.


Możesz to ułatwić, dodając alias do swojego ~/.gitconfigpliku:

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

Teraz możesz po prostu wpisać, git ignoredaby zobaczyć listę. O wiele łatwiejsze do zapamiętania i szybsze pisanie.

Jeśli wolisz bardziej zwięzłe wyświetlanie rozwiązania Jasona Genga, możesz dodać dla tego alias:

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

Jednak bardziej szczegółowe dane wyjściowe są bardziej przydatne w rozwiązywaniu problemów z plikami .gitignore, ponieważ zawiera listę każdego pojedynczego pliku, który jest ignorowany. Zwykle grepprzesyłasz wyniki, aby sprawdzić, czy znajduje się tam plik, który chcesz zignorować, czy też plik, którego nie chcesz ignorować.

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

Następnie, gdy chcesz tylko zobaczyć krótki ekran, łatwo jest zapamiętać i wpisać

git status --ignored

( -sZwykle można to pominąć.)

ikonoklasta
źródło
Dla mnie to nigdy nie działało, ponieważ musisz ręcznie wyświetlić te pliki. git status --ignoreddziała na sid Debianie, ale może jest bardzo nowy… ale najwyraźniej został dodany z powodu popularnego popytu ;-)
mirabilos 18.09.2013
1
Przez „działa na Debianie sid” Zakładam, że masz na myśli „działa z wersją Gita zainstalowaną domyślnie na Debianie sid”? Naprawdę powinieneś unikać dawania zakładników wersjom narzędzi zawartych w twojej dystrybucji. Możesz je ulepszyć niezależnie od samej dystrybucji.
iconoclast
12

Oto jak wydrukować pełną listę plików w drzewie roboczym, które pasują do wzorców znajdujących się w dowolnym miejscu w wielu źródłach gitignore Gita (jeśli używasz GNU find):

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

Sprawdza wszystkie pliki w bieżącej gałęzi repozytorium (chyba że zostały usunięte lokalnie).

I identyfikuje również konkretne linie źródłowe gitignore.

Git kontynuuje śledzenie zmian w niektórych plikach, które pasują do wzorców gitignore, po prostu dlatego, że te pliki zostały już dodane. Przydatnie powyższe polecenie wyświetla również te pliki.

Dopasowywane są również negatywne wzory gitignore. Można je jednak łatwo odróżnić na liście, ponieważ zaczynają się od !.

Jeśli używasz systemu Windows, Git Bash zawiera GNU find(jak ujawnił find --version).

Jeśli lista jest długa (i masz rev), możesz też wyświetlić je według rozszerzenia (nieco):

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

Aby uzyskać więcej informacji, zobacz man find, man git-check-ignore, man rev, i man sort.

Chodzi o to, że Git (oprogramowanie) zmienia się szybko i jest bardzo złożone. Z kolei GNU findjest wyjątkowo stabilny (przynajmniej w zastosowanych tutaj funkcjach). Zatem każdy, kto chce być konkurencyjny, wykazując się dogłębną znajomością Git, odpowie na pytanie w inny sposób.

Jaka jest najlepsza odpowiedź? Ta odpowiedź celowo minimalizuje poleganie na wiedzy Git, zmierzając do osiągnięcia celu stabilności i prostoty poprzez modułowość (izolację informacji) i ma na celu trwać bardzo długo .

MarkDBlackwell
źródło
Wielkie dzięki! Z trudem próbowałem dowiedzieć się, dlaczego niektóre z moich nowych plików źródłowych czasami brakuje w moich zatwierdzeniach. Okazuje się, że miałem wzorzec: bin *, który moim zdaniem pasowałby tylko do nazw plików / katalogów zaczynających się od bin, ale zamiast tego pasuje do wszystkiego, co zawiera bin w pełnej ścieżce do pliku / katalogu! Chyba mój problem wynika z niezrozumienia precyzyjnej semantyki dopasowywania wzorców w .gitignore. Twój 2-liniowy skrypt pomógł mi znaleźć ten błąd!
Nicolas Rouquette,
1

(rozszerzenie innych odpowiedzi)

Uwaga, git check-ignoreużywa zatwierdzonego, .gitignorea nie tego z twojego drzewa roboczego! Aby grać z nim bez zanieczyszczania historii git, możesz swobodnie spróbować go edytować, a następnie zatwierdzić za pomocągit commit --amend .

Ten problem występuje głównie, jeśli potrzebujesz obejścia problemu, że git nie podąża za katalogami. Wpisz w .gitignore:

dirtokeep/**
!dirtokeep/.keep

.keeppowinien być plikiem o zerowej długości dirtokeep.

Rezultat będzie taki, że wszystko w dirtokeepzostanie zignorowane, z wyjątkiem dirtokeep/.keep , co spowoduje, że również dirtokeepkatalog zostanie skonstruowany podczas klonowania / pobierania.

peterh - Przywróć Monikę
źródło
0

Zakładając, że istnieje kilka katalogów ignorowania, dlaczego nie użyć „git status node / logs /”, który powie ci, jakie pliki mają zostać dodane? W katalogu mam plik tekstowy, który nie jest częścią wyjścia statusu, np .:

On master master
Twój oddział jest aktualny z „origin / master”.
Nieśledzone pliki:
(użyj „git add ...”, aby uwzględnić w tym, co zostanie zatwierdzone )

    node/logs/.gitignore 

.gitignore to:

*

! .gitignore

pikknz
źródło