.gitignore Sözdizimi: bin - bin / - bin / * - bin / **


90

Ekleme arasındaki fark nedir bin, bin/, bin/*ve bin/**benim .gitignore dosyasında? Ben kullanıyorum bin/, ama şu an başka .gitignore dosyaları (içinde tutulması dosyası çift ve tek yıldızı bile beraber böyle kullanılır: tmp/**/*Ne bununla kalmış?) İlk iki desenler de yaygın sıra kullanıldığını görüyoruz. Birisi lütfen üçü arasındaki farkları açıklayabilir mi?


4
@unutbu: Görünüşe göre bu soru için kabul edilen cevap tartışmalı. En iyi yorumlardan biri, cevabın aslında tam bir efsane olduğunu iddia ediyor.
chandsie

Davranış tamamen kılavuz sayfasında belirtilmiştir ve eminim buralarda tüm bu bilgileri içeren bir soru / cevap (veya on) vardır.
Cascabel

3
**
Şununla

Yanıtlar:


85

bin'bin' adlı herhangi bir dosya veya dizinle eşleşir .

bin/'bin' adlı herhangi bir dizinle eşleşir , bu da aslında Git dizinleri tek başına izlemediği için tüm içeriği anlamına gelir.

bin/*herhangi birindeki tüm dosya ve dizinlerle eşleşir bin/. Bu Git otomatik olarak alt dizinlerinde tüm dosyaları bulma önler ancak, bir derseniz bin/fooalt dizin oluşturulur, bu kural olacak değil maç foo'ın içeriğini.

bin/**herhangi bir bin/dizindeki ve tüm alt dizinlerindeki tüm dosya ve dizinlerle eşleşir .

Kurallar arşiv köküne bağlı olmadığından ve dosya sistemi ağacının herhangi bir yerinde geçerli olduğundan "herhangi biri" sözcüğü burada kritiktir . Kurallara, yalnızca amaçlananla eşleşmek için sistemin kökü değil, havuzun kökü anlamına gelen bir /(veya !/yok saymamak) ile başlamalısınız .

UYARI: Sen gerektiğini asla gibi kuralları kullanabilirsiniz dir/*, /dir/**vb yalnız da bu dizinin içinde var bir şey un-görmezden sürece . Atla yıldız işareti veya kalıcı olarak çok veri kaybedebilir belli halinin çağrıları gelen git gc, git stashve daha fazlası.

Ne yapmam gerektiğini gerçekten bilmiyorum tmp/**/*. Başlangıçta, alt dizinlerindeki dosyaları eşleştirmek için kullanılabileceğini düşündüm, tmp/ancak doğrudan tmp/kendi içinde mevcut olan dosyaları değil . Ancak basit bir test, bunun içindeki tüm dosyaları yoksaydığını gösteriyor gibi görünüyor tmp/.


10
açıklığa kavuşturmak için, bin/ve arasındaki fark bin/**nedir?
chandsie

1
Sanıyorum bin/, oysa bin dizini yok sayacak bin/**bin dizini dahil ancak herhangi içeriğinin olacak
Robin Winslow

1
Bu, Siddhartha'nın cevabı ile tutarsız görünüyor. Cevabını yola çıkarak, bin/oysa (tüm alt dizinleri ve dosyaları da dahil) dizinin kendisini yok sayacaktır bin/**tüm bin dizinindeki dosyaları ve alt dizinleri, ancak göz ardı eder değil bin dizini kendisi. Doğru olsun ya da olmasın, emin değilim.
Christopher Berman

3
bin / dizinindeki tüm dosyaları izlemek, ancak alt dizinlerindeki tüm dosyaları göz ardı etmek istiyorsanız, şunları yapabilirsiniz (sonraki satırlarda) bin/** \n !bin/*(mini Markdown'da bir satır
kırılmasını

9
Bu cevap pek çok yönden yanlış. İlk olarak git, dizinlerin kaydını tutmaz, bu nedenle bir .gitignore girişi yalnızca dizin içeriğiyle eşleşebilir, asla böyle bir dizinle eşleşmez. İkincisi, binmaçları hem adlı bir dosya bin ve içeriğini binklasörüne. Üçüncü olarak, alt dizinlerindeki tüm dosyalarla bin/* eşleşir . Bunu test ettiniz mi?
ThomasR

46

binve bin/yalnızca ikincisi yalnızca bir dizinle eşleşecek olması bakımından farklılık gösterir.

bin/**/*bin/**(1.8.2'den beri, @ VonC'nin cevabına göre) ile aynıdır .

Bir saat kadar saçımı yırtıp atarak geçirdiğim aldatıcı olan, bu bin/ve tamamen aynı bin/**değil ! Öncekiler dizini bir bütün olarak görmezden geldiğinden ve ikincisi içindeki dosyaların her birini görmezden geldiğinden ve neredeyse tüm durumlarda git dizinleri umursamadığından, normalde bir fark yoktur. Ancak, bir alt yolu yok saymak için kullanmayı denerseniz , ana dizini yok sayarsanız git (ahem) 'in onu yok saydığını göreceksiniz! (yine dizin içeriği yerine)!

Bu, örnek olarak en açık olanıdır, bu nedenle yeni başlatılan bir depo için şu şekilde kurulur:

$ cat .gitignore
ignored-file
or-dir
dir-only/
!dir-only/cant-reinclude
dir-contents/**
!dir-contents/can-reinclude

$ mkdir or-dir dir-only dir-contents

$ touch file ignored-file or-dir/ignored-file dir-only/cant-reinclude dir-contents/can-reinclude

Aşağıdaki izlenmeyen dosyalar var:

$ git ls-files --other
.gitignore
dir-contents/can-reinclude
dir-only/cant-reinclude
file
ignored-file
or-dir/ignored-file

Ancak aşağıdaki dosyaların göz ardı edilmediğini görebilirsiniz:

$ git ls-files --other --exclude-standard
.gitignore
dir-contents/can-reinclude
file

Ve eklemeye çalışırsanız, şunları elde edersiniz:

$ git add dir-only/cant-reinclude
The following paths are ignored by one of your .gitignore files:
dir-only/cant-reinclude
Use -f if you really want to add them.
fatal: no files added

Bu davranışı bir hata olarak görüyorum. (Hepsi açık git version 1.8.4.msysgit.0)


1
+1, gerçekten. Davranış beklenmedik göründüğünden, bununla ilgili gerçek bir hata raporu doldurmayı düşünmelisiniz.
chandsie

1
Tam olarak benim kullanım durumum. Teşekkürler!
Sebastian Graf

3
Farklı davranış dir/ve dir/**yeniden. ile göz ardı edilmesinin !nedeni "Bir dosyanın üst dizini dışarıda bırakılırsa bir dosyayı yeniden dahil etmek mümkün değildir" [kaynak ]. Kafa karıştırıcı, ancak performans nedeniyle yapıldı. İlgili bir SO sorusuna bakın .
tanius

23

Git'in dizinleri değil yalnızca dosyaları izlediğini unutmayın. Bu nedenle bir dizin eklemek mümkün değildir, yalnızca içeriğini eklemek mümkündür .

.gitignoreBununla birlikte, bağlamında git, dizinleri anlıyor gibi davranıyor çünkü

Bir dosyanın üst dizini dışarıda bırakılırsa, bir dosyayı yeniden dahil etmek mümkün değildir.
https://git-scm.com/docs/gitignore#_pattern_format

Dışlama kalıpları için bu ne anlama geliyor? Onları ayrıntılı olarak inceleyelim:

bin

Bu görmezden geliyor

  • adlı dosyalar bin.
  • adlı klasörlerin içeriği bin

Göz ardı edilen bindosya ve klasörleri sonraki !girişleri ekleyerek beyaz listeye ekleyebilirsiniz, ancak adlı klasörlerin içeriğini beyaz listeye alamazsınız .bin

bin

!bin/file_in_bin # has no effect, since bin/ is blacklisted!
!bin/* # has no effect, since bin/ is blacklisted!
!file_in_bin # has no effect, since bin/ is blacklisted!

!bin # this works

bin/

Yukarıdaki ile aynı, ancak adı verilen dosyalarla eşleşmiyor bin. Sona eklemek /, git'e yalnızca dizinlerle eşleşmesini söyler.

bin/*

Bu görmezden geliyor

  • adlı bir klasörde bulunan dosyalarbin
  • adlı klasörlerin doğrudan alt klasörlerinin içeriği bin
bin/*  # blacklists bin/file_in_bin and bin/subfolder/

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted!
!bin # whitelists files named bin/bin, since bin/ itself is not blacklisted
!bin/ # has no effect, since bin/ itself is not blacklisted


!bin/file_in_bin # works since bin/ itself is not blacklisted
!file_in_bin # works too
!bin/subfolder # works (so implicitly whitelists bin/subfolder/file_in_sub)
!bin/subfolder/ # works just as well
!bin/* # works for file_in_bin and subfolder/

bin/**

Bu görmezden geliyor

  • içeriği bin
  • içindeki alt klasörlerin içeriği (herhangi bir iç içe geçme düzeyi) bin
bin/**  # blacklists bin/file_in_bin and
        # bin/subfolder/ and bin/subfolder/file_in_sub and
        # bin/subfolder/2/ and bin/subfolder/2/file_in_sub_2

!bin/subfolder/file_in_sub # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/ # has no effect, since bin/subfolder is blacklisted
!bin/subfolder/2/file_in_sub_2 # has no effect, since bin/subfolder is blacklisted

!bin/subfolder # works only in combinations with other whitelist entries,
               # since all contents of subfolder are blacklisted (1)

!bin/file_in_bin # works since bin itself is not blacklisted
!bin/* # works for file_in_bin and subfolder; see (1)

9

Yeni bir depo yaptım ve bazı şeyler denedim. İşte sonuçlarım:

YENİ SONUÇLAR

git sürüm 2.10.1.windows.1

  1. Neredeyse boş depoyu başlatın. Sadece README dosyası
  2. Doldurma binderin dizin birkaç katmanları
    • bin.txt
    • Test.txt
    • bin/a/b/bin.txt
    • bin/a/b/Test.txt
    • bin/a/bin/bin.txt
    • bin/a/bin/Test.txt
    • bin/a/bin.txt
    • bin/a/Test.txt
    • bin/bin.txt
    • bin/Test.txt
  3. binGitignore'a ekle : Sonuçlar
    • binDizinin altındaki (ve daha derin) her şey artık yok sayılıyor
    • Kök seviyesi yok sayılmaz (/bin.txt ve /Test.txt hala gösteriliyor)
  4. Düzenleme biniçin bin/gitignore içinde: Sonuçlar
    • Değişiklik yok
  5. Düzenleme bin/içinbin/*
    • Değişiklik yok
  6. Düzenleme bin/*içinbin/**
    • Değişiklik yok
  7. Düzenleme bin/**içinbin/**/
    • bin/bin.txtve bin/Test.txtartık göz ardı edilmiyor
  8. Düzenleme bin/**/içinbin/**/*
    • bin/bin.txtve bin/Test.txtgörmezden gelinmeye geri döndü

ESKİ SONUÇLAR

git sürümü: 2.7.0.windows.1

  1. Neredeyse boş depoyu başlatın. Sadece README dosyası
  2. Doldurma binderin dizin birkaç katmanları
    • bin/a/b/Test.txt
    • bin/a/bin/Test.txt
    • bin/a/Test.txt
    • bin/Test.txt
  3. binGitignore'a ekle : Sonuçlar
    • binDizinin altındaki (ve daha derin) her şey artık yok sayılıyor
  4. Düzenleme biniçin bin/gitignore içinde: Sonuçlar
    • binDizinin altındaki (ve daha derin) her şey hala göz ardı ediliyor (değişiklik yok)
  5. Düzenleme bin/içinbin/*
    • binDizinin altındaki (ve daha derin) her şey hala göz ardı ediliyor (değişiklik yok)
  6. Düzenleme bin/*içinbin/**
    • binDizinin altındaki (ve daha derin) her şey hala göz ardı ediliyor (değişiklik yok)
  7. Düzenleme bin/**içinbin/**/
    • bin/Test.txt artık göz ardı edilmiyor
  8. Düzenleme bin/**/içinbin/**/*
    • binDizinin altındaki (ve daha derin) her şey tekrar göz ardı edilir

1
Bu iyi bir test, text.txt'yi bin.txt olarak yeniden adlandırmanın bazı temel farklılıkları daha iyi göstereceğini düşünüyorum. Bunu yaparsan, bu cevaba oy veririm.
Matt Johnson

@MattJohnson Doğru ... ne yazık ki şu anda daha yeni bir git sürümüne değilim
Joe Phillips

@MattJohnson Sonunda buna alıştım
Joe Phillips

8

Git1.8.2 sürüm notunda şu anda bahsettiğinden ' **', bir alt dizinle ( **/bar) birleştirildiğinde varsayılan davranışından farklı olmalıdır :

.gitignoreVe .gitattributesdosyalarındaki kalıplar, **/0 veya daha fazla alt dizin düzeyiyle eşleşen bir kalıp olarak sahip olabilir .

Örneğin , " " kendisinde veya " " alt dizininde " foo/**/bar" bar"ile " "eşleşir .foofoo


Hatırlanması gereken kural (ve bu sözdiziminin ardındaki niyet farkını anlamaya yardımcı olan) şudur:

Bir dosyanın üst dizini dışarıda bırakılırsa, bir dosyayı yeniden dahil etmek mümkün değildir.


Tipik olarak, dosyaları göz ardı etme klasörünün f alt klasöründen çıkarmak istiyorsanız, şunları yaparsınız:

f/**
!f/**/
!f/a/sub/folder/someFile.txt

Yani:

  • İlk kural olsaydı f/, klasör f/göz ardı edilir ve aşağıdaki kuralların fönemi olmazdı.
  • f/**ile aynı şeyi yapın f/, ancak tüm alt öğeleri (dosyalar ve alt klasörler) göz ardı edin .
    Bu size alt klasörler (gitignore dışında tutmak) beyaz listesi fırsatı verir: !f/**/.
  • Tüm falt klasörler göz ardı edilmediğinden , bir dosyayı ( !f/a/sub/folder/someFile.txt) hariç tutmak için bir kural ekleyebilirsiniz.

Bu soruya nasıl cevap veriyor?
ThomasR

0

Arasında başka bir fark var bin/*ve bin/.

bin/eşleşir foo/bin/test.txt(beklendiği gibi), ancak bin/*eşleşmiyor, bu garip görünüyor, ancak belgeleniyor: https://git-scm.com/docs/gitignore

"Documentation / *. Html", "Documentation / git.html" ile eşleşir ancak "Documentation / ppc / ppc.html" veya "tools / perf / Documentation / perf.html" ile eşleşmez.

Bunun nedeni şu kurallar gibi görünüyor:

  • Desen eğik çizgiyle biterse, aşağıdaki açıklama amacıyla kaldırılır…

  • Kalıp bir eğik çizgi / içermiyorsa, Git bunu bir kabuk glob kalıbı olarak ele alır ve .gitignore dosyasının konumuna göre yol adına göre bir eşleşme olup olmadığını denetler…

  • Aksi takdirde Git, kalıbı FNM_PATHNAME bayrağıyla fnmatch (3) tarafından tüketime uygun bir kabuk glob olarak ele alır…

Dolayısıyla, desen bir eğik çizgiyle biterse, eğik çizgi kaldırılır ve bir kabuk glob deseni olarak kabul edilir, bu durumda bineşleşir foo/bin/test.txt. /*İle biterse , eğik çizgi kaldırılmaz ve alt dizinlerde eşleşmeyen fnmatch'e iletilir.

Bununla birlikte, aynı durum için geçerli değildir foo/bin/ve foo/bin/*çünkü sondaki eğik çizgiyi kaldırdıktan sonra bile foo/bin/, yine de bir eğik çizgi içerir, bu nedenle bir glob değil, bir fnmatch deseni olarak değerlendirilir. Yani eşleşmeyecekbar/foo/bin/test.txt

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.