Wróć do bloga

Gitignore nie działa? Oto prawdziwa naprawa

17 września 2026

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 .gitignore na 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-owe git status rozmija 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?

PlikZasięgCommitowany?Do czego
.gitignore (repo)Każdy, kto sklonujeTakWyniki builda, zależności, .env — reguły współdzielone
.git/info/excludeTylko twój klonNieOsobiste śmieci: .scratch/, odpadki edytora
core.excludesFile (globalny)Wszystkie twoje repoNieŚmieci systemowe: .DS_Store, Thumbs.db, *.swp
.gitignore + negacjaRepoTakPrzywracanie 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.

self-hosted · no third parties · one-click unsubscribe

what is this?

Ollama nie używa GPU? Napraw to na Linuksie, Windows i WSL

Podobają się teksty? Tak buduję zawodowo. zatrudnij mnie