कोर्स
कुछ स्थितियों में, हम किसी लोकल Git ब्रांच की स्थिति को रिमोट रिपोजिटरी के अनुरूप रीसेट करना चाहते हैं, ताकि कोई भी लोकल बदलाव हटा दिए जाएँ। इसे आमतौर पर फोर्स्ड पुल कहा जाता है।
इससे एक गलत धारणा बनती है कि इसे हासिल करने का तरीका git pull कमांड में --force विकल्प का उपयोग करना है। इस लेख में, हम समझेंगे कि ये अलग-अलग बातें हैं।
यदि आप Git के लिए नए हैं, तो पहले हमारा Git push और pull ट्यूटोरियल पढ़ने पर विचार करें।
हम नीचे दिए गए कमांड्स से अपनी लोकल स्थिति को रिमोट स्थिति से ओवरराइट कर सकते हैं, जहाँ <branch_name> को अपनी ब्रांच के नाम से बदलें। यह क्रिया उस ब्रांच में आपके सभी लोकल बदलाव स्थायी रूप से हटा देगी।
git fetch
git reset --hard origin/<branch_name>
यह लेख इन कमांड्स के काम करने के तरीके के विवरण में जाएगा। हम त्वरित उपायों से आगे बढ़कर अंतर्निहित यांत्रिकी को समझेंगे, ताकि महत्वपूर्ण बदलाव खोने के जोखिम के बिना वांछित परिणाम पाने के अधिक प्रभावी तरीके सीख सकें। हम इस गलत धारणा को भी दूर करेंगे और समझेंगे कि git pull का --force विकल्प वास्तव में क्या करता है।
कब लोकल बदलाव ओवरराइट करने पर विचार करें
आम तौर पर, इस तरह लोकल बदलावों को ओवरराइट करना Git के इच्छित उपयोग के विरुद्ध है। लगभग हर स्थिति के लिए, उसे हल करने का एक उचित Git वर्कफ़्लो होता है। हालांकि, इनमें से कुछ के लिए Git की गहरी समझ चाहिए और उन्हें लागू करने में अधिक समय लग सकता है। भले ही यह सर्वश्रेष्ठ अभ्यास न हो, कुछ मामलों में लोकल बदलावों को ओवरराइट करना काम पूरा करने का सबसे तेज़ तरीका हो सकता है।
मेरे साथ यह तब होता है जब मैं किसी ऐसी फ़ीचर पर काम कर रहा होता/होती हूँ जिससे मैं बहुत परिचित नहीं होता/होती। मैं एक ब्रांच बनाकर कुछ कमिट्स करता/करती हूँ। जब मैं अटक जाता/जाती हूँ, तो मदद के लिए किसी सहकर्मी से पूछता/पूछती हूँ। वे मेरे गलती करने से पहले के किसी पुराने कमिट से शुरू करते हैं, समस्या हल करते हैं और अपने बदलाव पुश कर देते हैं। इस बिंदु पर, मुझे अपने लोकल वर्जन को अपडेटेड रिमोट वर्जन से बदलना होता है, अपने लोकल बदलावों को हटाते हुए, ताकि मैं फीचर पर काम जारी रख सकूँ।
एक और उदाहरण तब है जब कोई कॉन्फ्लिक्ट होता है, और मुझे लगता है कि कॉन्फ्लिक्ट को ठीक करना उससे अधिक कठिन या समय लेने वाला है बनिस्बत हमारे बदलावों को कोड के नवीनतम वर्जन पर फिर से लागू करने के।
कारण चाहे जो भी हो, हमेशा सुनिश्चित करें कि वे बदलाव वास्तव में आवश्यक नहीं हैं और सुरक्षित रूप से हटाए जा सकते हैं, या फिर महत्वपूर्ण काम खोने से बचने के लिए अपनी ब्रांच का बैकअप बना लें।
लोकल बदलाव सही तरीके से कैसे ओवरराइट करें
पहला कदम यह है कि हम अपनी लोकल मशीन पर रिमोट रिपोजिटरी से नवीनतम सामग्री फ़ेच (डाउनलोड) करें। यह Git के fetch कमांड से किया जाता है:
git fetch
डिफ़ॉल्ट रूप से, यह वर्तमान ब्रांच की सामग्री फ़ेच करेगा, जो प्रायः हमें चाहिए। हम वैकल्पिक रूप से उस ब्रांच को निर्दिष्ट कर सकते हैं जिसे हम डाउनलोड करना चाहते हैं (नीचे <branch_name> को उस ब्रांच के नाम से बदलें जिसे हम फ़ेच करना चाहते हैं):
git fetch origin/<branch_name>
वैकल्पिक रूप से, हम सब कुछ डाउनलोड करने के लिए --all विकल्प का उपयोग कर सकते हैं:
git fetch –all
रिमोट रिपोजिटरी से बदलाव फ़ेच करने से आपकी वर्तमान वर्किंग ब्रांच डायरेक्टरी की फ़ाइलों पर असर नहीं पड़ता। fetch कमांड रिमोट रिपोजिटरी से बदलाव डाउनलोड करता है लेकिन उन्हें मर्ज नहीं करता। लोकल रिपोजिटरी लोकल और रिमोट दोनों फ़ाइलों का दृश्य रखती है, और फ़ेचिंग से रिमोट फ़ाइलों के दृश्य को अपडेट किया जाता है।
रिमोट रिपोजिटरी से बदलाव डाउनलोड करने के बाद, हम Git के reset कमांड का उपयोग करके वर्तमान वर्किंग ब्रांच को दी गई स्थिति में रीसेट कर सकते हैं:
git reset --hard origin/<branch_name>
--hard विकल्प आवश्यक है ताकि यह सुनिश्चित हो सके कि लोकल बदलाव रिमोट बदलावों से ओवरराइट हो जाएँ। ऊपर दिए गए कमांड में, हमने वर्तमान वर्किंग ब्रांच को origin/<banch_name> से बदलने का चयन किया है, जो अभी-अभी फ़ेच की गई उस ब्रांच के रिमोट वर्जन के अनुरूप है।
git reset कमांड लोकल बदलावों को हटा देगा, भले ही वे कमिट किए गए हों। इसलिए, इस कमांड को चलाने से पहले वर्तमान ब्रांच का लोकल बैकअप बनाना अनुशंसित है। यह इस प्रकार किया जा सकता है:
git branch <name_of_the_backup_branck>
यहाँ <name_of_the_backup_branch> को उस नाम से बदलें जो आप बैकअप ब्रांच को देना चाहते हैं।
सब कुछ मिलाकर, हम किसी दी गई ब्रांच के सभी लोकल बदलावों को नवीनतम रिमोट वर्जन से इस प्रकार ओवरराइट कर सकते हैं:
git fetch
git branch <name_of_the_backup_branch>
git reset --hard origin/<branch_name>
यदि आप Git में ब्रांचों के साथ काम करने के बारे में अपना ज्ञान बढ़ाना चाहते हैं, तो Git की किसी विशेष ब्रांच को क्लोन करने का ट्यूटोरियल देखें।
अनट्रैक्ड फ़ाइलें हटाकर पूरा क्लीनअप
Git अनट्रैक्ड फ़ाइलों (जो कभी git add से जोड़ी नहीं गईं) को नहीं छुएगा। यदि हम इन फ़ाइलों को भी हटाना चाहते हैं, तो हम यह कर सकते हैं:
git clean -fdx
यह एक खतरनाक कमांड है जिसका उपयोग वर्किंग डायरेक्टरी से अनट्रैक्ड फ़ाइलों को हटाने के लिए किया जाता है। इस कमांड का सावधानी से उपयोग करना आवश्यक है क्योंकि यह फ़ाइलों को स्थायी रूप से हटा देता है, जिससे उन्हें Git के माध्यम से पुनर्प्राप्त करना असंभव हो जाता है। कमांड विकल्पों का विवरण इस प्रकार है:
-f: यह विकल्प क्लीन ऑपरेशन को जबरन आगे बढ़ाता है। आकस्मिक डेटा हानि से बचाव के लिए इस फ़्लैग के बिना Git वर्किंग डायरेक्टरी से अनट्रैक्ड फ़ाइलों को हटाने से मना कर देगा।-d: यहgit cleanको न केवल अनट्रैक्ड फ़ाइलें बल्कि अनट्रैक्ड डायरेक्टरी भी हटाने को कहता है। डिफ़ॉल्ट रूप से,git cleanकेवल अनट्रैक्ड फ़ाइलों को लक्षित करता है और डायरेक्टरी को अनदेखा करता है।-x: डिफ़ॉल्ट रूप से,git clean.gitignoreनियमों का सम्मान करेगा और उन फ़ाइलों/डायरेक्टरीज़ को नहीं हटाएगा जो इन पैटर्न से मेल खाती हैं। -x शामिल करने से यह व्यवहार ओवरराइड हो जाता है, और Git को निर्देश मिलता है कि वह.gitignoreया अन्य इग्नोर नियमों द्वारा अनदेखी की गई फ़ाइलों/डायरेक्टरीज़ को भी हटाए। इससे बहुत गहन सफ़ाई होती है, जिसमें बिल्ड आउटपुट, लॉग फ़ाइलें और अन्य जेनरेटेड आर्टिफैक्ट्स सहित रिपोजिटरी की सभी अनट्रैक्ड फ़ाइलें हट जाती हैं।
Git Pull को समझना
हम आमतौर पर अपनी लोकल रिपोजिटरी को रिमोट बदलावों से git pull कमांड के जरिए अपडेट करते हैं। हालांकि, इस कमांड का उपयोग हमारे लोकल बदलावों को ओवरराइट करने के लिए नहीं किया जा सकता क्योंकि git pull हमारी लोकल वर्जन को रिमोट के साथ मर्ज करने की कोशिश करेगा।
अंदर ही अंदर, git pull निम्नलिखित चरणों को पूरा करता है:
- यह रिमोट रिपोजिटरी के नवीनतम वर्जन को डाउनलोड करने के लिए
git fetchका उपयोग करता है। - यह लोकल और रिमोट ब्रांचों को मर्ज करने के लिए
git mergeका उपयोग करता है।
मर्ज वाले चरण के कारण, git pull उन स्थितियों में उपयुक्त कमांड नहीं है जहाँ हम लोकल बदलावों को नज़रअंदाज कर उन्हें हटाना चाहते हैं।

git pull --force के बारे में क्या?
git pull कमांड के दस्तावेज़ देखें तो पता चलता है कि यह --force विकल्प देता है। आम गलतफहमी यह है कि यह विकल्प git pull को लोकल बदलावों को रिमोट बदलावों से मिटा कर ज़बरन चलाएगा।
जब हम git pull को --force विकल्प देते हैं, तो यह विकल्प git fetch तक पास होता है। इस प्रकार git pull --force निम्नलिखित चरणों को पूरा करता है:
git fetch --forcegit merge

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

हालाँकि, ऐसा भी हो सकता है कि किसी ने रिमोट ब्रांच के कमिट इतिहास को फिर से लिखा हो, जिससे वह लोकल दृश्य के साथ असंगत हो जाए। इस स्थिति में फ़ेच काम नहीं करेगा।

हम --force विकल्प का उपयोग करके इससे पार पा सकते हैं, जो Git को लोकल इतिहास की अनदेखी कर उसे रिमोट इतिहास से ओवरराइट करने के लिए मजबूर करेगा।
हम देखते हैं कि --force विकल्प कमिट इतिहास को ज़बरन ओवरराइट करने से संबंधित है और वर्किंग ब्रांच डायरेक्टरी में लोकल बदलावों को अनदेखा करने से इसका कोई लेना-देना नहीं है।
लोकल बदलावों का एकीकरण
लोकल बदलावों को रिमोट बदलावों से ओवरराइट करना सामान्य Git प्रथा नहीं है, पर कुछ मामलों में यह उपयोगी हो सकता है जब हम कॉन्फ्लिक्ट्स से नहीं निपटना चाहते या हमें अपने लोकल बदलावों की परवाह नहीं।
मर्जिंग
आमतौर पर, कोई बदलाव पुल करेगा और कॉन्फ्लिक्ट्स से निपटेगा। लोग अक्सर कॉन्फ्लिक्ट्स से निपटने से डरते हैं। कुछ कॉन्फ्लिक्ट्स भारी लग सकते हैं, लेकिन ऐसा अक्सर नहीं होता। कॉन्फ्लिक्ट तब होता है जब:
- लोकल ब्रांच और रिमोट ब्रांच, दोनों में, फ़ाइल के एक ही हिस्से पर बदलाव हों।
- किसी एक तरफ फ़ाइल डिलीट हो और दूसरी तरफ उसमें संशोधन किया गया हो।
इन मामलों में Git अंदाज़ा नहीं लगा सकता कि हमें कौन-से बदलाव रखने हैं, और हमें इसे मैन्युअली बताना पड़ता है। Git फ़ाइलों में इस प्रकार कॉन्फ्लिक्ट को हाइलाइट करेगा:

किसी कॉन्फ्लिक्ट को हल करने के लिए, हम फ़ाइल को संपादित करते हैं और इन लाइनों को हटा देते हैं, सिवाय उनके जिन्हें हम रखना चाहते हैं। सभी कॉन्फ्लिक्ट्स संभाल लेने के बाद, हम बदलावों को कमिट कर सकते हैं। विस्तृत मार्गदर्शिका के लिए, यह ट्यूटोरियल देखें: Git में मर्ज कॉन्फ्लिक्ट्स कैसे सुलझाएँ।
चेरी-पिकिंग
यदि हम सचमुच पहले अपनी लोकल वर्जन को रिमोट वर्जन से मिलाना चाहते हैं और फिर अंततः अपने बदलावों को जोड़ना चाहते हैं, तो हम बैकअप ब्रांच से कमिट्स को वर्तमान ब्रांच में इस प्रकार ला सकते हैं:
git cherry-pick <commit_hash>
यहाँ <commit_hash> उस कमिट का हैश है जिसे हम जोड़ना चाहते हैं। यह मानकर चलता है कि git reset करने से पहले हमने git branch <name_of_the_backup_branck> से एक बैकअप ब्रांच बनाई थी और लोकल बदलाव कमिट किए गए थे।
<commit_hash> ढूँढने के लिए, हम बैकअप ब्रांच में कमिट हैश की सूची निम्न कमांड से देख सकते हैं:
git log <name_of_the_backup_branck>
स्टैशिंग
वैकल्पिक रूप से, यदि हम अपने बदलाव कमिट नहीं करना चाहते या बैकअप ब्रांच नहीं बनाना चाहते, तो हम मर्ज करने से पहले अपने बदलावों को स्टैश कर सकते हैं:
git stash
यह कमांड वर्तमान काम को अस्थायी रूप से सहेजने के लिए उपयोग की जाती है, बिना उसे ब्रांच इतिहास में कमिट किए। स्टैशिंग आपके संशोधनों को अलग रखती है, जिससे आपकी वर्किंग डायरेक्टरी साफ़ हो जाती है।
रीसेट करने के बाद, हम निम्न कमांड का उपयोग करके अपने बदलावों को वापस ला सकते हैं:
git stash pop
स्टैशिंग का उपयोग करते हुए, पूरा वर्कफ़्लो कुछ इस तरह दिखेगा:
git fetch
git stash
git reset --hard origin/<branch_name>
git stash pop
और जानने के लिए, यह चीट शीट देखें जिसमें स्टैश और अन्य Git कमांड्स हैं।
निष्कर्ष
सर्वोत्तम प्रथा न होने के बावजूद, कभी-कभी हम ऐसी स्थिति में होते हैं जहाँ हम अपने लोकल बदलावों को त्यागते हुए बस अपनी लोकल ब्रांच को रिमोट ब्रांच की सामग्री से मिलाना चाहते हैं।
यह गलतफहमी है कि यह git pull --force से हासिल होता है। यह गलत है क्योंकि git pull --force git fetch --force और git merge को जोड़ता है। इसलिए, यह लोकल बदलावों को रिमोट बदलावों के साथ मर्ज करने का प्रयास करता है, उन्हें ओवरराइट नहीं करता।
लोकल बदलावों को रिमोट रिपोजिटरी की सामग्री से ओवरराइट करने का सही तरीका यह है:
git fetch
git reset --hard origin/<branch_name>
git reset कमांड का सावधानी से उपयोग करना चाहिए क्योंकि यह लोकल बदलावों को हटा देगा, भले ही वे कमिट किए गए हों। यदि हमारे पास लोकल कमिट्स थे और हमने बैकअप ब्रांच बनाई थी, तो हम उन्हें git cherry-pick से वापस ला सकते हैं। यदि हमने कमिट नहीं किया था और अपना लोकल काम अस्थायी रूप से सहेजना चाहते हैं, तो रीसेट करने से पहले git stash और फिर बदलाव वापस लाने के लिए git stash pop का उपयोग कर सकते हैं।
