.gitignore
Git widzi każdy plik w Twojej kopii roboczej jako należący do jednej z trzech kategorii:
- śledzony — plik, który został już dodany do przechowalni lub zatwierdzony;
- nieśledzony — plik, który nie został dodany do przechowalni ani zatwierdzony;
- ignorowany — plik, który zgodnie z wyraźnym poleceniem Git ma ignorować.
Plikami ignorowanymi są zazwyczaj artefakty kompilacji oraz pliki generowane maszynowo, które mogą pochodzić ze źródła repozytorium lub z innych powodów nie powinny być zatwierdzane. Do typowych przykładów należą:
- pamięci podręczne zależności, takie jak zawartość katalogów
/node_modules
lub/packages
; - skompilowany kod, np. pliki
.o
,.pyc
i.class
; - katalogi wyjściowe kompilacji, np.
/bin
,/out
lub/target
; - pliki generowane w czasie wykonywania, takie jak
.log
,.lock
lub.tmp
; - ukryte pliki systemowe, takie jak
.DS_Store
lubThumbs.db
; - osobiste pliki konfiguracji IDE, takie jak
.idea/workspace.xml
.
Pliki ignorowane są śledzone w specjalnym pliku o nazwie .gitignore
, który jest ewidencjonowany w katalogu głównym repozytorium. W Git nie ma wyraźnego polecenia ignorowania. Jeśli pojawią się nowe pliki, które chcesz ignorować, musisz edytować plik .gitignore
, a następnie zatwierdzić go ręcznie. Nazwy plików w repozytorium są porównywane z wzorcami w pliku .gitignore
w celu określenia, czy powinny być ignorowane.
- Ignorowanie plików w Git
Wzorce ignorowania Git
Plik .gitignore
wykorzystuje wzorce z obsługą symboli wieloznacznych do porównywania z nazwami plików. Możesz tworzyć własne wzorce, używając różnych symboli:
Wzorzec | Przykładowe dopasowania | Objaśnienie* |
---|---|---|
**/logs | logs/debug.log logs/monday/foo.bar build/logs/debug.log | Można poprzedzić wzorzec podwójną gwiazdką, aby dopasować katalogi z dowolnej lokalizacji w repozytorium. |
**/logs/debug.log | logs/debug.log build/logs/debug.log ale nie logs/build/debug.log | Można również użyć podwójnej gwiazdki, aby dopasować pliki na podstawie ich nazwy i nazwy ich katalogu nadrzędnego. |
*.log | debug.log foo.log .log logs/debug.log | Gwiazdka jest symbolem wieloznacznym, który może zastępować zero lub większą liczbę znaków. |
*.log !important.log | debug.log trace.log ale nie important.log logs/important.log | Poprzedzenie wzorca wykrzyknikiem powoduje jego zanegowanie. Jeśli plik będzie pasował do wzorca, ale równocześnie będzie pasował do zdefiniowanego później w pliku wzorca negacji, nie będzie ignorowany. |
*.log !important/*.log trace.* | debug.log important/trace.log ale nie important/debug.log | Wzorce zdefiniowane po wzorcu negacji spowodują ponowne zignorowanie wszelkich zanegowanych wcześniej plików. |
/debug.log | debug.log ale nie logs/debug.log | Poprzedzenie ukośnikiem umożliwia dopasowanie wyłącznie plików w katalogu głównym repozytorium. |
debug.log | debug.log logs/debug.log | Domyślnie wzorce są porównywane z plikami w dowolnym katalogu. |
debug?.log | debug0.log debugg.log ale nie debug10.log | Znak zapytania zastępuje dokładnie jeden znak. |
debug[0-9].log | debug0.log debug1.log ale nie debug10.log | Nawiasy kwadratowe można wykorzystać także do dopasowania pojedynczego znaku ze wskazanego zakresu. |
debug[01].log | debug0.log debug1.log ale nie debug2.log debug01.log | Nawiasy kwadratowe pozwalają dopasować jeden znak ze wskazanego zbioru. |
debug[!01].log | debug2.log ale nie debug0.log debug1.log debug01.log | Wykrzyknik pozwala dopasować dowolny znak nienależący do wskazanego zbioru. |
debug[a-z].log | debuga.log debugb.log ale nie debug1.log | Zakresy mogą być liczbowe lub alfabetyczne. |
logs | logs logs/debug.log logs/latest/foo.bar build/logs build/logs/debug.log | W razie pominięcia ukośnika, wzorzec będzie pasował zarówno do plików, jak i do zawartości katalogów o takiej nazwie. W przykładowych dopasowaniach z lewej strony, zarówno katalogi, jak i pliki o nazwie logs zostaną zignorowane. |
logs/ | logs/debug.log logs/latest/foo.bar build/logs/foo.bar build/logs/latest/debug.log | Dołączenie ukośnika wskazuje, że wzorzec jest katalogiem. Cała zawartość dowolnego katalogu o pasującej nazwie w repozytorium — wraz ze wszystkimi plikami i katalogami podrzędnymi — zostanie zignorowana. |
logs/ !logs/important.log | logs/debug.log logs/important.log | Chwileczkę! Czy logs/important.log w przykładzie po lewej nie powinno być zanegowane?Nie. Ze względu na specyficzny mechanizm związany z wydajnością systemu Git nie można zanegować pliku, który został zignorowany z powodu pasującego do wzorca katalogu. |
logs/**/debug.log | logs/debug.log logs/monday/debug.log logs/monday/pm/debug.log | Podwójna gwiazdka zastępuje zero lub większą liczbę katalogów. |
logs/*day/debug.log | logs/monday/debug.log logs/tuesday/debug.log ale nie logs/latest/debug.log | Symboli wieloznacznych można używać także w nazwach katalogów. |
logs/debug.log | logs/debug.log ale nie debug.log build/logs/debug.log | Wzorce określające plik w konkretnym katalogu są względne w stosunku do katalogu głównego repozytorium. (Można poprzedzić je ukośnikiem, jednak nie wywołuje to żadnego konkretnego skutku). |
** przedstawione powyżej objaśnienia zakładają, że plik .gitignore znajduje się w katalogu najwyższego poziomu repozytorium, zgodnie z konwencją. Jeśli w repozytorium znajduje się wiele plików .gitignore, wystarczy zastąpić w myślach „katalog główny repozytorium” „katalogiem zawierającym plik .gitignore” (i rozważyć ich unifikację dla dobra zespołu).*
Oprócz tych znaków można użyć znaku #, aby dodać komentarze w pliku .gitignore
:
# ignore all logs
*.log
Za pomocą symbolu \ można wprowadzić znaki specjalne wzorca .gitignore
, jeśli pliki lub katalogi je zawierają:
# ignore the file literally named foo[01].txt
foo\[01\].txt
Udostępnione pliki .gitignore w repozytorium
Reguły ignorowania Git zazwyczaj są definiowane w pliku .gitignore
znajdującym się w katalogu głównym repozytorium. Można jednak zdefiniować wiele plików .gitignore
w różnych katalogach w repozytorium. Każdy wzorzec w konkretnym pliku .gitignore
jest testowany w odniesieniu do katalogu zawierającego ten plik. Jednak konwencja i zarazem najprostsze podejście zakłada zdefiniowanie jednego pliku .gitignore
w katalogu głównym. Po zaewidencjonowaniu pliku .gitignore
jest on wersjonowany jak każdy inny plik w repozytorium i udostępniany innym członkom zespołu po wypchnięciu. Zazwyczaj w pliku .gitignore
uwzględnia się tylko wzorce, które będą przydatne dla innych użytkowników repozytorium.
Osobiste reguły ignorowania Git
Można również zdefiniować osobiste wzorce ignorowania dla konkretnego repozytorium w specjalnym pliku znajdującym się w lokalizacji .git/info/exclude
. Nie są one wersjonowane ani dystrybuowane razem z repozytorium, więc jest to odpowiednie miejsce, aby dodać wzorce, które najprawdopodobniej będą przydatne tylko dla Ciebie. Przykładowo, jeśli korzystasz z niestandardowej konfiguracji rejestrowania lub specjalnych narzędzi programistycznych, które generują pliki w katalogu roboczym repozytorium, warto dodać je do lokalizacji .git/info/exclude
, aby zapobiec przypadkowemu zatwierdzeniu ich w repozytorium.
Globalne reguły ignorowania Git
Ponadto można zdefiniować globalne wzorce ignorowania Git dla wszystkich repozytoriów w systemie lokalnym, ustawiając właściwość core.excludesFile
w Git. Plik musisz utworzyć samodzielnie. Jeśli nie wiesz, gdzie umieścić globalny plik .gitignore
, dobrym wyborem będzie katalog główny (w ten sposób można go również łatwo znaleźć później). Po utworzeniu pliku musisz skonfigurować jego lokalizację za pomocą polecenia git config
:
$ touch ~/.gitignore
$ git config --global core.excludesFile ~/.gitignore
Należy uważać, jakie wzorce są wybierane na potrzeby globalnego ignorowania, ponieważ w różnych projektach wykorzystuje się różnego rodzaju pliki. Specjalne pliki systemu operacyjnego (np. .ds_store
i thumbs.db
) lub pliki tymczasowe tworzone przez niektóre narzędzia programistyczne są typowymi kandydatami do globalnego ignorowania.
Ignorowanie wcześniej zatwierdzonego pliku
Aby zignorować plik, który został już wcześniej zatwierdzony, należy go usunąć z repozytorium, a następnie dodać dla niego regułę .gitignore
. Użycie opcji --cached
z poleceniem git rm
oznacza, że plik zostanie usunięty z repozytorium, ale pozostanie w katalogu roboczym jako plik ignorowany.
$ echo debug.log >> .gitignore
$ git rm --cached debug.log
rm 'debug.log'
$ git commit -m "Start ignoring debug.log"
Można również pominąć opcję --cached
, aby usunąć plik zarówno z repozytorium, jak i z lokalnego systemu plików.
Zatwierdzanie ignorowanego pliku
Można wymusić zatwierdzenie w repozytorium zignorowanego pliku za pomocą opcji -f
(lub --force
) użytej z poleceniem git add
:
$ cat .gitignore
*.log
$ git add -f debug.log
$ git commit -m "Force adding debug.log"
Warto rozważyć ten sposób, jeśli zdefiniowano ogólny wzorzec (np. *.log
), ale trzeba zatwierdzić konkretny plik. Lepszym rozwiązaniem jest jednak zdefiniowanie wyjątku od reguły ogólnej:
$ echo !debug.log >> .gitignore
$ cat .gitignore
*.log
!debug.log
$ git add debug.log
$ git commit -m "Adding debug.log"
Takie podejście jest bardziej oczywiste i wprowadza mniej zamieszania dla innych członków zespołu.
Dodawanie do schowka ignorowanego pliku
Polecenie git stash
to zaawansowana funkcja Git służąca do tymczasowego „odkładania na półkę” i przywracania zmian lokalnych z możliwością ich ponownego zastosowania w przyszłości. Jak można się spodziewać, domyślnie polecenie git stash
ignoruje pliki ignorowane i dodaje do schowka zmiany wyłącznie w plikach śledzonych przez Git. Można jednak użyć polecenia git stash z opcją --all, aby dodać do schowka zmiany także w ignorowanych i nieśledzonych plikach.
Debugowanie plików .gitignore
Jeśli plik .gitignore
zawiera złożone wzorce lub wzorce są rozproszone w kilku plikach .gitignore
, czasem trudno znaleźć przyczynę ignorowania konkretnego pliku. Polecenie git check-ignore
z opcją -v
(lub --verbose
) pozwala ustalić, który wzorzec powoduje ignorowanie określonego pliku:
$ git check-ignore -v debug.log
.gitignore:3:*.log debug.log
Wyświetlany wynik jest następujący:
<file containing the pattern> : <line number of the pattern> : <pattern> <file name>
Do polecenia git check-ignore
można przekazać wiele nazw plików, a same nazwy nie muszą nawet odpowiadać plikom, które występują w repozytorium.