Spraw, aby .gitignore ignorował wszystko oprócz kilku plików

1697

Rozumiem, że plik .gitignore maskuje określone pliki z kontroli wersji Gita. Mam projekt (LaTeX), który generuje wiele dodatkowych plików (.auth, .dvi, .pdf, logi itp.) W trakcie działania, ale nie chcę, aby były one śledzone.

Wiem, że mógłbym (może powinienem) sprawić, aby wszystkie te pliki zostały umieszczone w osobnym podfolderze w projekcie, ponieważ mogłem wtedy po prostu zignorować folder.

Czy jest jednak jakiś możliwy sposób na utrzymanie plików wyjściowych w katalogu głównym drzewa projektu i użycie .gitignore do zignorowania wszystkiego oprócz plików, które śledzę za pomocą Git? Coś jak

# Ignore everything
*

# But not these files...
script.pl
template.latex
# etc...
Andrzej
źródło
12
Duplikat stackoverflow.com/q/9162919/321973 (wiem, że to nowsze, ale odpowiedź jest bardziej poprawna). Właściwie ta odpowiedź jest prawdopodobnie najlepsza
Tobias Kienzler,

Odpowiedzi:

2436

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.

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# ...even if they are in subdirectories
!*/

# if the files to be tracked are in subdirectories
!*/a/b/file1.txt
!*/a/b/c/*
Joakim Elofsson
źródło
14
Wygląda na to, że również „ignoruje” podfoldery, tak że pliki o nazwie „script.pl” w katalogu innym niż katalog główny nie zostaną znalezione. Używam tego teraz (wraz z * .pl) i wszystkie pliki * .pl są ignorowane, mimo że wiele z nich znajduje się w podkatalogach poniżej pliku
.gitignore
38
@PandaWood Problem ten został poruszony tutaj (stackoverflow.com). Jest to spowodowane tym, że pierwsze wyrażenie pasuje do wszystkiego, łącznie z katalogami, czego nigdy nie negujesz. Aby to naprawić, dodaj (! * /), Który pasuje do dowolnego podkatalogu (rekurencyjnie) w bieżącym katalogu. To nie pomoże odpowiedzi nadrzędnej, która zawiera określone pliki na białej liście (jeśli są one w podkatalogach, prawdopodobnie prawdopodobnie chcesz ręcznie podać pełną ścieżkę lub użyć plików .gitignore specyficznych dla katalogu).
simont
40
Nie mogłem tego uruchomić. Ignoruję folder (np. wp/), Ale NIE chcę ignorować niektórych plików głęboko w tym folderze (np wp/path/to/some/location/*.). Jedynym sposobem, w jaki udało mi się go uruchomić, było zrobienie tegogit add -f wp/path/to/some/location/*
trusktr
13
@trusktr Użyj !*/wyjątku simonta
Tobias Kienzler,
7
Rany, ta ostatnia zasada: !*/robi różnicę w moich daremnych próbach udaremnienia .gitignorepliku do pracy. Dziękuję Ci bardzo.
racl101
627

Jeśli chcesz zignorować całą zawartość katalogu oprócz jednego pliku w nim, możesz napisać parę reguł dla każdego katalogu na ścieżce pliku. Np. .Gitignore, aby zignorować folder pippo, z wyjątkiem pippo / pluto / paperino.xml

.gitignore

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml
Giuseppe Galano
źródło
58
Doskonała odpowiedź, ale warto zauważyć, dla każdego, napotykając to później fooi foo/*to nie to samo. Aby to zadziałało, musisz użyć foo/*folderu podstawowego
thislooksfun
20
@Mayank Pippo to Goofy po włosku, a Paperino to Kaczor Donald, a Pluto to to samo co po angielsku. Były bardzo popularną trypletą nazw zmiennych do programowania próbek już w tamtych czasach. Miło było je ponownie przeczytać .. :)
Ghidello
To, co mówi @thislooksfun, jest ważne, jeśli chcesz „wykluczyć folder oprócz pliku x”.
Czechnology
8
nie działa dla mnie: node_modules / *! node_modules / bootstrap
SuperUberDuper
1
@simple_human Byłoby to prawdą, gdyby ignorował wszystko w katalogu głównym repozytorium lub miałby plik .gitignore, o który należałoby dbać, we wspomnianych katalogach.
xZero
244

Chcesz użyć /*zamiast *lub */w większości przypadków

Używanie *jest poprawne, ale działa rekurencyjnie. Odtąd nie będzie przeglądać katalogów. Ludzie zalecają !*/ponowne użycie listy katalogów na białej liście, ale tak naprawdę lepiej umieścić na czarnej liście folder najwyższego poziomu/*

# Blacklist files/folders in same directory as the .gitignore file
/*

# Whitelist some files
!.gitignore
!README.md

# Ignore all files named .DS_Store or ending with .log
**/.DS_Store
**.log

# Whitelist folder/a/b1/ and folder/a/b2/
# trailing "/" is optional for folders, may match file though.
# "/" is NOT optional when followed by a *
!folder/
folder/*
!folder/a/
folder/a/*
!folder/a/b1/
!folder/a/b2/
!folder/a/file.txt

# Adding to the above, this also works...
!/folder/a/deeply
/folder/a/deeply/*
!/folder/a/deeply/nested
/folder/a/deeply/nested/*
!/folder/a/deeply/nested/subfolder

Powyższy kod będzie ignorować wszystkie pliki z wyjątkiem .gitignore, README.md, folder/a/file.txt, folder/a/b1/i folder/a/b2/, a wszystko zawarte w tych ostatnich dwóch folderów. (A .DS_Storei *.logpliki będą ignorowane w tych folderach.)

Oczywiście mógłbym zrobić np. !/folderLub !/.gitignoreteż.

Więcej informacji: http://git-scm.com/docs/gitignore

Ryan Taylor
źródło
3
Bardzo sprytne, dzięki. IMO, jest to najlepszy sposób na obejście tego w przypadku witryn WordPress z minimalną liczbą reguł włączenia. Ponadto wszelkie nowe wtyczki, motywy lub aktualizacje WP nie są usuwane ani dodawane bez Twojej wyraźnej zgody. Podczas korzystania z GitHub Desktop uważam, że .DS_Storepliki nie są ignorowane, ale za pośrednictwem wiersza poleceń nie stanowi to problemu. Aby obejść ten problem, musiałem przejść **/.DS_Storeponiżej wszystkich innych zasad.
Jibran
7
Mój wewnętrzny zakreślacz składni ma dziwną reakcję na tytuł twojego postu.
itsadok
3
Gracias! możesz także dodać białą listę do folderu w folderze ..! /some/folder/file.txt
PodTech.io
Wspaniale, użycie / * zamiast * rozwiązało wszystkie moje problemy, gdy powyższe odpowiedzi nie. Moje jedyne pytanie brzmi: jaka jest różnica między! / Folder a! / Folder / *? Jeśli korzystam z folderu! / Bez *, o ile wiem, nadal pobiera zmiany do wszystkich plików w folderze.
dallin,
1
@dallin nie ma różnicy. Jedna biała lista folder, a druga biała lista potomna tego folderu, co robi to samo. Jedynym problemem jest to folder lub rodzic files zawiera się na białej liście, zanim można się na białej liście, więc nie można zrobić /*następnie !/nested/folder/*(lub odpowiednik !/nested/folder), nie robiąc !/nested/lub !/nestedpierwszy! (i prawdopodobnie /nested/*pomiędzy). Sztuką do zapamiętania jest to, że jeśli umieszczasz na białej liście głęboko zagnieżdżony podfolder, musisz podbić dzieci w każdym podfolderze aż do góry, a te czarne listy zakończą się „gwiazdą ukośnika” ...
Ryan Taylor
75

Nieco bardziej szczegółowe:

Przykład: zignoruj ​​wszystko webroot/cache- ale zachowaj webroot/cache/.htaccess.

Zwróć uwagę na ukośnik (/) po cachefolderze:

WADY

webroot/cache*
!webroot/cache/.htaccess

PRACUJE

webroot/cache/*
!webroot/cache/.htaccess
Nik
źródło
Jeśli używasz VS Code, uważaj, aby nie odczytać kolorowania pliku po zastosowaniu go do folderu z rozszerzeniem .gitkeep, ponieważ nazwa folderu zmieni kolor na zielony, ale plik .gitkeep zmieni kolor na szary, tak jak wszystkie inne ignorowane pliki; .gitkeep będzie wyglądał na zignorowany, ale powinieneś zobaczyć, że po prawej stronie znajduje się „U”, co oznacza, że ​​zostało wykryte
OzzyTheGiant
55
# ignore these
*
# except foo
!foo
Suvesh Pratapa
źródło
28

Aby zignorować niektóre pliki w katalogu, musisz to zrobić w odpowiedniej kolejności :

Na przykład zignoruj ​​wszystko w folderze „application” oprócz index.php i folder „config” zwróć uwagę na kolejność .

Najpierw musisz zaprzeczyć, że chcesz.

WADY

application/*

!application/config/*

!application/index.php

PRACUJE

!application/config/*

!application/index.php

application/*

slatunje
źródło
38
Źle. Negujesz po „zignoruj ​​wszystko”.
Carlos
2
Nie daj się zwieść git statussprawdzeniu, czy zmiany .gitignoredziałają zgodnie z oczekiwaniami
Philippe Rathé
10
Jeśli git statusnie powie ci, na co patrzy, a co jest ignorowane, to skąd możesz wiedzieć, czy to działa?
Kris,
1
@kris Najpierw wyczyść pamięć podręczną git. Najpierw wykonaj „git rm --cached *”, a następnie „git add --all”, a następnie „git status” pokaże wszystkie nowe zmiany w gitignore.
Mark McCorkle
20

Możesz użyć, git config status.showUntrackedFiles noa wszystkie nieśledzone pliki zostaną przed tobą ukryte. Zobacz man git-configszczegóły.

Robert Munteanu
źródło
Jest to świetne, jeśli chcesz zatwierdzić tylko kilka plików z wielu!
Josh M.
16

Aby wykluczyć folder z .gitignore, można wykonać następujące czynności.

!app/

app/*
!app/bower_components/

app/bower_components/*
!app/bower_components/highcharts/

Spowoduje to zignorowanie wszystkich plików / podfolderów bower_componentsz wyjątkiem /highcharts.

Guy Baskin
źródło
14

Istnieje wiele podobnych pytań na ten temat, więc opublikuję to, co napisałem wcześniej:

Jedynym sposobem, w jaki mogłem to zrobić na mojej maszynie, było zrobienie tego w ten sposób:

# Ignore all directories, and all sub-directories, and it's contents:
*/*

#Now ignore all files in the current directory 
#(This fails to ignore files without a ".", for example 
#'file.txt' works, but 
#'file' doesn't):
*.*

#Only Include these specific directories and subdirectories and files if you wish:
!wordpress/somefile.jpg
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*

Zwróć uwagę, w jaki sposób musisz wyraźnie zezwalać na zawartość dla każdego poziomu, który chcesz uwzględnić. Więc jeśli mam podkatalogi 5 głęboko pod tematami, nadal muszę to przeliterować.

To jest z komentarza @ Yarin tutaj: https://stackoverflow.com/a/5250314/1696153

Były to przydatne tematy:

Też próbowałem

*
*/*
**/**

i **/wp-content/themes/**

lub /wp-content/themes/**/*

To też nie działało dla mnie. Dużo śladów i błędów!

Katie
źródło
2
Jest to jedyna metoda, która działa wyłącznie w celu uwzględnienia niektórych rozszerzeń plików. Co więcej, robi świetną sztukę ASCII: gist.github.com/Wolfgange3311999/91c671f5e4d3c56cf5a1
Matthew D. Scholefield
10

Miałem problem z podfolderem.

Nie działa:

/custom/*
!/custom/config/foo.yml.dist

Pracuje:

/custom/config/*
!/custom/config/foo.yml.dist
Fabian Picone
źródło
9

Próbowałem wszystkich odpowiedzi, jak podano tutaj powyżej, ale żadna nie działała dla mnie. Po przeczytaniu dokumentacji gitignore ( tutaj ) dowiedziałem się, że jeśli najpierw wykluczysz folder, nazwy plików w podfolderze nie będą indeksowane. Więc jeśli użyjesz wykrzyknika, aby dołączyć plik, nie zostanie on znaleziony w indeksie, a zatem nie zostanie uwzględniony w twoim kliencie git.

To był sposób na znalezienie rozwiązania. Zacząłem od dodania wyjątków dla wszystkich podfolderów w moim drzewie folderów, aby działało, co jest cholernie trudne. Potem mogłem skompresować szczegółową konfigurację do poniższej konfiguracji, co jest nieco sprzeczne z dokumentacją.

Działający .gitignore:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' subfolder
/Pro/3rdparty/*
!Pro/3rdparty/domain/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

W rezultacie widzę w moim kliencie git, że tylko dwa pliki w folderze Pro / 3rdparty / domain / modulename / są przygotowywane do następnego zatwierdzenia i właśnie tego szukałem.

A jeśli chcesz dodać do białej listy kilka podfolderów tego samego folderu, zgrupuj linie wykrzykników poniżej instrukcji wykluczenia w następujący sposób:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' & 'hosting' subfolders
/Pro/3rdparty/*
!Pro/3rdparty/domain/
!Pro/3rdparty/hosting/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

# Ignore the 'hosting' folder, except for the 'modulename' subfolder
Pro/3rdparty/hosting/*
!Pro/3rdparty/hosting/modulename/

W przeciwnym razie nie będzie działać zgodnie z oczekiwaniami.

Tim B.
źródło
Wreszcie odpowiedź, która zadziałała. Zastanawiam się, kiedy zrozumiem, jak działa .gitignore
David
8

Właśnie to zadziałało, chciałem zatwierdzić tylko jedną wtyczkę Cordova do repozytorium:

...
plugins/*
!plugins/cordova-plugin-app-customization
Dmitrij Sokurenko
źródło
8

Wiem, że jestem spóźniony na przyjęcie, ale oto moja odpowiedź.

Jak powiedział @Joakim, aby zignorować plik, możesz użyć czegoś takiego jak poniżej.

# Ignore everything
*

# But not these files...
!.gitignore
!someFile.txt

ale jeśli plik znajduje się w zagnieżdżonych katalogach, trudno jest ręcznie napisać reguły.

Na przykład, jeśli chcemy pominąć wszystkie pliki w gitprojekcie, ale nie w a.txtktórym znajduje się aDir/anotherDir/someOtherDir/aDir/bDir/cDir. W takim razie nasze .gitignorebędzie coś takiego

# Skip all files
*

# But not `aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt`
!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Powyższy .gitignoreplik pominie wszystkie katalogi i pliki oprócz!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Jak zapewne zauważyłeś, trudno jest zdefiniować te reguły.

Aby rozwiązać tę przeszkodę, stworzyłem prostą aplikację konsolową o nazwie git-do-not-ignore, która wygeneruje dla Ciebie reguły. Prowadziłem projekt w github ze szczegółową instrukcją.

Przykład użycia

java -jar git-do-not-ignore.jar "aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt"

Wynik

!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Istnieje również prosta wersja internetowa dostępna tutaj

Dziękuję Ci.

theapache64
źródło
7

Mam Jquery i Angular z altany. Bower zainstalował je

/public_html/bower_components/jquery/dist/bunch-of-jquery-files
/public_html/bower_components/jquery/src/bunch-of-jquery-source-files
/public_html/bower_components/angular/angular-files

Zminimalizowana jquery znajduje się w distkatalogu, a kątowy w angularkatalogu. Potrzebowałem tylko zminimalizowanych plików, aby zostać przydzielonym do github. Trochę ingerowałem w .gitignore i właśnie to udało mi się wyczarować ...

/public_html/bower_components/jquery/*
!public_html/bower_components/jquery/dist
/public_html/bower_components/jquery/dist/*
!public_html/bower_components/jquery/dist/jquery.min.js
/public_html/bower_components/angular/*
!public_html/bower_components/angular/angular.min.js

Mam nadzieję, że ktoś może uznać to za przydatne.

Mario Legenda
źródło
7

Oto jak to zrobiłem:

# Ignore everything
*

# Whitelist anything that's a directory
!*/

# Whitelist some files
!.gitignore

# Whitelist this folder and everything inside of it
!wordpress/wp-content/themes/my-theme/**

# Ignore this folder inside that folder
wordpress/wp-content/themes/my-theme/node_modules

# Ignore this file recursively
**/.DS_Store

Służy gig status -udo rekurencyjnego przeglądania pojedynczych plików w nieśledzonych katalogach - git statuszobaczysz tylko foldery, które mogą Cię oszukać, że wszystko w nich było śledzone

zok
źródło
5

Proste rozwiązanie, jeśli chcesz zignorować wszystko oprócz kilku plików i kilku folderów głównych :

/*
!.gitignore
!showMe.txt
!my_visible_dir

Magia jest w /*(jak opisano powyżej) ignoruje wszystko w folderze (głównym), ale NIE rekurencyjnie.

d.raev
źródło
4

Miałem też pewne problemy z negacją pojedynczych plików. Mogłem je zatwierdzić, ale moje IDE (IntelliJ) zawsze narzekało na ignorowane pliki, które są śledzone.

git ls-files -i --exclude-from .gitignore

Wyświetliłem dwa pliki, które wykluczyłem w ten sposób:

public/
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

W końcu to zadziałało dla mnie:

public/*
!public/typo3conf/
public/typo3conf/*
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

Kluczem była najpierw negacja folderu typo3conf/ .

Wydaje się również, że kolejność instrukcji nie ma znaczenia . Zamiast tego musisz jawnie zanegować wszystkie podfoldery, zanim będziesz mógł negować pojedyncze pliki w nim.

Folder !public/typo3conf/i zawartość folderu public/typo3conf/*to dwie różne rzeczy dla .gitignore.

Świetny wątek! Ten problem martwił mnie na chwilę;)

Armin
źródło
3

Do tej pory nic mi nie działało, ponieważ próbowałem dodać jeden słoik z biblioteki lib.

To nie zadziałało:

build/*
!build/libs/*
!build/libs/
!build/libs/myjarfile.jar 

To działało:

build/*
!build/libs
Manish Bansal
źródło
3

Mam to działa

# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib
raftaar1191
źródło
2

Miał podobny problem jak OP, ale żadna z 10 najbardziej pozytywnych odpowiedzi nie zadziałała .
W końcu dowiedziałem się, co następuje

Zła składnia:

*
!bin/script.sh

Prawidłowa składnia:

*
!bin
!bin/script.sh

Objaśnienie ze strony podręcznika gitignore :

Opcjonalny przedrostek „!” co neguje wzór; każdy pasujący plik wykluczony przez poprzedni wzór zostanie ponownie dołączony. Ponowne dołączenie pliku nie jest możliwe, jeśli katalog nadrzędny tego pliku jest wykluczony . Git nie wyświetla wykluczonych katalogów ze względu na wydajność, więc wszelkie wzorce w zawartych plikach nie mają wpływu, bez względu na to, gdzie są zdefiniowane.

Rozszerzony przykład:

drzewo $.

.
├── .gitignore
└── bin
    ├── ignore.txt
    └── sub
        └── folder
            └── path
                ├── other.sh
                └── script.sh

$ cat .gitignore

*
!.gitignore
!bin
!bin/sub
!bin/sub/folder
!bin/sub/folder/path
!bin/sub/folder/path/script.sh

$ git status --untracked-files --ignored

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        bin/sub/folder/path/script.sh

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
        bin/ignore.txt
        bin/sub/folder/path/other.sh

nothing added to commit but untracked files present (use "git add" to track)
frntn
źródło
1

Sens

# Ignore everything
*

# But not these files...
!script.pl
!template.latex

I prawdopodobnie obejmują:

!.gitignore

Odniesienie

Od https://git-scm.com/docs/gitignore :

Opcjonalny przedrostek „ !”, który neguje wzór; każdy pasujący plik wykluczony przez poprzedni wzór zostanie ponownie dołączony. Ponowne dołączenie pliku nie jest możliwe, jeśli katalog nadrzędny tego pliku jest wykluczony. Git nie wyświetla wykluczonych katalogów ze względu na wydajność, więc wszelkie wzorce w zawartych plikach nie mają wpływu, bez względu na to, gdzie są zdefiniowane. Umieść ukośnik odwrotny („ \”) przed pierwszym „ !” dla wzorów rozpoczynających się od literału „ !”, na przykład „ \!important!.txt”.

...

Przykład wykluczenia wszystkiego oprócz określonego katalogu foo/bar(zwróć uwagę /*- bez ukośnika, symbol wieloznaczny również wyklucza wszystko w środku foo/bar):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar
Will Cain
źródło
0

Wydaje mi się, że znalazłem coś, co zadziałało dla mnie, o czym nikt inny nie wspomniał.

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# And if you want to include a sub-directory and all sub-directory and files under it, but not all sub-directories
!subdir/
!subdir/**/*

Zasadniczo wydaje się, że neguje to ignorowanie podkatalogu, musisz mieć dwa wpisy, jeden dla samego podkatalogu, !subdir/a drugi dla wszystkich plików i folderów w nim zawartych!subdir/**/*

Didier A.
źródło