Kiedy używać początkowego ukośnika w gitignore

108

Staram się lepiej zrozumieć .gitignoreskładnię, w szczególności jeśli chodzi o https://github.com/github/gitignore gitignores.

Widzę, że początkowy ukośnik jest używany do dopasowania tylko nazw ścieżek względem lokalizacji .gitignorepliku (z http://git-scm.com/docs/gitignore ):

Początkowy ukośnik pasuje do początku nazwy ścieżki. Na przykład „/*.c” odpowiada „cat-file.c”, ale nie „mozilla-sha1 / sha1.c”.

Ale co się stanie, gdy usunę wiodący ukośnik? O ile zrozumiałem, są dwa przypadki:

  1. Jeśli wzorzec nie zawiera ukośnika (lub zawiera tylko ukośnik na końcu, co oznacza, że ​​powinien pasować do katalogu), wyszukiwanie odbywa się w całym drzewie katalogów. Na przykład, wzór dir/będzie pasował <root>/dir, <root>/a/dir, <root>/a/b/c/.../dir, itd., Gdzie <root>jest lokalizacja .gitignorepliku.
  2. Jeśli wzorzec zawiera ukośnik, który nie znajduje się na końcu (nie jest to ostatni znak), to jest dopasowywany tylko z nazwami ścieżek względem .gitignorelokalizacji pliku.

Oto przykłady, które zrobiłem, aby sprawdzić to zachowanie:

# Directory structure:
<root>
├─ dir/
│   └─ test
├─ src/
│   ├─ dir/
│   │   └─ test
test file is there only because Git does not track empty directories.

Pierwszy test:

# .gitignore
dir/

# git status
nothing to commit

Więc Git ignoruje oba dirkatalogi. Jest to zgodne z przypadkiem numer 1: wzorzec nie ma ukośników (z wyjątkiem końcowego), więc Git obserwuje całe drzewo katalogów, ignorując wszystko, co pasuje do wzorca.

Drugi test:

# .gitignore
/dir/

# git status
Untracked files:
    src/

Tutaj Git ignoruje tylko dirkatalog bezpośrednio pod katalogiem głównym, dzięki wiodącemu ukośnikowi we wzorcu.

Trzeci test:

# .gitignore
dir/*

# git status
Untracked files:
    src/

Jest to zgodne z przypadkiem numer 2: wzorzec ma w sobie ukośnik, więc jest traktowany jako ścieżka zaczynająca się od katalogu głównego.

Teraz czas na prawdziwe pytanie. Rozważmy ten plik gitignore : kiedy downloader/na przykład ignorują katalog , czy w rzeczywistości nie ignorują każdego downloaderkatalogu znalezionego w całym drzewie katalogów? Właśnie o tym myślę od czasu tego, co widziałem wcześniej o działaniu Git.

Więc jeśli zdarzy mi się mieć niestandardowy moduł z downloaderkatalogiem w środku, czy zostanie on nieoczekiwanie zignorowany, podobnie jak zwykły w katalogu głównym Magento? To trochę retoryczne pytanie, ponieważ tak naprawdę już mi się przydarzyło, powodując naprawdę trudny do znalezienia błąd.

Tak więc w .gitignorepliku Magento (do którego odnoszę się tylko jako przykład, przy okazji) wiele wzorców zawiera ukośniki, więc są one poprawnie dopasowywane do nazw ścieżek zaczynających się od katalogu głównego, ale jest kilka przypadków, takich jak downloader/czy errors/tamto , jeśli się nie mylę, są potencjalnie niebezpieczne i prawdopodobnie należy je zmienić na /downloader/i /errors/.

Jako bardziej ogólne pytanie, czy zawsze powinienem używać początkowego ukośnika dla wzorców niezawierających ukośników (z wyjątkiem końcowego), gdy chcę wybrać nazwę ścieżki jawnie zaczynającą się od katalogu głównego i nie używać jej dla wzorców zawierających ukośniki, czy też powinienem zawsze używaj początkowego ukośnika dla jasności? Co o tym myślisz?

Dziękuję za przeczytanie i przepraszam za długi post.

swahnee
źródło
8
Świetne pytanie i naprawdę fajne wyjaśnienie. Mnie też to przeszkadzało, a twoje badania wyjaśniły mi sprawę. Po przeczytaniu tego powiedziałbym, że dobrą praktyką jest zawsze rozpoczynanie ścieżek ukośnikiem, jeśli mają zaczynać się od korzenia, dzięki temu intencja jest bardziej oczywista.
Martinsos
4
Dzięki :) Zgadzam się z twoją uwagą dotyczącą używania ukośników, aby wyraźniej wyrazić intencje.
swahnee
8
Powinno to być częścią dokumentacji .gitignore. O wiele łatwiejsze do zrozumienia!
rmorrin
Bardzo chciałbym zobaczyć ten wspaniały post podzielony na sekcje pytań i odpowiedzi ...
Barett

Odpowiedzi:

25

Chciałem tylko podsumować, aby możliwe było szybkie odniesienie w przyszłości - wiodący ukośnik zakotwicza dopasowanie do korzenia. Zatem w poniższym przykładzie, bez ukośnika, symbol wieloznaczny wykluczałby również wszystko w foo, ponieważ zajmowałby *i przesuwał się rekurencyjnie w dół drzewa. Jednak w programie /*wyklucza wszystko oprócz folderu foo i jego zawartości:

$ cat .gitignore
/*
!/foo
przesilenie 333
źródło
24

Odpowiedziałeś całkowicie na swoje pytanie. Jeśli przyjrzysz się bliżej repozytorium github / gitignore, zobaczysz, że większość plików używa niespójnych reguł dotyczących pisania wzorców; najprawdopodobniej większość z nich pochodziła od ludzi, którzy nie zadali sobie trudu, aby czytać dokumentację ani testować rzeczy tak jak ty.

Więc jeśli to pomoże: masz rację, bądź pewny siebie.

Jeśli zauważysz błędy we wspólnych projektach, takich jak ten, nie wahaj się i podziel się swoją wiedzą. Istnieje nawet precedens, jeśli musisz dalej budować swoją pewność siebie.

tne
źródło