.Gitignore dışlama kuralları gerçekte nasıl çalışır?


150

Gitignore problemini büyük bir dizin yapısında çözmeye çalışıyorum, ancak sorumu basitleştirmek için aşağıdaki kısma indirdim.

Yepyeni bir git deposunda iki dosyanın (foo, bar) aşağıdaki dizin yapısına sahibim (şu ana kadar taahhüt yok):

a/b/c/foo
a/b/c/bar

Açıkçası, bir 'git durumu -u' şunu gösterir:

# Untracked files:
...
#       a/b/c/bar
#       a/b/c/foo

Yapmak istediğim şey, a / b / c içindeki her şeyi yok sayan ancak 'foo' dosyasını yok saymayan bir .gitignore dosyası oluşturmak.

Bir .gitignore oluşturursam, şöyle:

c/

Sonra bir 'git status -u', hem foo hem de bar'ı yok sayılmış olarak gösterir:

# Untracked files:
...
#       .gitignore

Beklediğim gibi.

Şimdi foo için bir dışlama kuralı eklersem, şöyle:

c/
!foo

Gitignore kılavuzuna göre, bunun işe yaramasını bekliyorum. Ama değil - hala foo'yu görmezden geliyor:

# Untracked files:
...
#       .gitignore

Bu da çalışmıyor:

c/
!a/b/c/foo

Bu da yapmaz:

c/*
!foo

Verir:

# Untracked files:
...
#       .gitignore
#       a/b/c/bar
#       a/b/c/foo

Bu durumda, foo artık yok sayılmasa da, bar da göz ardı edilmez.

.Gitignore'daki kuralların sırası da önemli görünmüyor.

Bu da beklediğim şeyi yapmıyor:

a/b/c/
!a/b/c/foo

Bu hem foo hem de bar'ı görmezden geliyor.

İşe yarayan bir durum, a / b / c / .gitignore dosyasını oluşturup oraya koymamdır:

*
!foo

Ancak bununla ilgili sorun şu ki, sonunda a / b / c altında başka alt dizinler olacak ve her birine ayrı bir .gitignore koymak istemiyorum - 'proje tabanlı' .gitignore oluşturmayı umuyordum. her projenin en üst dizininde yer alan ve tüm 'standart' alt dizin yapısını kapsayan dosyalar.

Bu da eşdeğer görünüyor:

a/b/c/*
!a/b/c/foo

Bu, elde edebileceğim "çalışmaya" en yakın şey olabilir, ancak tam göreceli yolların ve açık istisnaların belirtilmesi gerekir; bu, farklı düzeylerde çok sayıda "foo" adında dosyam varsa, bu bir acı olacaktır. alt dizin ağacının.

Her neyse, ya dışlama kurallarının nasıl çalıştığını tam olarak anlamıyorum ya da dizinler (joker karakterler yerine) yok sayıldığında - a / ile biten bir kurala göre - hiç çalışmıyorlar.

Biri lütfen buna ışık tutabilir mi?

Gitignore'un bu beceriksiz kabuk tabanlı sözdizimi yerine normal ifadeler gibi mantıklı bir şey kullanmasını sağlamanın bir yolu var mı?

Bunu Cygwin / bash3 üzerinde git-1.6.6.1 ve Ubuntu / bash3 üzerinde git-1.7.1 ile kullanıyorum ve gözlemliyorum.



5
Mükemmel yazılmış soru! Denediğiniz vaka sayısı, benzer vakamda neyi yanlış yaptığımı anlamama gerçekten yardımcı oldu. Tanrıya şükür, bugün uzun zamandır arıyordum.
Alex G

Yanıtlar:


158
/ABC/*
! foo

Benim için çalışıyor gibi görünüyor (Linux'ta git 1.7.0.4). Bu *önemlidir, çünkü aksi halde dizindeki dosyalar yerine dizinin kendisini görmezden gelirsiniz (böylece git içeriye bakmaz) (dışarıda bırakmaya izin verir).

Hariç tutulanları "ama bunu değil", "ama şunu dahil et" - "bu dizini yok sayın ( /a/b/c/) ama bunu yapma ( foo)" çok mantıklı değil; "bu dizindeki ( /a/b/c/*) tüm dosyaları yoksay ama bu ( foo) yok". Man sayfasını alıntılamak için:

İsteğe bağlı bir önek! kalıbı olumsuzlayan; önceki bir kalıp tarafından hariç tutulan eşleşen herhangi bir dosya tekrar dahil edilecektir.

başka bir deyişle, dosyanın yeniden dahil edilebilmesi için zaten dışlanmış olması gerekir. Umarım bu biraz ışık tutar.


Evet, verdiğiniz örnek benim için de iyi çalışıyor. Sorun şu ki / a / b / *, foo c içindeyse çalışmıyor, bu da c altındaki çeşitli alt dizinlerde birden çok foo dosyam varsa (örn. D /, e /, f / g / h /, i / j /, vb.) o zaman '! foo' olumsuzlama kuralı bunları yakalayamaz.
Davida

1
@meowsqueak Gerçekten olmayacak. / A / b / * 'yi görmezden gelirseniz, foo'nun içinde bulunabileceği bir dizin yoktur! / A / b altındaki dizin ağacının tamamını yok saymaya çalışıyorsanız, ancak ağacın herhangi bir yerinde olabilecek "foo" adlı herhangi bir dosyayı dahil ediyorsanız, bunun .gitignore kalıplarıyla yapılabileceğini sanmıyorum: \
Chris

Aslında bu benim için neden işe yaramadığını açıklayabilir - aşağıdaki kurallar çalışmıyor: "/ a / b / *", "! C / foo". Bu işe yaradıysa, bir sorun olmayabilir.
Davida

5
".Gitignore kalıplarıyla yapılabileceğini sanmıyorum" - Maalesef haklı olduğunu düşünüyorum.
Davida

@meowsqueak Muhtemelen görmezden gelebilir /a/b/cve ardından git add --forceeşleşen herhangi bir dosyaya ön işleme veya başka bir şey yazabilirsiniz
Chris

24

Benzer bir durumum var, çözümüm şuydu:

/a/**/*
!/a/**/foo

**Doğru okursam, rastgele sayıda ara dizin için işe yarayacaktır .


6

bu .gitignore man sayfasından kesinlikle anlaşılmamaktadır. Bu çalışıyor:

*
!/a
!/a/b
!/a/b/c
!/a/b/c/foo

# don't forget this one
!.gitignore

Chris'in bahsettiği gibi, dışarıda bırakıldığında bir dizin açılmıyor bile. Dolayısıyla, * ancak bazı dosyaları görmezden gelebilmek istiyorsanız, bu dosyaların yolunu yukarıdaki gibi oluşturmanız gerekir. Benim için bu uygundur, çünkü bir kitaplığın 1 dosyası üzerinde kod incelemesi yapmak istiyorum ve daha sonra başka bir tane yapmak istersem onu ​​eklerim ve diğer her şey göz ardı edilir.


6

İşte başka bir seçenek:

*
!/a*
!/a/*
!/a/*/*
!/a/*/*/*

Bu, her dosya ve dizini göz ardı eder, ancak bir.


5

Daha genel bir kayda göre, git1.8.2 içerecektir yama (ayrıca onun v4 de , bazı yığın taşması soruya tarafından istendiğinde itibaren) Adam Kuleler hangi belirleme hakkında gitignoregerçekte dosyayı görmezden kural.

Git1.8.2 sürüm notlarına ve " gitignore kuralı dosyamı yok sayan " SO sorusuna bakın :
bu komut olacaktır git check-ignore.


1
Bu bilgiyi yayınladığınız için teşekkürler. check-ignoreayrıca , eğer durum buysa, hangi kuralın dosyanızın göz ardı edilmesini engellediğini söyleyecektir .
Adam Spiers

@AdamSpiers kulağa hoş geliyor. Onunla kesinlikle oynamak zorunda kalacağım.
VonC
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.