.गरिग्नोर सिंटेक्स: बिन बनाम बिन / बनाम बिन / * बनाम बिन / **


89

जोड़ने में क्या अंतर है bin, bin/, bin/*और bin/**मेरी .gitignore फ़ाइल में? मैं उपयोग कर रहा हूं bin/, लेकिन अन्य .gitignore फ़ाइलों को देख रहा हूं ( ग्रहण फ़ाइल में डबल और सिंगल स्टार को एक साथ इस तरह से भी उपयोग किया जाता है: tmp/**/*इसके साथ क्या हो रहा है?) मैं देखता हूं कि पहले दो पैटर्न भी व्यापक रूप से उपयोग किए जाते हैं। क्या कोई कृपया तीनों के बीच अंतर बता सकता है?


4
@unutbu: उस प्रश्न के लिए स्वीकृत उत्तर स्पष्ट रूप से विवादित है। शीर्ष टिप्पणियों में से एक का दावा है कि उत्तर वास्तव में एक पूर्ण मिथक है।
chandsie

व्यवहार पूरी तरह से मैनपेज में निर्दिष्ट है, और मुझे यकीन है कि यहाँ (या दस) के आसपास एक प्रश्न / उत्तर है जिसमें वह सभी जानकारी शामिल है।
कैस्केबेल

3
के संबंध में **: stackoverflow.com/questions/1470572/…
Cascabel

जवाबों:


84

bin'बिन' नाम की किसी भी फाइल या निर्देशिका से मेल खाता है ।

bin/'बिन' नाम की किसी भी निर्देशिका से मेल खाता है , जिसका प्रभाव इसकी सभी सामग्रियों से है क्योंकि गिट अकेले निर्देशिका को ट्रैक नहीं करता है।

bin/*सीधे किसी भी फाइल और निर्देशिकाओं से मेल खाता है bin/। यह Git को अपने उपनिर्देशिकाओं में स्वचालित रूप से किसी भी फ़ाइल को खोजने से रोकता है, लेकिन अगर, bin/fooमान लें कि एक उपनिर्देशिका बनाई गई है, तो यह नियम सामग्री से मेल नहीं खाएगा foo

bin/**किसी भी bin/डायरेक्टरी और उसके सभी उपनिर्देशिकाओं में सभी फाइलों और निर्देशिकाओं से मेल खाता है ।

शब्द "कोई भी" यहां महत्वपूर्ण है क्योंकि नियम रिपॉजिटरी रूट के सापेक्ष नहीं हैं और फाइलसिस्टम ट्री में कहीं भी लागू होते हैं । आपको नियमों को /(या !/अन-इग्नोर करने के लिए) से शुरू करना चाहिए, जिसका अर्थ है रिपॉजिटरी की जड़, सिस्टम की जड़ नहीं, केवल उसी उद्देश्य से मेल खाने के लिए।

चेतावनी: आप चाहिए कभी नहीं की तरह नियमों का उपयोग dir/*, /dir/**अकेले आदि जब तक आप भी कुछ ऐसा है जो कि निर्देशिका के अंदर मौजूद है अनदेखा करना । न आना तारांकन या आप स्थायी रूप से डेटा का एक बहुत खो सकता है कुछ के आमंत्रण से git gc, git stashअधिक से।

मैं वास्तव में नहीं जानता कि क्या tmp/**/*करना है। मैंने शुरू में सोचा था कि इसका उपयोग फाइलों को उप-निर्देशिका में मेल करने के लिए किया जा सकता है, tmp/लेकिन फाइलों को सीधे tmp/अपने आप में मौजूद नहीं । लेकिन एक साधारण परीक्षण से लगता है कि यह सभी फाइलों को नजरअंदाज करता है tmp/


10
बस स्पष्ट करने के लिए, के बीच क्या फर्क है bin/और bin/**?
chandsie

1
मुझे संदेह है bin/कि बिन निर्देशिका को नजरअंदाज किया जाएगा, जबकि बिन निर्देशिका bin/**को शामिल किया जाएगा , लेकिन इसकी कोई भी सामग्री नहीं
रॉबिन विंसलो

1
यह सिद्धार्थ के जवाब से असंगत लगता है। जवाब से रेखाचित्र, bin/निर्देशिका ही (सभी उप-निर्देशिका और फ़ाइलों सहित) पर ध्यान नहीं देगा, जबकि bin/**बिन निर्देशिका में सभी फाइलों और उसके उप-निर्देशिका, लेकिन ध्यान नहीं देगा नहीं बिन निर्देशिका ही। यह सटीक है या नहीं, मैं अनिश्चित हूं।
क्रिस्टोफर बर्मन

3
ध्यान दें, यदि आप बिन / निर्देशिका में सभी फ़ाइलों को ट्रैक करना चाहते हैं, लेकिन इसकी उपनिर्देशिकाओं की सभी फ़ाइलों को अनदेखा करते हैं, तो आप (बाद की तर्ज पर) bin/** \n !bin/*कर सकते हैं (क्योंकि मैं नहीं देख सकता कि मिनी-
मार्कडाउन में लाइनब्रेक

9
यह जवाब कई मायनों में गलत है। सबसे पहले, गिट निर्देशिकाओं का ट्रैक नहीं रखता है, इसलिए एक .itignore प्रविष्टि केवल निर्देशिका सामग्री से कभी भी मेल खा सकती है, जैसे कि निर्देशिका कभी नहीं। दूसरा, नाम की फ़ाइल और फ़ोल्डर की सामग्री दोनों सेbin मेल खाता है । तीसरा, अपने उपनिर्देशिकाओं में किसी भी फाइल से मेल खाता है । क्या आप लोगों ने भी इसका परीक्षण किया था? bin binbin/*
थॉमस

46

binऔर bin/केवल इसमें भिन्नता है कि उत्तरार्द्ध केवल एक निर्देशिका से मेल खाएगा।

bin/**/*के रूप में ही है bin/**(जाहिरा तौर पर 1.8.2 के बाद से, @ VonC के जवाब के अनुसार)।

मुश्किल एक, कि मैं सिर्फ एक घंटे बिताता हूं या अपने बालों को बाहर रगड़ता हूं, यह वही है bin/और काफी समान bin/**नहीं हैं ! चूंकि पहले पूरी तरह से निर्देशिका को अनदेखा करता है, और बाद वाला इसके भीतर की प्रत्येक फ़ाइल को अनदेखा करता है, और लगभग सभी मामलों में गिट निर्देशिकाओं के बारे में परवाह नहीं करता है, आमतौर पर कोई अंतर नहीं होता है। हालाँकि, यदि आप एक सबपथ को अनदेखा करने के लिए उपयोग करने का प्रयास करते हैं , तो आप पाएंगे कि गिट (अहम) ने इसे अनदेखा कर दिया यदि आपने मूल निर्देशिका को अनदेखा कर दिया! (फिर, निर्देशिका सामग्री के बजाय)!

यह उदाहरण द्वारा स्पष्ट है, इसलिए एक नए इनिट-एड रिपॉजिटरी के लिए सेट किया गया है:

$ 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

निम्न अनुपलब्ध फ़ाइलें मौजूद हैं:

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

लेकिन आप देख सकते हैं कि निम्नलिखित फ़ाइलों को अनदेखा नहीं किया गया है:

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

और यदि आप जोड़ने की कोशिश करते हैं, तो आपको मिलता है:

$ 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

मैं इस व्यवहार को बग मानता हूं। (यह सब चालू है git version 1.8.4.msysgit.0)


1
+1, वास्तव में। आपको इस पर वास्तविक बग रिपोर्ट दर्ज करने पर विचार करना चाहिए क्योंकि व्यवहार अप्रत्याशित लगता है।
chandsie

1
बिल्कुल मेरा उपयोग मामला। धन्यवाद!
सेबेस्टियन ग्रेफ

3
dir/और dir/**फिर का अलग व्यवहार । अन-इग्नोरिंग के साथ !होता है क्योंकि "किसी फाइल को फिर से शामिल करना संभव नहीं होता है यदि उस फाइल की पैरेंट डाइरेक्टरी को बाहर रखा जाता है" [स्रोत ]। भ्रमित करना, लेकिन प्रदर्शन कारणों से किया गया। एक संबंधित SO प्रश्न देखें ।
तानीस

23

ध्यान दें कि, सख्ती से बोलना, गिट निर्देशिकाओं को ट्रैक नहीं करता है, केवल फाइलें। इसलिए निर्देशिका को जोड़ना संभव नहीं है, केवल इसकी सामग्री

.gitignoreहालांकि, संदर्भ में एकमात्र कारण के लिए निर्देशिकाओं को समझने का दिखावा है

किसी फ़ाइल को फिर से शामिल करना संभव नहीं है यदि उस फ़ाइल की मूल निर्देशिका को बाहर रखा गया है।
https://git-scm.com/docs/gitignore#_pattern_format

बहिष्कृत पैटर्न के लिए इसका क्या अर्थ है? आइए उनके बारे में विस्तार से जानें:

bin

यह उपेक्षा करता है

  • नाम की फाइलें bin
  • नामित फ़ोल्डर की सामग्री bin

आप binबाद की !प्रविष्टियों को जोड़कर फ़ाइलों और फ़ोल्डरों को अनदेखा कर सकते हैं, लेकिन आप नामित फ़ोल्डर्स की सामग्री को श्वेत सूची में नहीं डाल सकते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/

ऊपर के समान, सिवाय इसके कि यह नाम वाली फाइलों से मेल नहीं खाता bin। एक अनुगामी जोड़ना /केवल निर्देशिका से मिलान करने के लिए गिट बताता है।

bin/*

यह उपेक्षा करता है

  • नाम के फ़ोल्डर में सम्‍मिलित फ़ाइलेंbin
  • नाम वाले फ़ोल्डरों के डायरेक्ट सबफोल्डर्स की सामग्री 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/**

यह उपेक्षा करता है

  • की सामग्री bin
  • सबफ़ोल्डर्स (नेस्टिंग के किसी भी स्तर) की सामग्री भीतर 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

मैंने बस एक नया रेपो बनाया और कुछ चीजों की कोशिश की। यहाँ मेरे परिणाम हैं:

नए परिणाम

git संस्करण 2.10.1.windows.1

  1. प्रारंभिक-खाली रेपो। केवल README फाइल
  2. binडायरेक्टरी को कई लेयर्स को डीप पॉप्युलेट करें
    • 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 में : परिणाम
    • सब कुछ नीचे binनिर्देशिका के (और गहरा) अब नजरअंदाज कर दिया गया है
    • रूट स्तर को नजरअंदाज नहीं किया जाता (/bin.txt और /Test.txt अभी भी दिखा)
  4. को संपादित binकरेंbin/ gitignore में: परिणाम
    • कोई परिवर्तन नहीं होता है
  5. को संपादित bin/करेंbin/*
    • कोई परिवर्तन नहीं होता है
  6. को संपादित bin/*करेंbin/**
    • कोई परिवर्तन नहीं होता है
  7. को संपादित bin/**करेंbin/**/
    • bin/bin.txtऔर bin/Test.txtअब नजरअंदाज नहीं किया जाता है
  8. को संपादित bin/**/करेंbin/**/*
    • bin/bin.txtऔर bin/Test.txtवापस नजरअंदाज किया जा रहा है

पुराने परिणाम

git संस्करण: 2.7.0.windows.1

  1. प्रारंभिक-खाली रेपो। केवल README फाइल
  2. binडायरेक्टरी को कई लेयर्स को डीप पॉप्युलेट करें
    • bin/a/b/Test.txt
    • bin/a/bin/Test.txt
    • bin/a/Test.txt
    • bin/Test.txt
  3. जोड़ना binGitignore में : परिणाम
    • binनिर्देशिका के नीचे सब कुछ (और गहरा) अब नजरअंदाज कर दिया गया है
  4. को संपादित binकरेंbin/ gitignore में: परिणाम
    • binनिर्देशिका के नीचे सब कुछ (और गहरा) अभी भी अनदेखा है (कोई परिवर्तन नहीं)
  5. को संपादित bin/करेंbin/*
    • binनिर्देशिका के नीचे सब कुछ (और गहरा) अभी भी अनदेखा है (कोई परिवर्तन नहीं)
  6. को संपादित bin/*करेंbin/**
    • binनिर्देशिका के नीचे सब कुछ (और गहरा) अभी भी अनदेखा है (कोई परिवर्तन नहीं)
  7. को संपादित bin/**करेंbin/**/
    • bin/Test.txt अब नजरअंदाज नहीं किया जाता है
  8. को संपादित bin/**/करेंbin/**/*
    • binनिर्देशिका के नीचे सब कुछ (और गहरा) फिर से अनदेखा कर दिया जाता है

1
यह एक अच्छा परीक्षण है, मुझे लगता है कि text.txt को bin.txt का नाम बदलने से कुछ महत्वपूर्ण अंतर दिखाई देंगे। यदि आपने ऐसा किया तो मैं इस उत्तर के लिए मतदान करूंगा।
मैट जॉनसन

@MattJohnson यह सच है ... दुर्भाग्य से मैं इस समय एक नए हिट संस्करण पर हूँ
जो फिलिप्स

@MattJohnson मैं आखिरकार इसके आसपास हो गया
जो फिलिप्स

8

ध्यान दें कि ' **', जब एक उप-निर्देशिका के साथ संयुक्त होता है ( **/bar), अपने डिफ़ॉल्ट व्यवहार से बदल गया होगा, क्योंकि git1.8.2 के लिए जारी नोट में अब उल्लेख है:

इन .gitignoreऔर .gitattributesफाइल्स में पैटर्न **/0 या उससे अधिक स्तर के सबडायरेक्ट से मेल खाने वाले पैटर्न के रूप में हो सकता है ।

जैसे " foo/**/bar" " " " " " bar" में fooही या " foo" के उपनिर्देशिका में ।


याद रखने का नियम (और जो उन सिंटैक्स के पीछे के इरादे के अंतर को समझने में मदद करता है) है:

किसी फ़ाइल को फिर से शामिल करना संभव नहीं है यदि उस फ़ाइल की मूल निर्देशिका को बाहर रखा गया है।


आमतौर पर, यदि आप फ़ाइलों को अनदेखा फ़ोल्डर f के सबफ़ोल्डर से बाहर करना चाहते हैं, तो आप यह करेंगे:

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

अर्थात्:

  • यदि पहला नियम था f/, तो फ़ोल्डर f/को अनदेखा कर दिया जाएगा और नीचे दिए गए नियम fमायने नहीं रखेंगे।
  • f/**के रूप में ही प्राप्त करते हैं f/, लेकिन सभी उप-तत्वों (फ़ाइलों और सबफ़ोल्डर्स) को अनदेखा करें
    यह आपको श्वेतसूची (gitignore से बाहर) सबफ़ोल्डर्स का अवसर देता है !f/**/:।
  • चूंकि सभी fसबफ़ोल्डर्स को अनदेखा नहीं किया जाता है, आप फ़ाइल को बाहर करने के लिए एक नियम जोड़ सकते हैं ( !f/a/sub/folder/someFile.txt)

यह प्रश्न का उत्तर कैसे देता है?
थॉमस

0

वहाँ में एक और अंतर है bin/*और bin/

bin/मैच foo/bin/test.txt(उम्मीद के मुताबिक), लेकिन bin/*ऐसा नहीं है, जो अजीब लगता है, लेकिन यह प्रलेखित है: https://git-scm.com/docs/iddignore

"डॉक्यूमेंटेशन / *। Html" "डॉक्यूमेंटेशन / git.html" से मेल खाता है, लेकिन "डॉक्यूमेंटेशन / पीपीसी / ppc.html" या "टूल्स / परफेक्ट / डॉक्यूमेंटेशन / perf.html" नहीं।

इसका कारण ये नियम प्रतीत होते हैं:

  • यदि पैटर्न एक स्लैश के साथ समाप्त होता है, तो इसे निम्नलिखित विवरण के उद्देश्य से हटा दिया जाता है ...

  • यदि पैटर्न में कोई स्लैश / नहीं है, तो Git इसे शेल ग्लोब पैटर्न के रूप में मानता है और .nameignore फ़ाइल के स्थान के सापेक्ष पथनाम के विरुद्ध मैच के लिए जाँच करता है ...

  • अन्यथा, Git FNM_PATHNAME ध्वज के साथ fnmatch (3) द्वारा खपत के लिए उपयुक्त शेल गोला के रूप में पैटर्न का इलाज करता है ...

इसलिए यदि पैटर्न एक स्लैश के साथ समाप्त होता है, तो स्लैश को हटा दिया जाता है और इसे शेल ग्लॉब पैटर्न के रूप में माना जाता है, जिसमें मामला binमेल खाता है foo/bin/test.txt। यदि यह समाप्त हो जाता है /*, तो स्लैश को हटाया नहीं जाता है और इसे fnmatch को पास कर दिया जाता है, जो उपनिर्देशिकाओं में मेल नहीं खाता है।

हालाँकि, यह सच नहीं है foo/bin/और foo/bin/*, क्योंकि ट्रेलिंग स्लैश को हटाने के बाद भी foo/bin/, इसमें अभी भी एक स्लैश है, इसलिए इसे एक fnmatch पैटर्न के रूप में माना जाता है, न कि एक ग्लोब के रूप में। यानी यह मेल नहीं खाएगाbar/foo/bin/test.txt

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.