Jak zignorować pliki w katalogu w Git?

544

Jaka jest właściwa składnia .gitignorepliku do ignorowania plików w katalogu?

Czy może być

config/databases.yml
cache/*
log/*
data/sql/*
lib/filter/base/*
lib/form/base/*
lib/model/map/*
lib/model/om/*

lub

/config/databases.yml
/cache/*
/log/*
/data/sql/*
/lib/filter/base/*
/lib/form/base/*
/lib/model/map/*
/lib/model/om/*

?

Chris McKnight
źródło
5
czy .gitignorerozróżnia pliki i katalogi, które ignoruje? na przykład, czy datavs data/oznacza różne rzeczy?
Charlie Parker
6
@CharlieParker yes-ish: datazignoruje pasujące pliki i katalogi, data/zignoruje tylko pasujące katalogi.
jox
Zawsze pamiętaj, jeśli zainscenizowałeś lub zatwierdziłeś plik, który próbujesz zignorować, to nie ma sposobu, aby go zignorować :( Tylko moje 2 centy po tym, jak pomyślałem, że popełniłem błąd i marnowałem kwadrans.
Adam
@Adam poprawny, musisz zaktualizować plik .gitignore, a następnie cofnąć scenę / git rm - buforowałem plik.
Chris McKnight

Odpowiedzi:

374

FORMAT WZORU

  • Pusty wiersz nie pasuje do żadnych plików, więc może służyć jako separator dla czytelności.

  • Linia rozpoczynająca się od #służy jako komentarz.

  • Opcjonalny przedrostek, !który neguje wzór; każdy pasujący plik wykluczony przez poprzedni wzór zostanie ponownie dołączony. Jeśli negowany wzorzec pasuje, zastąpi to źródła wzorców o niższym priorytecie.

  • Jeśli wzorzec kończy się ukośnikiem, jest usuwany na potrzeby poniższego opisu, ale znajdzie dopasowanie tylko z katalogiem. Innymi słowy, foo/dopasuje katalog fooi ścieżki pod nim, ale nie będzie pasował do zwykłego pliku lub dowiązania symbolicznego foo(jest to zgodne ze sposobem, w jaki ogólnie działa pathspec).

  • Jeśli wzorzec nie zawiera ukośnika /, git traktuje go jako wzorzec globu powłoki i sprawdza zgodność z nazwą ścieżki względem lokalizacji .gitignorepliku (względem najwyższego poziomu drzewa roboczego, jeśli nie z .gitignorepliku).

  • W przeciwnym razie, Git traktuje wzorca jako glob powłoki odpowiedniej do spożycia przez fnmatch(3)z FNM_PATHNAMEflagą: dzikie karty we wzorcu nie dopasuje /się do ścieżki. Na przykład Documentation/*.htmlpasuje, Documentation/git.htmlale nie Documentation/ppc/ppc.htmllub tools/perf/Documentation/perf.html.

  • Wiodący ukośnik pasuje do początku nazwy ścieżki. Na przykład /*.cpasuje, cat-file.cale nie pasuje mozilla-sha1/sha1.c.

Możesz znaleźć więcej tutaj

git help gitignore
lub
man gitignore

Op De Cirkel
źródło
2
Jak mogę umieścić plik .gitignore na najwyższym poziomie i sprawić, aby działał dla dowolnego folderu poniżej? Dziękuję Ci.
Royi,
104
-1 TL; DR i ledwo odpowiada na pytanie. Chodzi o katalogi, a nie pliki, więc sekcja pogrubiona to tylko apropos z pewną gimnastyką umysłową. @Jefromi był bardziej bezpośredni.
Bob Stein
Przeczytałem tego człowieka i odpowiedź @ Jefromi jest lepsza - o ile również przeczytasz ostrzeżenie @ jox - i @ Luke Hutton mogą być bardziej przydatne do ignorowania np. Plików projektu IDE.
WillC
1
Jest to tak naprawdę kopia-wklej z dokumentacji git
mcont
1
Nie jestem pewien (zasadniczo) kopiowanie-wklejanie manstrony lub oficjalnego dokumentu to najlepszy format dla SO ...
jdk1.0 19.04.19
183

To byłby pierwszy. Przejdź także według rozszerzeń zamiast struktury folderów.

Tj. Mój przykład C # plik ignorowania rozwoju:

#OS junk files
[Tt]humbs.db
*.DS_Store

#Visual Studio files
*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf
ipch/
obj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad

#Tooling
_ReSharper*/
*.resharper
[Tt]est[Rr]esult*

#Project files
[Bb]uild/

#Subversion files
.svn

# Office Temp Files
~$*

Aktualizacja

Myślałem, że przedstawię aktualizację z poniższych komentarzy. Chociaż nie odpowiada bezpośrednio na pytanie PO, zobacz następujące przykłady .gitignoreskładni.

Wiki społeczności (stale aktualizowane):

.gitignore dla projektów i rozwiązań Visual Studio

Więcej przykładów z użyciem określonego języka można znaleźć tutaj (dzięki komentarzowi Chrisa McKnighta):

https://github.com/github/gitignore

Luke Hutton
źródło
5
@Stallman, to jest range. Więc pasuje *.Objtak samo jak *.obj.
norbert
131

Ścieżki zawierające ukośniki są uznawane za względne w stosunku do katalogu zawierającego plik .gitignore - zwykle najwyższy poziom repozytorium, chociaż można je również umieścić w podkatalogach.

Ponieważ we wszystkich podanych przykładach ścieżki zawierają ukośniki, obie wersje są identyczne. Jedyny raz, kiedy potrzebujesz umieścić wiodący ukośnik, jest to, że nie ma go jeszcze na ścieżce. Na przykład, aby zignorować foo tylko na najwyższym poziomie repozytorium, użyj /foo. Zwykłe pisanie foozignorowałoby wszystko, co nazywa się foo, w dowolnym miejscu w repozytorium.

Twoje symbole wieloznaczne są również zbędne. Jeśli chcesz zignorować cały katalog, po prostu nazwij go:

lib/model/om

Jedynym powodem używania symboli wieloznacznych tak, jak masz, jest zamiar późniejszego zignorowania czegoś w katalogu:

lib/model/om/*      # ignore everything in the directory
!lib/model/om/foo   # except foo
Cascabel
źródło
5
Lepsze wyjaśnienie niż zaakceptowana odpowiedź na to pytanie
eerrzz
78

Wiodący ukośnik wskazuje, że wpis ignorowania może być poprawny tylko w odniesieniu do katalogu, w którym znajduje się plik .gitignore. Określenie *.ozignoruje wszystkie pliki .o w tym katalogu i wszystkich podkatalogach, a /*.opo prostu zignoruje je w tym katalogu , a ponownie /foo/*.ozignoruje je tylko w /foo/*.o.

jørgensen
źródło
34

Jeśli chcesz umieścić plik .gitignore na najwyższym poziomie i sprawić, aby działał dla dowolnego folderu poniżej, użyj go /**/.

Np. Aby zignorować wszystkie *.mappliki w /src/main/folderze i podfolderach użyj:

/src/main/**/*.map
petrsyn
źródło
Musiałem to zrobić. Nie jestem pewien, dlaczego potrzebujesz dwóch ** . Jeden mi wystarczył.
Novocaine,
8
** pasuje również do plików w podkatalogach
petrsyn
Dzięki za informacje @petrsyn
Novocaine
30

Oba przykłady w pytaniu są w rzeczywistości bardzo złymi przykładami, które mogą prowadzić do utraty danych!

Moja rada: nigdy nie dołączaj /*do katalogów w plikach .gitignore, chyba że masz dobry powód!

Dobrym powodem byłoby na przykład to, co napisał Jefromi: „jeśli zamierzasz później zignorować coś w katalogu” .

Powodem, dla którego inaczej nie należy tego robić, jest to, że dołączanie /*do katalogów z jednej strony działa w taki sposób, że właściwie ignoruje całą zawartość katalogu, ale z drugiej strony ma niebezpieczny efekt uboczny:

Jeśli wykonasz git stash -u(aby tymczasowo ukryć śledzone i nieśledzone pliki) lub git clean -df(aby usunąć nieśledzone, ale zachowaj zignorowane pliki) w swoim repozytorium, wszystkie katalogi, które zostaną zignorowane za pomocą dołączonego, /*zostaną nieodwracalnie usunięte !

Trochę tła

Musiałem się tego nauczyć na własnej skórze. Ktoś z mojego zespołu dołączał /*do niektórych katalogów w naszym .gitignore. Z czasem miałem okazje, aby niektóre katalogi nagle zniknęły. Katalogi z gigabajtami danych lokalnych wymaganych przez naszą aplikację. Nikt nie mógł tego wyjaśnić i zawsze nie mogę ponownie pobrać wszystkich danych. Po chwili zrozumiałem, że może to mieć związek z tym git stash. Pewnego dnia chciałem wyczyścić moje lokalne repozytorium (zachowując zignorowane pliki) i używałem git clean -dfi znowu moje dane zniknęły. Tym razem miałem dość i zbadałem problem. W końcu doszedłem do wniosku, że przyczyną jest dołączony dodatek /*.

Zakładam, że można to jakoś wyjaśnić faktem, że directory/*ignoruje całą zawartość katalogu, ale nie sam katalog. Dlatego nie jest uważane za śledzone ani ignorowane, gdy rzeczy są usuwane. Chociaż git statusi git status --ignoreddać nieco inny obraz na nim.

Jak się rozmnażać

Oto jak odtworzyć zachowanie. Obecnie używam Git 2.8.4.

Katalog wywoływany localdata/z fikcyjnym plikiem ( important.dat) zostanie utworzony w lokalnym repozytorium git, a zawartość zostanie zignorowana przez umieszczenie /localdata/*w .gitignorepliku. Kiedy jedno z dwóch wymienionych poleceń git zostanie teraz wykonane, katalog zostanie (nieoczekiwanie) utracony.

mkdir test
cd test
git init
echo "/localdata/*" >.gitignore
git add .gitignore
git commit -m "Add .gitignore."
mkdir localdata
echo "Important data" >localdata/important.dat
touch untracked-file

Jeśli to zrobisz git status --ignored, otrzymasz:

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

  untracked-file

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

  localdata/

Teraz albo zrób

git stash -u
git stash pop

lub

git clean -df

W obu przypadkach rzekomo zignorowany katalog localdatazniknie!

Nie jestem pewien, czy można to uznać za błąd, ale myślę, że jest to przynajmniej funkcja, której nikt nie potrzebuje.

Zgłoszę to na listę deweloperów git i zobaczę, co o tym myślą.

jox
źródło
15

To byłby:

config/databases.yml
cache
log
data/sql
lib/filter/base
lib/form/base
lib/model/map
lib/model/om

a może nawet:

config/databases.yml
cache
log
data/sql
lib/*/base
lib/model/map
lib/model/om

w przypadku, filteri formsą jedynymi katalogi w lib że mam basepodkatalog, który musi być ignorowane (zobacz go jako przykład tego, co można zrobić z asterics).

aefxx
źródło
14

Pierwszy. Te ścieżki do plików są względne względem miejsca, w którym znajduje się plik .gitignore.

Unixmonkey
źródło
2
Dotyczy to tylko wzorów zawierających ukośnik. Pojedyncza nazwa katalogu, np. „Mój katalog”, będzie również ignorować katalogi (i pliki) znajdujące się w podfolderach na dowolnej głębokości. Tylko umieszczenie ukośnika na początku sprawi, że będzie względny z miejsca, w którym znajduje się plik .gitignore.
jox
4

Utrzymuję usługę opartą na GUI i CLI, która pozwala .gitignorebardzo łatwo generować szablony na https://www.gitignore.io .

Możesz wpisać odpowiednie szablony w polu wyszukiwania lub zainstalować alias wiersza polecenia i uruchomić

$ gi swift,osx

Joe
źródło
0

Przykładowy plik .gitignore może wyglądać jak poniżej dla projektu Android Studio

# built application files
*.apk
*.ap_

# files for the dex VM
*.dex

# Java class files
*.class

# generated files
bin/
gen/

# Local configuration file (sdk path, etc)
local.properties


#Eclipse
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
YourProjetcName/.gradle/
YourProjetcName/app/build/
*/YourProjetcName/.gradle/
*/YourProjetcName/app/build/

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath

# Proguard folder generated by Eclipse
proguard/

# Intellij project files
*.iml
*.ipr
*.iws
.idea/
/build
build/
*/build/
*/*/build/
*/*/*/build/
*.bin
*.lock
YourProjetcName/app/build/
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
.gradle/
app/build/
*app/build/

# Local configuration file (sdk path, etc)
local.properties
/YourProjetcName/build/intermediates/lint-cache/api-versions-6-23.1.bin
appcompat_v7_23_1_1.xml
projectFilesBackup
build.gradle
YourProjetcName.iml
YourProjetcName.iml
gradlew
gradlew.bat
local.properties
settings.gradle
.gradle
.idea
android
build
gradle
Shirish Herwade
źródło