TL;DR: jeśli .gitignore nie działa, plik niemal na pewno jest już śledzony. Git ignoruje pliki, których nigdy nie widział — plik w indeksie jest odporny na każdą regułę, jaką napiszesz. Prawdę powie git check-ignore -v <path>: milczenie oznacza, że ścieżka jest śledzona i żadna reguła nie obowiązuje. Naprawiasz przez git rm --cached <path>, commit, i od tego commita reguła ignorowania zaczyna działać. Kolejność reguł, pułapki negacji i czerwone śledzie z VS Code tłumaczą pozostałe przypadki.
Dlaczego .gitignore nie działa?
Jeden mechanizm pokrywa większość przypadków: plik został zacommitowany, zanim pojawiła się reguła. .gitignore nie jest filtrem ukrywającym pliki przed gitem — to reguła mówiąca, co git add ma podbrać ze stanu nieśledzonego. Gdy plik jest już w indeksie, git śledzi zmiany jego treści wiecznie, dopóki nie wycofasz go wprost. Edycja .gitignore po fakcie nie zmienia nic dla plików śledzonych — dlatego klasyczna sekwencja „commit .env, panika, dodaj .env do .gitignore, commit jeszcze raz” wysyła sekret przy każdym pushu.
To kłuje każdego, bo git jest niemal wszędobulski — badanie Stack Overflow 2022 wykazało, że gita używa ponad 93% zawodowych programistów (survey.stackoverflow.co) — a każdy z tych programistów prędzej czy później pisze regułę dla pliku, który zacommitował tydzień temu.
Reszta posta pokrywa przypadki mniejszościowe: błędy kolejności reguł, pułapki negacji, ciekawostki folderowe i pytanie o IDE. Ale najpierw odpal kontrolę z następnej sekcji — w ponad dziewięciu na dziesięć przypadków to ona kończy śledztwo.
Jak sprawdzić, która reguła gitignore pasuje do pliku?
git check-ignore to narzędzie diagnostyczne, a jego milczenie jest diagnozą:
# Wypisuje pasującą regułę + plik + numer linii, gdy reguła obowiązuje
git check-ignore -v debug.log
# .gitignore:3:*.log debug.log
# Nie wypisuje NIC, gdy żadna reguła nie pasuje — plik jest śledzony (albo reguły nie ma)
git check-ignore -v src/.env
# (milczenie = .gitignore nie ignoruje tej ścieżki, cokolwiek byś nie napisał)
# Kody wyjścia: 0 = ignorowany, 1 = nieignorowany — do użycia w skryptach
git check-ignore -q debug.log && echo "ignored" || echo "tracked or unruly" Czytanie wyjścia -v: źródło reguły (.gitignore, .git/info/exclude albo twój globalny plik ignorowania), potem numer-linii:wzorzec, potem ścieżka. Jeśli późniejsza reguła cię zaskoczy, pamiętaj o priorytetach: wygrywa ostatnia pasująca reguła, więc !important.log po *.log przywraca ten jeden plik.
Dlaczego gitignore nie działa dla plików już zacommitowanych?
Wycofaj plik ze śledzenia, zostaw go na dysku, zacommituj usunięcie:
# Wycofanie jednego pliku (kopia lokalna przeżywa — --cached dotyka tylko indeksu)
git rm --cached .env
git commit -m "stop tracking .env"
# Weryfikacja, że reguła ignorowania już obowiązuje
git check-ignore -v .env Od tego commita .gitignore włada ścieżką: zmiany w pliku nie pokazują się już w git status, a git add . nie podbierze go ponownie. Plik zostaje jednak w historii — jeśli to był sekret, samo usunięcie go z najnowszego commita to za mało. Rotacja poświadczenia to jedyne realne rozwiązanie; przepisywanie historii to kosmetyka (a cofanie ostatniego commita pomaga tylko dopóki zły commit jest jeszcze na czubku).
Dla repo pełnego wcześniej zacommitowanych śmieci — wyników builda, odpadków edytora, node_modules, które wkradło się na starcie — hurtowe wycofanie to dwie linijki:
git rm -r --cached .
git add .
git commit -m "apply .gitignore to tracked files" To przebudowuje indeks według obecnych reguł: ignorowane ścieżki wypadają, cała reszta wraca bez zmian. Diff wygląda dramatycznie (tysiące usunięć), ale z dysku nie znika nic. Jeśli celem jest faktyczne usunięcie tych plików, a nie tylko wycofanie ich ze śledzenia, to teren git clean -fdx — patrz git remove untracked files, safely.
Git ignoruje pliki, których nigdy nie widział. Plik już siedzący w indeksie jest odporny na
.gitignore— żadna reguła tego nie odwidzi.
Dlaczego gitignore nie działa dla folderu?
Trzy pułapki właściwe folderom:
1. Ukośnik na końcu mówi o intencji, nie o dopasowaniu. build i build/ oba łapią katalog, ale build/ dokumentuje, że masz na myśli wyłącznie katalog — plik o nazwie build by przeżył. Symetria jednak się sypie przy ponownym włączaniu (następna pułapka).
2. Negacja nie uratuje plików wewnątrz wykluczonego katalogu. Dokumentacja gita jest jednoznaczna: „Nie można ponownie dołączyć pliku, jeśli katalog nadrzędny tego pliku jest wykluczony” (git-scm.com/docs/gitignore). To decyzja wydajnościowa — git pomija wykluczone katalogi w całości, zamiast po nich chodzić. Dlatego to nie działa:
build/
!build/keep.me # martwa reguła — git nigdy nie zagląda do build/ Rozwiązanie: wyklucz zawartość, nie katalog:
build/*
!build/keep.me # działa — build/ sam w sobie zostaje otwarty do wglądu 3. Zagnieżdżone .gitignore wygrywają w swoim zasięgu. Reguły w subdir/.gitignore nadpisują plik główny dla ścieżek pod subdir. Gdy git check-ignore -v wskaże źródło reguły, którego się nie spodziewałeś, zwykle o to chodzi.
Dlaczego gitignore nie działa w VS Code?
Prawie nigdy z winy VS Code. Widok Source Control czyta ten sam indeks co git, więc objaw jest identyczny: plik był już zacommitowany, a żaden restart IDE nie zmienia indeksu. Dwie rzeczy wokół VS Code warte znajomości:
- Wyszarzony w Explorerze = ignorowany; pomarańczowy/żółty = śledzony ze zmianami. Plik pokazujący się jako zmodyfikowany po dodaniu reguły to twoje potwierdzenie, że jest śledzony — odpal wyżej opisaną naprawę z
git rm --cached. - Brak
.gitignorena liście zmian w Explorerze oznacza, że reguła działa — plik w ogóle nie pojawia się jako nieśledzony. Ludzie często zgłaszają „VS Code ignoruje moje gitignore”, gdy CLI-owegit statusrozmija się ze nieświeżym widokiem SCM; przeładuj okno (Cmd/Ctrl+Shift+P→ „Reload Window”), zanim obwinisz gita.
.gitignore vs .git/info/exclude vs globalny: który na kiedy?
| Plik | Zasięg | Commitowany? | Do czego |
|---|---|---|---|
.gitignore (repo) | Każdy, kto sklonuje | Tak | Wyniki builda, zależności, .env — reguły współdzielone |
.git/info/exclude | Tylko twój klon | Nie | Osobiste śmieci: .scratch/, odpadki edytora |
core.excludesFile (globalny) | Wszystkie twoje repo | Nie | Śmieci systemowe: .DS_Store, Thumbs.db, *.swp |
.gitignore + negacja | Repo | Tak | Przywracanie wyjątków w śledzonej konfiguracji |
Plik globalny to ten, którego większość programistów nigdy nie ustawia, a powinna:
git config --global core.excludesFile ~/.gitignore_global
printf '.DS_Store\nThumbs.db\n*.swp\n' >> ~/.gitignore_global Reguła domu warta skopiowania: jeśli reguła służy całemu zespołowi, należy do repo; jeśli tylko tobie, należy do exclude albo pliku globalnego. Commitowanie osobistych reguł ignorowania to sposób, w jaki .gitignore rozrastają się do 300 linii, a nikt nie wie, która połowa jeszcze coś robi.
Jak zignorować zmiany w śledzonym pliku?
Czasem chcesz mieć śledzony plik (szablon konfiguracji, ustawienia IDE), ale chcesz, by lokalne zmiany przestały się pokazywać w git status. Dwie flagi git update-index, z których żadna nie należy do zespołowego workflow:
git update-index --skip-worktree config/local.dev # lokalne zmiany milkną
git update-index --no-skip-worktree config/local.dev # ...i z powrotem --skip-worktree to broniona opcja — mówi „moja lokalna wersja celowo odbiega”. Kuzynka --assume-unchanged to obietnica wydajnościowa („ten plik się nie zmieni”), nie mechanizm ignorowania, a git może po cichu ją złamać. Obie flagi krzyczą przy pullu, gdy upstream też zmienił plik — trwałe odpowiedzi to lokalna konfiguracja przez exclude od chwili stworzenia repo albo plik szablonowy (config.example), który git śledzi, a ty kopiujesz.
Kontrola .gitignore w 30 sekund
git check-ignore -v <path> # która reguła? (milczenie = śledzony, brak reguły)
git ls-files --error-unmatch <path> # czy w ogóle jest śledzony?
git rm --cached <path> # wycofaj ze śledzenia, zostaw na dysku
git commit -m "stop tracking <path>"
git check-ignore -v <path> # reguła już się pokazuje Diagnoza, wycofanie, weryfikacja. Wzorzec za każdym zgłoszeniem „gitignore nie działa” to ten sam plik w dwóch rolach — śledzony po jednej stronie indeksu, ignorowany po drugiej — a jedna flaga --cached zdejmuje mu drugą rolę.
FAQ
Dlaczego .gitignore nie działa?
W większości przypadków plik jest już śledzony. Git ignoruje wyłącznie pliki nieśledzone; plik obecny w indeksie jest odporny na .gitignore, dopóki nie wycofasz go przez git rm --cached i nie zrobisz commita.
Jak sprawdzić, która reguła gitignore pasuje do pliku?
Uruchom git check-ignore -v <path>. Wypisze dokładną linię .gitignore i numer reguły albo zakończy się w milczeniu, gdy plik jest śledzony i żadna reguła nie obowiązuje.
Czy git rm --cached usuwa mój lokalny plik?
Nie. --cached usuwa plik wyłącznie z indeksu; kopia na dysku zostaje. Zacommituj usunięcie, a plik stanie się nieśledzony i .gitignore zacznie go obowiązywać.
Dlaczego gitignore nie może przywrócić pliku wewnątrz zignorowanego folderu?
Dla wydajności Git pomija wykluczone katalogi w całości. Z dokumentacji gita wynika, że nie można ponownie dołączyć pliku, jeśli katalog nadrzędny tego pliku jest wykluczony.
— mrsaynothing
Get the next one by email
One email per post. No spam, no algorithms.
what is this?Ollama nie używa GPU? Napraw to na Linuksie, Windows i WSL
Podobają się teksty? Tak buduję zawodowo. zatrudnij mnie