सारांश
डिफ़ॉल्ट रूप से, git pull
मर्ज कमिट बनाता है जो कोड इतिहास में शोर और जटिलता जोड़ता है। इसके अलावा, pull
यह सोचना आसान नहीं है कि आने वाले परिवर्तनों से आपके परिवर्तन कैसे प्रभावित हो सकते हैं।
जब git pull
तक यह केवल तेजी से अग्रेषित मर्ज करता है, तब तक यह कमांड सुरक्षित रहता है। यदि git pull
केवल फास्ट-फ़ॉरवर्ड मर्ज करने के लिए कॉन्फ़िगर किया गया है और जब फ़ॉर-फ़ॉरवर्ड मर्ज संभव नहीं है, तो Git एक त्रुटि के साथ बाहर निकल जाएगा। इससे आपको आने वाले कमिट्स का अध्ययन करने का अवसर मिलेगा, इस बारे में सोचें कि वे आपके स्थानीय कमेंट्स को कैसे प्रभावित कर सकते हैं, और कार्रवाई का सबसे अच्छा तरीका तय करें (मर्ज, रिबेस, रीसेट, आदि)।
Git 2.0 और नए के साथ, आप चला सकते हैं:
git config --global pull.ff only
डिफ़ॉल्ट व्यवहार को केवल तेज़ी से अग्रेषित करने के लिए परिवर्तित करना। 1.6.6 और 1.9.x के बीच Git संस्करणों के साथ आपको टाइपिंग की आदत डालनी होगी:
git pull --ff-only
हालांकि, Git के सभी संस्करणों के साथ, मैं git up
इस तरह से एक उपनाम को कॉन्फ़िगर करने की सलाह देता हूं :
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
और का उपयोग कर git up
के बजाय git pull
। मैं इस उपनाम को पसंद करता हूं git pull --ff-only
क्योंकि:
- यह Git के सभी (गैर-प्राचीन) संस्करणों के साथ काम करता है,
- यह सभी अपस्ट्रीम शाखाओं को प्राप्त करता है (न केवल उस शाखा को जो आप वर्तमान में काम कर रहे हैं), और
- यह पुरानी
origin/*
शाखाओं को साफ करता है जो अब ऊपर की ओर मौजूद नहीं हैं।
के साथ समस्याएं git pull
git pull
यह ठीक से उपयोग किया जाता है तो बुरा नहीं है। Git में कई हालिया परिवर्तनों ने इसे git pull
ठीक से उपयोग करना आसान बना दिया है , लेकिन दुर्भाग्य से एक सादे के डिफ़ॉल्ट व्यवहार git pull
में कई समस्याएं हैं:
- यह इतिहास में गैरजरूरी गैर-परिचय का परिचय देता है
- यह आकस्मिक रूप से कमिट करना आसान बनाता है जो जानबूझकर अपस्ट्रीम से बाहर किए गए थे
- यह अप्रत्याशित तरीके से आपकी कार्य निर्देशिका को संशोधित करता है
- किसी और के काम की समीक्षा करने के लिए आप जो कर रहे हैं, उसे रोकना कष्टप्रद है
git pull
- यह दूरस्थ शाखा पर सही ढंग से रिबेस करने के लिए कठिन बनाता है
- यह दूरस्थ रेपो में हटा दी गई शाखाओं को साफ नहीं करता है
इन समस्याओं को नीचे विस्तार से वर्णित किया गया है।
नॉनलाइनियर हिस्ट्री
डिफ़ॉल्ट रूप से, git pull
कमांड git fetch
उसके बाद चलने के बराबर है git merge @{u}
। यदि स्थानीय रिपॉजिटरी में अप्रकाशित कमिट हैं, तो मर्ज का हिस्सा git pull
मर्ज कमिट बनाता है।
मर्ज कमिट्स के बारे में कुछ भी बुरा नहीं है, लेकिन वे खतरनाक हो सकते हैं और उन्हें सम्मान के साथ माना जाना चाहिए:
- मर्ज कमिट्स को जांचना स्वाभाविक है। यह समझने के लिए कि एक मर्ज क्या कर रहा है, आपको सभी माता-पिता के मतभेदों को समझना होगा। एक पारंपरिक अंतर इस बहुआयामी जानकारी को अच्छी तरह से व्यक्त नहीं करता है। इसके विपरीत, सामान्य आवागमन की एक श्रृंखला की समीक्षा करना आसान है।
- मर्ज संघर्ष रिज़ॉल्यूशन मुश्किल है, और गलतियाँ अक्सर लंबे समय तक नहीं चल पाती हैं क्योंकि मर्ज कमिट की समीक्षा करना मुश्किल होता है।
- मर्ज चुपचाप नियमित रूप से आने वाले प्रभावों को प्रभावित कर सकते हैं। कोड अब वृद्धिशील कमिट का योग नहीं है, जो वास्तव में बदल गया है के बारे में गलतफहमी के लिए अग्रणी है।
- मर्ज किए जाने से कुछ निरंतर एकीकरण योजनाएं बाधित हो सकती हैं (उदाहरण के लिए, मान लिया गया अधिवेशन के तहत केवल पहला-मूल पथ ऑटो-बिल्ड करता है, जो दूसरे माता-पिता प्रगति में अपूर्ण कार्यों की ओर इशारा करते हैं)।
बेशक विलय के लिए एक समय और एक जगह है, लेकिन यह समझना कि विलय कब किया जाना चाहिए और क्या नहीं किया जाना चाहिए, यह आपके भंडार की उपयोगिता में सुधार कर सकता है।
ध्यान दें कि Git का उद्देश्य कोडबेस के विकास को साझा करना और उपभोग करना आसान बनाना है, न कि इतिहास को ठीक वैसे ही रिकॉर्ड करना, जैसा कि यह प्रकट किया गया था। (यदि आप असहमत हैं, तो rebase
कमांड पर विचार करें और इसे क्यों बनाया गया था।) बनाया गया मर्ज git pull
दूसरों के लिए उपयोगी शब्दार्थ को व्यक्त नहीं करता है - वे सिर्फ इतना कहते हैं कि आपके बदलावों से पहले किसी और ने रिपॉजिटरी को धक्का देने के लिए हुआ था। यदि वे दूसरों के लिए सार्थक नहीं हैं और खतरनाक हो सकते हैं, तो वे विलय क्यों करते हैं?
git pull
मर्ज के बजाय रिबेस को कॉन्फ़िगर करना संभव है , लेकिन इसमें समस्याएं भी हैं (बाद में चर्चा की गई)। इसके बजाय, git pull
केवल फास्ट-फॉरवर्ड मर्ज करने के लिए कॉन्फ़िगर किया जाना चाहिए।
रिबेड-आउट कमिट्स का पुन: निर्माण
मान लीजिए कि कोई शाखा को विद्रोह करता है और बल उसे धक्का देता है। यह आम तौर पर नहीं होना चाहिए, लेकिन यह कभी-कभी आवश्यक होता है (उदाहरण के लिए, 50GiB लॉग फ़ाइल को हटाने के लिए जो गलती से कॉमेड और धक्का दिया गया था)। द्वारा किया गया git pull
मर्ज अपस्ट्रीम ब्रांच के नए वर्जन को पुराने वर्जन में मर्ज कर देगा जो अभी भी आपके स्थानीय रिपॉजिटरी में मौजूद है। यदि आप परिणाम को आगे बढ़ाते हैं, तो पिच कांटे और मशालें आपके रास्ते में आने लगेंगी।
कुछ तर्क दे सकते हैं कि वास्तविक समस्या बल अद्यतन है। हां, जब भी संभव हो, बल धक्का से बचने के लिए आमतौर पर सलाह दी जाती है, लेकिन वे कभी-कभी अपरिहार्य होते हैं। डेवलपर्स को बल अद्यतन से निपटने के लिए तैयार रहना चाहिए, क्योंकि वे कभी-कभी होते हैं। इसका मतलब यह है कि नेत्रहीन पुराने के माध्यम से एक साधारण में विलय नहीं करता है git pull
।
आश्चर्य कार्य निर्देशिका संशोधन
जब तक काम करने वाली निर्देशिका या इंडेक्स जैसा नहीं होगा तब तक भविष्यवाणी करने का कोई तरीका नहीं git pull
है। इससे पहले कि आप कुछ और कर सकें, इसे आपस में मिलाने के लिए मर्ज संघर्ष हो सकता है, यह आपकी वर्किंग डायरेक्टरी में 50GiB लॉग फाइल को पेश कर सकता है क्योंकि किसी ने गलती से इसे धक्का दे दिया, हो सकता है कि यह उस डायरेक्टरी का नाम बदल दे, जिसमें आप काम कर रहे हैं, आदि।
git remote update -p
(या git fetch --all -p
) आपको मर्ज या रिबेस करने का निर्णय लेने से पहले अन्य लोगों के कमिट्स को देखने की अनुमति देता है, जिससे आप कार्रवाई करने से पहले एक योजना बना सकते हैं।
अन्य लोगों की कमिटियों की समीक्षा करने में कठिनाई
मान लीजिए कि आप कुछ बदलाव करने के लिए बीच में हैं और कोई व्यक्ति चाहता है कि आप कुछ कमिट्स की समीक्षा करें, जिन्हें उन्होंने अभी-अभी पुश किया है। git pull
's मर्ज (या रिबेस) ऑपरेशन काम करने वाली डायरेक्टरी और इंडेक्स को संशोधित करता है, जिसका मतलब है कि आपकी वर्किंग डायरेक्टरी और इंडेक्स साफ होना चाहिए।
आप उपयोग कर सकते हैं git stash
और फिर git pull
, लेकिन जब आप समीक्षा करते हैं तो आप क्या करते हैं? जहाँ आप थे, वहाँ वापस जाने के लिए आपको मर्ज द्वारा बनाए गए git pull
और स्लैश को लागू करना होगा।
git remote update -p
(या git fetch --all -p
) कार्य निर्देशिका या सूचकांक को संशोधित नहीं करता है, इसलिए किसी भी समय चलाना सुरक्षित है - भले ही आपने मंचन किया हो और / या अप्रतिबंधित परिवर्तन किए हों। आप जो कर रहे हैं उस पर विराम लगा सकते हैं और आप जिस काम पर काम कर रहे हैं उसे खत्म करने या खत्म करने की चिंता किए बिना किसी और की प्रतिबद्धता की समीक्षा करें। git pull
आपको वह लचीलापन नहीं देता है।
रिमोट ब्रांच पर रिबासिंग
एक सामान्य Git उपयोग पैटर्न को git pull
नवीनतम परिवर्तनों को लाने के लिए करना है, इसके बाद git rebase @{u}
मर्ज किए गए कमिट को समाप्त करने के लिए git pull
। यह आम पर्याप्त है कि Git कुछ कॉन्फ़िगरेशन को बताकर एक ही चरण के लिए इन दो चरणों कम करने की क्षमता है git pull
किसी मर्ज के बजाय एक रिबेस प्रदर्शन करने के लिए (देखें branch.<branch>.rebase
, branch.autosetuprebase
, और pull.rebase
विकल्प)।
दुर्भाग्यवश, यदि आपके पास कोई अनपेक्षित मर्ज है, जिसे आप संरक्षित करना चाहते हैं (जैसे, एक धक्का सुविधा शाखा को एक में विलय करना master
), तो न तो रिबास-पुल ( सेट के git pull
साथ ) और न ही मर्ज-पुल (डिफ़ॉल्ट व्यवहार) के बाद रिबास काम करेगा। ऐसा इसलिए है क्योंकि विकल्प के बिना मर्ज को समाप्त कर देता है (यह DAG को रेखीय करता है) । रीबेस-पुल ऑपरेशन को मर्ज को संरक्षित करने के लिए कॉन्फ़िगर नहीं किया जा सकता है, और मर्ज-पुल मर्ज-पुल के कारण मर्ज को समाप्त नहीं करेगा। अद्यतन: Git v1.8.5 जोड़ा गया और । अपस्ट्रीम के आने के बाद ऐसा करने का कारण बनता है। ( हेड-अप के लिए कवक के लिए धन्यवाद !)branch.<branch>.rebase
true
git pull
git rebase
--preserve-merges
git rebase -p @{u}
git pull --rebase=preserve
git config pull.rebase preserve
git pull
git rebase --preserve-merges
हटाए गए शाखाओं की सफाई
git pull
दूरस्थ रिपॉजिटरी से हटाए गए शाखाओं के अनुरूप दूरस्थ ट्रैकिंग शाखाएं नहीं छंटती हैं। उदाहरण के लिए, यदि कोई foo
दूरस्थ रेपो से शाखा को हटाता है, तो आप अभी भी देखेंगे origin/foo
।
यह उपयोगकर्ताओं को गलती से मारे गए शाखाओं को फिर से जीवित करने की ओर जाता है क्योंकि उन्हें लगता है कि वे अभी भी सक्रिय हैं।
एक बेहतर विकल्प: के git up
बजाय का उपयोग करेंgit pull
इसके बजाय git pull
, मैं निम्नलिखित git up
उपनाम बनाने और उपयोग करने की सलाह देता हूं :
git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'
यह उपनाम सभी अपस्ट्रीम शाखाओं (मृत शाखाओं को काटता है) से सभी नवीनतम आवागमन डाउनलोड करता है और स्थानीय शाखा को अपस्ट्रीम शाखा पर नवीनतम प्रतिबद्ध करने के लिए तेजी से अग्रेषित करने का प्रयास करता है। यदि सफल हुआ, तो स्थानीय कमिट नहीं थे, इसलिए मर्ज संघर्ष का कोई जोखिम नहीं था। यदि स्थानीय (अप्रकाशित) कमिट हैं, तो फास्ट-फ़ॉर्वर्ड आगे विफल हो जाएगा, जिससे आपको कार्रवाई से पहले अपस्ट्रीम कमिट्स की समीक्षा करने का अवसर मिलेगा।
यह अभी भी अप्रत्याशित तरीके से आपकी कामकाजी निर्देशिका को संशोधित करता है, लेकिन केवल अगर आपके पास कोई स्थानीय परिवर्तन नहीं है। इसके विपरीत git pull
, git up
आप एक मर्ज संघर्ष को ठीक करने की उम्मीद करते हुए आपको कभी नहीं छोड़ेंगे।
एक अन्य विकल्प: git pull --ff-only --all -p
निम्नलिखित उपरोक्त git up
उपनाम का एक विकल्प है :
git config --global alias.up 'pull --ff-only --all -p'
इस संस्करण में git up
पिछले git up
उपनाम के समान व्यवहार है , इसके अलावा:
- यदि आपकी स्थानीय शाखा एक अपस्ट्रीम शाखा से कॉन्फ़िगर नहीं है, तो त्रुटि संदेश थोड़ा अधिक गूढ़ है
- यह एक अनिर्दिष्ट सुविधा (
-p
तर्क, जो इसे पारित किया गया है fetch
) पर निर्भर करता है जो भविष्य के Git के संस्करणों में बदल सकता है
अगर आप Git 2.0 या नया चला रहे हैं
Git 2.0 और नए के साथ आप git pull
केवल डिफ़ॉल्ट रूप से फास्ट-फॉरवर्ड मर्ज करने के लिए कॉन्फ़िगर कर सकते हैं :
git config --global pull.ff only
यह git pull
कार्य करने का कारण बनता है git pull --ff-only
, लेकिन यह अभी भी सभी अपस्ट्रीम कमिट नहीं करता है या पुरानी origin/*
शाखाओं को साफ नहीं करता है, इसलिए मैं अभी भी पसंद करता हूं git up
।