Szukaj…


Wprowadzenie

W tym temacie pokazano, jak unikać dodawania niechcianych plików (lub zmian plików) w repozytorium Git. Istnieje kilka sposobów (globalny lub lokalny .gitignore , .git/exclude , git update-index --assume-unchanged i git update-index --skip-tree ), ale pamiętaj, że Git zarządza treścią , co oznacza: ignorowanie faktycznie ignoruje zawartość folderu (tzn. pliki). Pusty folder byłby domyślnie ignorowany, ponieważ i tak nie można go dodać.

Ignorowanie plików i katalogów za pomocą pliku .gitignore

Możesz sprawić, aby Git ignorował niektóre pliki i katalogi - to znaczy wykluczył je ze śledzenia przez Git - tworząc jeden lub więcej plików .gitignore w repozytorium.

W projektach programowych .gitignore zazwyczaj zawiera listę plików i / lub katalogów generowanych podczas procesu kompilacji lub w czasie wykonywania. Wpisy w pliku .gitignore mogą zawierać nazwy lub ścieżki wskazujące na:

  1. zasoby tymczasowe, np. pamięci podręczne, pliki dziennika, skompilowany kod itp.
  2. lokalne pliki konfiguracyjne, których nie należy udostępniać innym programistom
  3. pliki zawierające tajne informacje, takie jak hasła logowania, klucze i poświadczenia

Po utworzeniu w katalogu najwyższego poziomu reguły będą miały zastosowanie rekurencyjne do wszystkich plików i podkatalogów w całym repozytorium. Po utworzeniu w podkatalogu reguły będą miały zastosowanie do tego konkretnego katalogu i jego podkatalogów.

Gdy plik lub katalog zostanie zignorowany, nie będzie to:

  1. śledzone przez Git
  2. zgłaszane przez polecenia takie jak git status lub git diff
  3. przemieszczane za pomocą poleceń takich jak git add -A

W nietypowym przypadku, gdy musisz zignorować śledzone pliki, należy zachować szczególną ostrożność. Zobacz: Ignoruj pliki, które zostały już zatwierdzone w repozytorium Git .


Przykłady

Oto kilka ogólnych przykładów reguł w pliku .gitignore , opartych na wzorcach plików glob :

# Lines starting with `#` are comments.

# Ignore files called 'file.ext'
file.ext

# Comments can't be on the same line as rules!
# The following line ignores files called 'file.ext # not a comment'
file.ext # not a comment 

# Ignoring files with full path.
# This matches files in the root directory and subdirectories too.
# i.e. otherfile.ext will be ignored anywhere on the tree.
dir/otherdir/file.ext
otherfile.ext

# Ignoring directories
# Both the directory itself and its contents will be ignored.
bin/
gen/

# Glob pattern can also be used here to ignore paths with certain characters.
# For example, the below rule will match both build/ and Build/
[bB]uild/

# Without the trailing slash, the rule will match a file and/or
# a directory, so the following would ignore both a file named `gen`
# and a directory named `gen`, as well as any contents of that directory
bin
gen

# Ignoring files by extension
# All files with these extensions will be ignored in
# this directory and all its sub-directories.
*.apk
*.class

# It's possible to combine both forms to ignore files with certain
# extensions in certain directories. The following rules would be
# redundant with generic rules defined above.
java/*.apk
gen/*.class

# To ignore files only at the top level directory, but not in its
# subdirectories, prefix the rule with a `/`
/*.apk
/*.class

# To ignore any directories named DirectoryA 
# in any depth use ** before DirectoryA
# Do not forget the last /, 
# Otherwise it will ignore all files named DirectoryA, rather than directories
**/DirectoryA/
# This would ignore 
# DirectoryA/
# DirectoryB/DirectoryA/ 
# DirectoryC/DirectoryB/DirectoryA/
# It would not ignore a file named DirectoryA, at any level

# To ignore any directory named DirectoryB within a 
# directory named DirectoryA with any number of 
# directories in between, use ** between the directories
DirectoryA/**/DirectoryB/
# This would ignore 
# DirectoryA/DirectoryB/ 
# DirectoryA/DirectoryQ/DirectoryB/ 
# DirectoryA/DirectoryQ/DirectoryW/DirectoryB/

# To ignore a set of files, wildcards can be used, as can be seen above.
# A sole '*' will ignore everything in your folder, including your .gitignore file.
# To exclude specific files when using wildcards, negate them.
# So they are excluded from the ignore list:
!.gitignore 

# Use the backslash as escape character to ignore files with a hash (#)
# (supported since 1.6.2.1)
\#*#

Większość plików .gitignore jest standardowych w różnych językach, więc na początek jest zestaw przykładowych plików .gitignore wymienionych według języka, z którego można sklonować lub skopiować / zmodyfikować w projekcie. Alternatywnie, dla świeżego projektu możesz rozważyć automatyczne wygenerowanie pliku startowego za pomocą narzędzia online .


Inne formy .gitignore

Pliki .gitignore są przeznaczone do zatwierdzenia jako część repozytorium. Jeśli chcesz zignorować niektóre pliki bez zatwierdzania reguł ignorowania, oto kilka opcji:

  • Edytuj plik .git/info/exclude (używając tej samej składni co .gitignore ). Reguły będą globalne w zakresie repozytorium;
  • Skonfiguruj globalny plik gitignore, który zastosuje reguły ignorowania do wszystkich lokalnych repozytoriów:

Ponadto możesz zignorować lokalne zmiany w śledzonych plikach bez zmiany globalnej konfiguracji git za pomocą:

  • git update-index --skip-worktree [<file>...] : dla drobnych modyfikacji lokalnych
  • git update-index --assume-unchanged [<file>...] : dla gotowych do produkcji, niezmiennych plików w górę

Zobacz więcej szczegółów na temat różnic między tymi ostatnimi flagami a dokumentacją git update-index aby uzyskać dodatkowe opcje.


Czyszczenie zignorowanych plików

Możesz użyć git clean -X aby git clean -X zignorowane pliki:

git clean -Xn #display a list of ignored files
git clean -Xf #remove the previously displayed files

Uwaga: -X ( -X litery) czyści tylko ignorowane pliki. Użyj -x (bez wielkich liter), aby również usunąć nieśledzone pliki.

Więcej informacji znajduje się w dokumentacji git clean .


Więcej informacji znajduje się w podręczniku Git .

Wyjątki w pliku .gitignore

Jeśli pliki są ignorowane przy użyciu wzorca, ale mają wyjątki, należy poprzedzić wykrzyknikiem (!) Wyjątek. Na przykład:

*.txt
!important.txt

Powyższy przykład instruuje Git, aby ignorował wszystkie pliki z rozszerzeniem .txt z wyjątkiem plików o nazwie important.txt .

Jeśli plik znajduje się w zignorowanym folderze, NIE możesz go tak łatwo ponownie dołączyć:

folder/
!folder/*.txt

W tym przykładzie wszystkie pliki .txt w folderze pozostaną ignorowane.

Właściwym sposobem jest ponowne włączenie samego folderu w osobnym wierszu, a następnie zignorowanie wszystkich plików w folder przez * , a następnie ponowne dołączenie *.txt w folder , jak poniżej:

!folder/
folder/*
!folder/*.txt

Uwaga : W przypadku nazw plików rozpoczynających się od wykrzyknika dodaj dwa wykrzykniki lub użyj znaku \ :

!!includethis
\!excludethis

Globalny plik .gitignore

Aby Git ignorował niektóre pliki we wszystkich repozytoriach, możesz utworzyć globalny plik .gitignore za pomocą następującego polecenia w terminalu lub wierszu polecenia:

$ git config --global core.excludesfile <Path_To_Global_gitignore_file>

Git będzie teraz używał tego oprócz własnego pliku .gitignore każdego repozytorium. Zasady tego są następujące:

  • Jeśli lokalny plik .gitignore wyraźnie zawiera plik, podczas gdy globalny .gitignore go ignoruje, lokalny .gitignore ma priorytet (plik zostanie dołączony)
  • Jeśli repozytorium klonuje się na wielu maszynach, to globalny .gigignore muszą zostać załadowane na wszystkich maszynach lub przynajmniej włączenie go, jak pliki zostaną zignorowane popychany do repo natomiast PC z globalnym .gitignore nie będzie go zaktualizować . To dlatego repo specyficzny .gitignore jest lepszym pomysłem niż globalnej, jeśli projekt jest opracowywane przez zespół

Ten plik jest dobrym miejscem do ignorowania ignorowanych przez platformę, maszynę lub użytkownika elementów, np. OSX .DS_Store , Windows Thumbs.db lub Vim *.ext~ i *.ext.swp ignoruje je, jeśli nie chcesz przechowywać ich w repozytorium . Tak więc jeden członek zespołu pracujący w systemie OS X może dodać wszystkie .DS_STORE i _MACOSX (co w rzeczywistości jest bezużyteczne), podczas gdy inny członek zespołu w systemie Windows może zignorować wszystkie thumbs.bd

Zignoruj pliki, które zostały już zatwierdzone w repozytorium Git

Jeśli już dodałeś plik do swojego repozytorium Git i teraz chcesz przestać go śledzić (aby nie był obecny w przyszłych zatwierdzeniach), możesz usunąć go z indeksu:

git rm --cached <file>

Spowoduje to usunięcie pliku z repozytorium i zapobiegnie śledzeniu dalszych zmian przez Git. Opcja --cached upewni się, że plik nie zostanie fizycznie usunięty.

Pamiętaj, że wcześniej dodana zawartość pliku będzie nadal widoczna w historii Git.

Pamiętaj, że jeśli ktoś usunie plik z repozytorium po usunięciu pliku z indeksu, jego kopia zostanie fizycznie usunięta .


Możesz sprawić, by Git udawał, że wersja katalogu roboczego pliku jest aktualna i zamiast tego odczytał wersję indeksu (ignorując w ten sposób zmiany) za pomocą bitu „ pomiń drzewko robocze ”:

git update-index --skip-worktree <file>

Ten bit nie wpływa na pisanie, bezpieczeństwo treści jest nadal priorytetem. Nigdy nie stracisz swoich cennych ignorowanych zmian; z drugiej strony ten bit jest w konflikcie z ukrywaniem: aby usunąć ten bit, użyj

git update-index --no-skip-worktree <file>

Czasem błędnie zaleca się okłamywanie Gita i zakładanie, że plik nie został zmieniony bez sprawdzania go. Na pierwszy rzut oka wygląda na ignorowanie jakichkolwiek dalszych zmian w pliku, bez usuwania go z indeksu:

git update-index --assume-unchanged <file>

Zmusi to git do zignorowania wszelkich zmian dokonanych w pliku (pamiętaj, że jeśli wyciągniesz jakieś zmiany do tego pliku lub ukryjesz go, twoje zignorowane zmiany zostaną utracone )

Jeśli chcesz, aby git „przejmował się” tym plikiem, uruchom następującą komendę:

git update-index --no-assume-unchanged <file>

Sprawdzanie, czy plik jest ignorowany

Polecenie git check-ignore zgłasza pliki ignorowane przez Git.

Możesz przekazać nazwy plików w wierszu poleceń, a git check-ignore wyświetli listę nazw plików, które są ignorowane. Na przykład:

$ cat .gitignore
*.o
$ git check-ignore example.o Readme.md
example.o

Tutaj tylko pliki * .o są zdefiniowane w .gitignore, więc Readme.md nie jest wymieniony w danych wyjściowych git check-ignore .

Jeśli chcesz zobaczyć wiersz, który .gitignore jest odpowiedzialny za ignorowanie pliku, dodaj -v do komendy git check-ignore:

$ git check-ignore -v example.o Readme.md
.gitignore:1:*.o        example.o

Począwszy od wersji Git 1.7.6 możesz także używać git status --ignored , aby zobaczyć zignorowane pliki. Więcej informacji na ten temat można znaleźć w oficjalnej dokumentacji lub w Znajdowaniu plików ignorowanych przez .gitignore .

Ignorowanie plików w podfolderach (wiele plików gitignore)

Załóżmy, że masz taką strukturę repozytorium:

examples/
    output.log
src/
    <files not shown>
    output.log
README.md

output.log w katalogu przykładów jest poprawny i wymagany, aby projekt zebrał zrozumienie, podczas gdy plik poniżej src/ jest tworzony podczas debugowania i nie powinien znajdować się w historii ani części repozytorium.

Istnieją dwa sposoby zignorowania tego pliku. Możesz umieścić ścieżkę bezwzględną do pliku .gitignore w katalogu głównym katalogu roboczego:

# /.gitignore
src/output.log

Alternatywnie możesz utworzyć plik .gitignore w katalogu src/ i zignorować plik względny do tego .gitignore :

# /src/.gitignore
output.log

Ignorowanie pliku w dowolnym katalogu

Aby zignorować plik foo.txt w dowolnym katalogu, wystarczy wpisać jego nazwę:

foo.txt # matches all files 'foo.txt' in any directory

Jeśli chcesz zignorować plik tylko w części drzewa, możesz określić podkatalogi określonego katalogu za pomocą ** wzorca:

bar/**/foo.txt # matches all files 'foo.txt' in 'bar' and all subdirectories

Lub możesz utworzyć plik .gitignore w katalogu bar/ . Odpowiednikiem poprzedniego przykładu byłoby utworzenie pliku bar/.gitignore z następującą zawartością:

foo.txt # matches all files 'foo.txt' in any directory under bar/

Ignoruj pliki lokalnie bez wprowadzania reguł ignorowania

.gitignore ignoruje pliki lokalnie, ale jest przeznaczone do zapisania w repozytorium i udostępnienia innym współautorom i użytkownikom. Możesz ustawić globalny .gitignore , ale wtedy wszystkie twoje repozytoria współużytkują te ustawienia.

Jeśli chcesz zignorować niektóre pliki w repozytorium lokalnie i nie .git/info/exclude pliku do żadnego repozytorium, edytuj .git/info/exclude w swoim repozytorium.

Na przykład:

# these files are only ignored on this repo
# these rules are not shared with anyone
# as they are personal                                              
gtk_tests.py
gui/gtk/tests/*
localhost
pushReports.py
server/

Wstępnie wypełnione szablony .gitignore

Jeśli nie masz pewności, które reguły .gitignore pliku .gitignore , lub po prostu chcesz dodać ogólnie akceptowane wyjątki do swojego projektu, możesz wybrać lub wygenerować plik .gitignore :

Wiele usług hostingowych, takich jak GitHub i BitBucket oferują możliwość generowania .gitignore plików w oparciu o języki programowania i IDE można używać:

Lista rozwijana GitHub .gitignore

Ignorowanie kolejnych zmian w pliku (bez usuwania)

Czasami chcesz mieć plik przechowywany w Git, ale ignorujesz kolejne zmiany.

Powiedz Gitowi, aby zignorował zmiany w pliku lub katalogu przy użyciu update-index :

git update-index --assume-unchanged my-file.txt

Powyższe polecenie nakazuje Gitowi założyć, my-file.txt nie został zmieniony i nie sprawdzać ani nie zgłaszać zmian. Plik jest nadal obecny w repozytorium.

Może to być przydatne do zapewnienia wartości domyślnych i zezwalania na lokalne zastąpienia środowiska, np .:

# create a file with some values in
cat <<EOF
MYSQL_USER=app
MYSQL_PASSWORD=FIXME_SECRET_PASSWORD
EOF > .env

# commit to Git
git add .env
git commit -m "Adding .env template"

# ignore future changes to .env
git update-index --assume-unchanged .env

# update your password
vi .env

# no changes!
git status

Ignorowanie tylko części pliku [stub]

Czasami możesz chcieć wprowadzić lokalne zmiany w pliku, którego nie chcesz zatwierdzać ani publikować. Idealnie ustawienia lokalne powinny być skoncentrowane w osobnym pliku, który można umieścić w .gitignore , ale czasami jako rozwiązanie krótkoterminowe pomocne może być posiadanie czegoś lokalnego w pliku zaewidencjonowanym.

Możesz sprawić, by Git „nie widział” tych linii, używając czystego filtra. Nie pojawią się nawet w różnicach.

Załóżmy, że tutaj jest fragment kodu z pliku file1.c :

struct settings s;
s.host = "localhost";
s.port = 5653;
s.auth = 1;
s.port = 15653; // NOCOMMIT
s.debug = 1; // NOCOMMIT
s.auth = 0; // NOCOMMIT

Nigdzie nie chcesz publikować linii NOCOMMIT .

Utwórz filtr „nocommit”, dodając go do pliku konfiguracyjnego Git, takiego jak .git/config :

[filter "nocommit"]
    clean=grep -v NOCOMMIT

Dodaj (lub utwórz) to do .git/info/attributes lub .gitmodules :

file1.c filter=nocommit

Twoje linie NOCOMMIT są ukryte przed Git.

Ostrzeżenia:

  • Użycie czystego filtra spowalnia przetwarzanie plików, szczególnie w systemie Windows.
  • Zignorowana linia może zniknąć z pliku, gdy Git ją zaktualizuje. Można temu przeciwdziałać za pomocą filtra rozmazywania, ale jest trudniejszy.
  • Nie testowano w systemie Windows

Ignorowanie zmian w śledzonych plikach. [kikut]

.gitignore i .git/info/exclude działają tylko dla nieśledzonych plików.

Aby ustawić flagę ignorowania w pliku śledzonym, użyj polecenia update-index :

git update-index --skip-worktree myfile.c

Aby to przywrócić, użyj:

git update-index --no-skip-worktree myfile.c

Możesz dodać ten fragment do swojej globalnej konfiguracji git, aby mieć wygodniejsze polecenia git hide , git unhide i git hidden :

[alias]
    hide   = update-index --skip-worktree
    unhide = update-index --no-skip-worktree
    hidden  = "!git ls-files -v | grep ^[hsS] | cut -c 3-"

Możesz także użyć opcji --assume-niezmieniona z funkcją aktualizacji indeksu

git update-index --assume-unchanged <file>

Jeśli chcesz ponownie obejrzeć ten plik pod kątem zmian, użyj

git update-index --no-assume-unchanged <file>

Jeśli podano opcję --assume-niezmienioną, użytkownik obiecuje nie zmieniać pliku i pozwala Gitowi założyć, że działający plik drzewa odpowiada temu, co jest zapisane w indeksie. Git zawiedzie, jeśli będzie musiał zmodyfikować ten plik w indeksie np. podczas łączenia zatwierdzenia; dlatego w przypadku zmiany założonego pliku, który nie został wyśledzony, należy ręcznie obsłużyć sytuację. W tym przypadku nacisk kładziony jest na wydajność.

Podczas gdy opcja --skip-worktree jest przydatna, gdy instruujesz git, aby nigdy nie dotykał określonego pliku, ponieważ plik zostanie zmieniony lokalnie i nie chcesz przypadkowo zatwierdzić zmian (tj. Pliku konfiguracji / właściwości skonfigurowanego dla określonego środowisko). Drzewo przeskoku ma pierwszeństwo przed założeniem-niezmienione, gdy oba są ustawione.

Wyczyść już zatwierdzone pliki, ale zawarte w .gitignore

Czasami zdarza się, że plik był śledzony przez git, ale później został dodany do .gitignore, aby przestać go śledzić. Bardzo częstym scenariuszem jest zapominanie o czyszczeniu takich plików przed dodaniem ich do .gitignore. W takim przypadku stary plik nadal będzie się zawieszał w repozytorium.

Aby rozwiązać ten problem, można wykonać „wszystko na sucho” usunięcie wszystkiego z repozytorium, a następnie ponownie dodać wszystkie pliki z powrotem. Dopóki nie ma oczekujących zmian, a parametr --cached jest przekazywany, uruchomienie tej komendy jest dość bezpieczne:

# Remove everything from the index (the files will stay in the file system) 
$ git rm -r --cached .

# Re-add everything (they'll be added in the current state, changes included)
$ git add .

# Commit, if anything changed. You should see only deletions
$ git commit -m 'Remove all files that are in the .gitignore'

# Update the remote
$ git push origin master

Utwórz pusty folder

Nie można dodawać i zatwierdzać pustych folderów w Git ze względu na to, że Git zarządza plikami i dołącza do nich swój katalog, co zmniejsza zatwierdzenia i przyspiesza. Aby obejść ten problem, istnieją dwie metody:

Metoda pierwsza: .gitkeep

Jednym ze .gitkeep na .gitkeep tego jest użycie pliku .gitkeep do zarejestrowania folderu w Git. Aby to zrobić, wystarczy utworzyć wymagany katalog i dodać plik .gitkeep do folderu. Ten plik jest pusty i nie służy żadnemu celowi poza rejestracją folderu. Aby to zrobić w systemie Windows (który ma dziwne konwencje nazewnictwa plików), po prostu otwórz git bash w katalogu i uruchom polecenie:

$ touch .gitkeep

To polecenie tworzy pusty plik .gitkeep w bieżącym katalogu

Metoda druga: dummy.txt

Kolejny hack do tego jest bardzo podobny do powyższego i można wykonać te same kroki, ale zamiast .gitkeep , po prostu użyj dummy.txt . Daje to dodatkową zaletę łatwego tworzenia go w systemie Windows za pomocą menu kontekstowego. Możesz też zostawić w nich śmieszne wiadomości. Możesz także użyć pliku .gitkeep do śledzenia pustego katalogu. .gitkeep zwykle jest pustym plikiem dodawanym w celu śledzenia pustego directoy.

Znajdowanie plików ignorowanych przez .gitignore

Możesz wyświetlić listę wszystkich plików ignorowanych przez git w bieżącym katalogu za pomocą polecenia:

git status --ignored

Więc jeśli mamy taką strukturę repozytorium:

.git
.gitignore
./example_1
./dir/example_2
./example_2

... i plik .gitignore zawierający:

example_2

... niż wynik polecenia będzie:

$ git status --ignored

On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

.gitignore
.example_1

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)

dir/
example_2

Jeśli chcesz wyświetlić rekursywnie ignorowane pliki w katalogach, musisz użyć dodatkowego parametru - --untracked-files=all

Wynik będzie wyglądał następująco:

$ git status --ignored --untracked-files=all
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

.gitignore
example_1

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)

dir/example_2
example_2


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow