Git: किसी भी रिपॉजिटरी से फ़ाइलों को हटाने के बिना इंडेक्स से फाइल कैसे निकालें


163

जब आप उपयोग करते हैं

git rm --cached myfile

यह स्थानीय फाइल सिस्टम से नहीं हटता है, जो कि लक्ष्य है। लेकिन अगर आपने पहले से ही फ़ाइल का संस्करण तैयार कर लिया है और उसे कमिट कर दिया है, तो उसे एक केंद्रीय भंडार में धकेल दिया, और कमांड का उपयोग करने से पहले इसे अन्य रिपॉजिटरी में खींच लिया, यह फ़ाइल को उस सिस्टम से हटा देगा।

वहाँ किसी भी फाइल सिस्टम से हटाने के बिना फ़ाइल को केवल संस्करण से हटाने का एक तरीका है?

संपादित करें: स्पष्ट, मुझे उम्मीद है।


शायद आप अपने उपयोग के मामले में विस्तार कर सकते हैं। अनुक्रमणिका अगले कमिट के लिए स्टेजिंग क्षेत्र है इसलिए यदि आप वर्तमान शाखा से इसे नहीं निकालना चाहते हैं तो आप तर्जनी से फ़ाइल क्यों निकालना चाहते हैं?
सीबी बेली

1
मुझे माफ कर दो। मेरे कहने का मतलब है कि मेरीफाइल किसी कारण से शुरू हुई थी और बहुत समय पहले वितरित की गई थी। अब लक्ष्य यह है कि इसे लोगों के सिस्टम से हटाए बिना संस्करण से हटाया जाए। यह कारण सामने आया क्योंकि मैंने गलती से एक कॉन्फिगर फाइल का संस्करण तैयार कर लिया था। कॉन्फ़िगरेशन फ़ाइल आवश्यक है, इसलिए मैं इसे विदेशी सिस्टम से निकालना नहीं चाहता।
फ्लेचर मूर

मैंने प्रश्न को अधिक स्पष्ट होने के लिए संपादित किया है।
फ्लेचर मूर

3
git rm - cached फाइल को दूसरे वर्किंग डायरेक्टरी से नहीं हटाएगा। फ़ाइल केवल तभी निकाल दी जाएगी जब कोई उस निर्देशिका में काम कर रहा हो, जो एक पुल निष्पादित करता है। फ़ाइल को आसानी से "git checkout HEAD @ {1} foo" के साथ पुनर्प्राप्त किया जा सकता है (यदि पुल के तुरंत बाद निष्पादित किया जाता है।)
विलियम पर्ससेल

जवाबों:


119

मुझे नहीं लगता कि एक Git कमिट "इस फाइल को ट्रैक करना बंद कर सकता है, लेकिन इसे डिलीट नहीं करता" जैसे इरादे को रिकॉर्ड कर सकता है।

इस तरह के इरादे को लागू करने के लिए किसी भी रिपॉजिटरी में Git के बाहर हस्तक्षेप की आवश्यकता होगी जो फ़ाइल को हटाने वाली एक कमेटी को मर्ज (या रीबेस) करता है।


एक प्रतिलिपि सहेजें, हटाएं लागू करें, पुनर्स्थापित करें

संभवतः करने के लिए सबसे आसान बात यह है कि अपने डाउनस्ट्रीम उपयोगकर्ताओं को फ़ाइल की एक प्रति बचाने के लिए, अपने विलोपन को खींचने के लिए कहें, फिर फ़ाइल को पुनर्स्थापित करें। यदि वे रिबास के माध्यम से खींच रहे हैं और फ़ाइल में संशोधन कर रहे हैं, तो उन्हें संघर्ष मिलेगा। इस तरह के संघर्षों को हल करने के लिए, उपयोग करें git rm foo.conf && git rebase --continue(यदि हटाए गए फ़ाइल के अलावा परस्पर विरोधी प्रतिबद्धता में परिवर्तन होता है) या git rebase --skip( या यदि विरोधाभासी प्रतिबद्धता केवल हटाए गए फ़ाइल में बदल गई है)।

पुनर्स्थापना के बाद फाइल को अनटैक्ड के रूप में एक कमिट करने के बाद हटा देता है

यदि उन्होंने पहले ही आपकी विलोपन प्रतिबद्धता को खींच लिया है, तब भी वे फ़ाइल के पिछले संस्करण को गिट शो के साथ पुनर्प्राप्त कर सकते हैं :

git show @{1}:foo.conf >foo.conf

या गिट चेकआउट के साथ (विलियम पर्सेल द्वारा प्रति टिप्पणी; लेकिन याद रखें कि इसे फिर से सूचकांक से हटा दें!)।

git checkout @{1} -- foo.conf && git rm --cached foo.conf

यदि उन्होंने आपके विलोपन को खींचने के बाद से अन्य कार्रवाइयाँ की हैं (या वे रिबेट के साथ अलग किए गए HEAD में खींच रहे हैं), तो उन्हें इसके अलावा कुछ और की आवश्यकता हो सकती है @{1}। वे git log -gआपके विलोपन को खींचने से ठीक पहले कमिटमेंट खोजने के लिए उपयोग कर सकते हैं ।


एक टिप्पणी में, आप उल्लेख करते हैं कि जिस फ़ाइल को आप "अनट्रैक करना चाहते हैं, लेकिन रखें" कुछ प्रकार की कॉन्फ़िगरेशन फ़ाइल है जो सॉफ़्टवेयर चलाने के लिए आवश्यक है (सीधे एक भंडार से बाहर)।

फ़ाइल को 'डिफ़ॉल्ट' और मैन्युअल रूप से स्वचालित रूप से सक्रिय रखें

यदि यह रिपॉजिटरी में कॉन्फ़िगरेशन फ़ाइल की सामग्री को बनाए रखने के लिए जारी रखने के लिए पूरी तरह से अस्वीकार्य नहीं है, तो आप ट्रैक किए गए फ़ाइल को (जैसे) foo.confसे foo.conf.defaultफिर से नाम बदलने में सक्षम हो सकते हैं और फिर अपने उपयोगकर्ताओं को cp foo.conf.default foo.confनाम बदलने के लिए प्रतिबद्ध करने के बाद निर्देश दे सकते हैं। या, यदि उपयोगकर्ता पहले से ही रिपॉजिटरी के कुछ मौजूदा हिस्से का उपयोग करते हैं (जैसे एक स्क्रिप्ट या कुछ अन्य प्रोग्राम जो रिपॉजिटरी में सामग्री द्वारा कॉन्फ़िगर किया गया है (जैसे Makefileया समान)) आपके सॉफ़्टवेयर को लॉन्च / तैनात करने के लिए, आप लॉन्च में एक डिफ़ॉल्ट तंत्र को शामिल कर सकते हैं / तैनाती प्रक्रिया:

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf

इस तरह के एक डिफ़ॉल्ट तंत्र के साथ, उपयोगकर्ताओं को किसी भी अतिरिक्त कार्य को foo.confकरने के foo.conf.defaultबिना एक नाम बदलने में सक्षम होना चाहिए । साथ ही, यदि आप भविष्य में अतिरिक्त इंस्टॉलेशन / रिपॉजिटरी बनाते हैं, तो आप मैन्युअल रूप से एक कॉन्फ़िगरेशन फ़ाइल की प्रतिलिपि बनाने से बचें।

इतिहास को फिर से लिखने के लिए मैन्युअल हस्तक्षेप की आवश्यकता होती है ...

यदि यह भंडार में सामग्री को बनाए रखने के लिए अस्वीकार्य है तो आप संभवतः इसे इतिहास से पूरी तरह से मिटाना चाहेंगे git filter-branch --index-filter …। यह इतिहास को फिर से लिखने के लिए है, जिसके लिए प्रत्येक शाखा / भंडार के लिए मैनुअल हस्तक्षेप की आवश्यकता होगी (देखें "अपस्ट्रीम रिबेस से पुनर्प्राप्त करना" अनुभाग में git rebase manpage )। आपकी कॉन्फ़िगरेशन फ़ाइल के लिए आवश्यक विशेष उपचार सिर्फ एक और कदम होगा जिसे किसी को फिर से लिखने के दौरान ठीक करना होगा:

  1. कॉन्फ़िगरेशन फ़ाइल की एक प्रति सहेजें।
  2. फिर से लिखना से पुनर्प्राप्त करें।
  3. कॉन्फ़िगरेशन फ़ाइल को पुनर्स्थापित करें।

पुनरावृत्ति को रोकने के लिए इसे अनदेखा करें

आप जिस भी तरीके का उपयोग करते हैं, आप शायद कॉन्फ़िगरेशन फ़ाइल नाम .gitignoreको रिपॉजिटरी में एक फ़ाइल में शामिल करना चाहेंगे ताकि कोई भी अनजाने में git add foo.confफिर से न हो सके (यह संभव है, लेकिन -f/ की आवश्यकता है --force)। यदि आपके पास एक से अधिक कॉन्फ़िगरेशन फ़ाइल है, तो आप उन सभी को एक ही निर्देशिका में 'ले जाने' पर विचार कर सकते हैं और पूरी चीज़ को अनदेखा कर सकते हैं ('मूविंग' से मेरा मतलब है कि परिवर्तन जहां प्रोग्राम अपनी कॉन्फ़िगरेशन फ़ाइलों को खोजने की उम्मीद करता है, और उपयोगकर्ता प्राप्त कर रहा है (या) लॉन्च / तैनाती तंत्र) फ़ाइलों को उनके नए स्थान पर कॉपी / स्थानांतरित करने के लिए; आप स्पष्ट रूप से एक फ़ाइल को एक निर्देशिका में बदलना नहीं चाहेंगे जिसे आप अनदेखा कर रहे हैं)।


5
अविश्वसनीय रूप से पूरी तरह से प्रतिक्रिया। धन्यवाद!
फ्लेचर मूर

नीचे टॉम पावर का जवाब, आपके पहले वाक्य के विपरीत प्रतीत होता है।
माइक एस

1
@ माइक: का प्रभाव --{,no-}assume-unchangedविशुद्ध रूप से स्थानीय है: इसका राज्य सीधे तौर पर कमिट में दर्ज नहीं किया गया है। यह एक रिपॉजिटरी को फ़ाइल में नए बदलाव करने से रोकने में मदद कर सकता है, लेकिन यह संस्करण नियंत्रण से इसे नहीं हटाता है। यदि आप इसे अपने सभी प्रासंगिक, संबंधित, गैर-नंगे रिपॉजिटरी के लिए सेट कर सकते हैं, तो यह आपकी स्थिति में मदद कर सकता है, लेकिन यह ऐसा कुछ नहीं है जिसे आप अन्य संबंधित, गैर-नंगे रिपॉजिटरी (विशेष रूप से उन) में सीधे + खींच / रिबेट कर सकते हैं आप प्रश्न पर मूल प्रश्नकर्ता की स्पष्ट टिप्पणियों के अनुसार नियंत्रण नहीं करते हैं: "लोगों के सिस्टम" / "विदेशी सिस्टम") देखें।
क्रिस जॉन्सन

1
I do not think a Git commit can record an intention like “stop tracking this file, but do not delete it”.- अब यह कर सकते हैं, के साथgit rm --cached foo.conf
निक Volynkin

1
@NickVolynkin: क्या यह प्रश्न पहले से ही इंगित नहीं करता है कि यह पूछने वाले के उद्देश्य के लिए अपर्याप्त है: (स्वचालित रूप से) फ़ाइल को इधर-उधर रखने पर जब परिणामी प्रतिबद्ध को दूसरे भंडार में खींच लिया जाता है?
क्रिस जॉन्सन

86

इस हफ्ते बहुत ही समस्या थी जब मैंने गलती से किया था, तो एक साझा रिपॉजिटरी से एक बिल्ड फ़ाइल को हटाने की कोशिश की, और यह:

http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

मेरे लिए ठीक काम किया है और अब तक उल्लेख नहीं किया है।

git update-index --assume-unchanged <file>

संस्करण नियंत्रण से आपकी रुचि वाली फ़ाइल को निकालने के लिए, फिर अपने सभी अन्य आदेशों का सामान्य रूप से उपयोग करें।

git update-index --no-assume-unchanged <file>

यदि आप कभी भी इसे वापस रखना चाहते थे।

संपादित करें: कृपया क्रिस जॉन्सन और केपीएम की टिप्पणियों को देखें, यह केवल स्थानीय रूप से काम करता है और फ़ाइल अन्य उपयोगकर्ताओं के लिए संस्करण नियंत्रण में रहती है यदि वे ऐसा नहीं करते हैं। स्वीकृत उत्तर इससे निपटने के लिए अधिक पूर्ण / सही तरीके देता है। इस विधि का उपयोग करने पर लिंक से कुछ नोट्स भी:

जाहिर है कि इसके साथ खेलने के लिए आने वाले कुछ कैविएट हैं। यदि आप फ़ाइल को सीधे जोड़ते हैं, तो इसे इंडेक्स में जोड़ा जाएगा। इस झंडे के साथ कमिट करने से मर्ज इनायत से विफल हो जाएगा ताकि आप इसे मैन्युअल रूप से संभाल सकें।


7
यह उल्लेखित विशिष्ट समस्या का जवाब नहीं है। यह केवल आपके स्वयं के स्थानीय भंडार के लिए काम करेगा, इसलिए प्रत्येक उपयोगकर्ता को यह स्वयं करना होगा। यह एक पीड़ा है।
केपीएम

28

फ़ाइल को अनुक्रमणिका से निकालने के लिए, उपयोग करें:

git reset myfile

यह आपकी स्थानीय प्रति या किसी और के लिए प्रभावित नहीं होना चाहिए।


1
resetयदि फ़ाइल वर्तमान HEAD कमिट में नहीं है, तो केवल फ़ाइल को अनुक्रमणिका से निकाल देता है, अन्यथा यह केवल अनुक्रमणिका संस्करण को वर्तमान HEAD संस्करण में बदल देता है।
सीबी बेली

1
शायद मैंने इस सवाल को गलत समझा है, लेकिन यह किसी भी हंगामे को प्रभावित किए बिना सूचकांक से एक फाइल को हटाने से संबंधित है।
आर्मंड

जैसा कि चार्ल्स ने कहा, रीसेट "एक फ़ाइल को हटा नहीं" है। अधिक जानकारी के लिए git सहायता रीसेट टाइप करें।
साइमन बी।

4
यह प्रश्न का उत्तर देता है, "किसी भी भंडार से फ़ाइलों को हटाने के बिना सूचकांक से फ़ाइल कैसे निकालें" शीर्षक से। हालांकि ओपी वास्तव में पूछ रहा था "मैं स्थानीय प्रतिलिपि को हटाने के साथ एक फ़ाइल को कैसे अनट्रैक कर सकता हूं।"
18

@hewsonism ओपी ने कहा "किसी भी फाइलसिस्टम" (किसी भी संपादन से पहले)।
jbobbins


15

git rm --cachedकमांड करने के बाद , फ़ाइल में जोड़ने myfileका प्रयास करें .gitignore(यदि यह मौजूद नहीं है तो एक बनाएं)। इसे जीआईटी को नजरअंदाज करना चाहिए myfile

.gitignoreफ़ाइल, संस्करणीकृत ताकि आप इसे प्रतिबद्ध और दूरदराज के भंडार को धक्का करने की आवश्यकता होगी है।


1

मेरा काम दूसरी कॉपी पर काम करना है और फिर करना है:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

जो कहता है कि नवीनतम टिप्पणी में सभी फ़ाइल पथ प्राप्त करें, और उन्हें हेड के माता-पिता से बाहर की जाँच करें। काम हो गया।


0

उपरोक्त समाधान अधिकांश मामलों के लिए ठीक काम करते हैं। हालाँकि, अगर आपको उस फ़ाइल के सभी निशान (यानी संवेदनशील डेटा जैसे पासवर्ड) को निकालने की आवश्यकता है, तो आप इसे अपने संपूर्ण कमिट इतिहास से भी निकालना चाहेंगे, क्योंकि फ़ाइल को अभी भी वहाँ से पुनर्प्राप्त किया जा सकता है।

यहां एक समाधान है जो आपके संपूर्ण प्रतिबद्ध इतिहास से फ़ाइल के सभी निशानों को हटा देता है, जैसे कि यह कभी अस्तित्व में नहीं था, फिर भी आपके सिस्टम पर फ़ाइल को रखता है।

https://help.github.com/articles/remove-sensitive-data/

यदि आप अपने स्थानीय गिट रिपॉजिटरी में हैं, तो आप वास्तव में चरण 3 पर जा सकते हैं और सूखा रन करने की आवश्यकता नहीं है। मेरे मामले में, मुझे केवल चरण 3 और 6 की आवश्यकता थी, जैसा कि मैंने पहले ही अपनी .gitignore फ़ाइल बनाई थी, और उस रिपॉजिटरी में था जिस पर मैं काम करना चाहता था।

अपने परिवर्तनों को देखने के लिए, आपको अपनी रिपॉजिटरी के GitHub रूट पर जाना होगा और पेज को रिफ्रेश करना होगा। फिर लिंक के माध्यम से नेविगेट करने के लिए एक पुरानी प्रतिबद्ध पाने के लिए कि एक बार फ़ाइल थी, यह देखने के लिए कि अब इसे हटा दिया गया है। मेरे लिए, पुराने प्रतिबद्ध पृष्ठ को ताज़ा करने से बदलाव नहीं दिखा।

यह पहली बार में डरा हुआ लग रहा था, लेकिन वास्तव में, आसान था और एक आकर्षण की तरह काम करता था! :-)

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