एक डेवलपर के रूप में, आप हर समय गिट के साथ काम करते हैं।
क्या आप कभी उस बिंदु पर पहुंचे जहां आपने कहा: "उह-ओह, मैंने अभी क्या किया?"
यह पोस्ट आपको विश्वास के साथ इतिहास को फिर से लिखने के लिए टूल देगी।
मैंने इस पोस्ट की सामग्री को कवर करते हुए एक लाइव वार्ता भी की। यदि आप एक वीडियो पसंद करते हैं (या इसे पढ़ने के साथ-साथ देखना चाहते हैं) - आप इसे पा सकते हैं
मैं गिट के बारे में एक किताब पर काम कर रहा हूं! क्या आप शुरुआती संस्करणों को पढ़ने और प्रतिक्रिया देने में रुचि रखते हैं? मुझे एक ईमेल भेजें: [email protected]
Git में चीजों को पूर्ववत करने के तरीके को समझने से पहले, आपको पहले यह समझना चाहिए कि हम Git में परिवर्तनों को कैसे रिकॉर्ड करते हैं । यदि आप पहले से ही सभी शर्तें जानते हैं, तो बेझिझक इस भाग को छोड़ दें।
समय में फ़ाइल सिस्टम के स्नैपशॉट को रिकॉर्ड करने के लिए एक प्रणाली के रूप में गिट के बारे में सोचना बहुत उपयोगी है। गिट रिपॉजिटरी को ध्यान में रखते हुए, इसके तीन "राज्य" या "पेड़" हैं:
आमतौर पर, जब हम अपने सोर्स कोड पर काम करते हैं, तो हम एक वर्किंग डायरेक्टर से काम करते हैं। एक कार्यकारी निदेशक (एक्ट्रोरी) (या काम करने वाला पेड़ ) हमारे फाइल सिस्टम में कोई निर्देशिका है जिसमें इसके साथ एक भंडार जुड़ा हुआ है।
इसमें हमारे प्रोजेक्ट के फोल्डर और फाइलें होती हैं और .git
नामक एक डायरेक्टरी भी होती है। मैंने .git
फ़ोल्डर की सामग्री का अधिक विस्तार से वर्णन किया है
आपके द्वारा कुछ परिवर्तन करने के बाद, हो सकता है कि आप उन्हें अपनी रिपॉजिटरी में रिकॉर्ड करना चाहें। एक रिपॉजिटरी (संक्षेप में: रेपो ) कमिट्स का एक संग्रह है, जिनमें से प्रत्येक इस बात का एक संग्रह है कि प्रोजेक्ट का वर्किंग ट्री पिछली तारीख में कैसा दिखता था, चाहे वह आपकी मशीन पर हो या किसी और का।
एक रिपॉजिटरी में हमारी कोड फ़ाइलों के अलावा अन्य चीज़ें भी शामिल होती हैं, जैसे कि HEAD
, शाखाएँ, आदि।
बीच में, हमारे पास इंडेक्स या स्टेजिंग एरिया है; ये दो शब्द विनिमेय हैं। जब हम एक शाखा checkout
, तो गिट इंडेक्स को उन सभी फ़ाइल सामग्री के साथ पॉप्युलेट करता है जिन्हें पिछली बार हमारी कार्यशील निर्देशिका में चेक आउट किया गया था और मूल रूप से चेक आउट होने पर वे क्या दिखते थे।
जब हम git commit
उपयोग करते हैं, तो इंडेक्स की स्थिति के आधार पर कमिट बनाया जाता है।
तो, इंडेक्स, या स्टेजिंग एरिया, अगले कमिट के लिए आपका खेल का मैदान है। आप इंडेक्स के साथ जो चाहें काम कर सकते हैं और कर सकते हैं, इसमें फाइलें जोड़ सकते हैं, इससे चीजें हटा सकते हैं, और उसके बाद ही जब आप तैयार हों, तो आप आगे बढ़ें और रिपॉजिटरी के लिए प्रतिबद्ध हों।
हाथ मिलाने का समय 🙌🏻
नए रिपॉजिटरी को इनिशियलाइज़ करने के लिए git init
उपयोग करें। 1.txt
नामक फ़ाइल में कुछ टेक्स्ट लिखें:
ऊपर बताए गए तीन ट्री स्टेट्स में से अब 1.txt
कहां है?
वर्किंग ट्री में, क्योंकि इसे अभी तक इंडेक्स में पेश नहीं किया गया है।
इसे चरणबद्ध करने के लिए, इसे अनुक्रमणिका में जोड़ने के लिए, git add 1.txt
का उपयोग करें।
अब, हम रिपॉजिटरी में अपने परिवर्तन करने के लिए git commit
उपयोग कर सकते हैं।
आपने एक नया कमिट ऑब्जेक्ट बनाया है, जिसमें पूरे वर्किंग ट्री का वर्णन करने वाले ट्री के लिए एक पॉइंटर शामिल है। इस स्थिति में, यह रूट फ़ोल्डर में केवल 1.txt
होगा। ट्री के लिए एक पॉइंटर के अलावा, प्रतिबद्ध वस्तु में मेटाडेटा भी शामिल है, जैसे टाइमस्टैम्प और लेखक की जानकारी।
गिट में वस्तुओं के बारे में अधिक जानकारी के लिए (जैसे कमिट और पेड़),
(हां, "चेक आउट", यमक इरादा 😇)
Git हमें इस प्रतिबद्ध वस्तु का SHA-1 मान भी बताता है। मेरे मामले में, यह c49f4ba
था (जो कुछ स्थान बचाने के लिए SHA-1 मान के केवल पहले 7 वर्ण हैं)।
यदि आप इस आदेश को अपनी मशीन पर चलाते हैं, तो आपको एक अलग SHA-1 मान मिलेगा, क्योंकि आप एक अलग लेखक हैं; साथ ही, आप एक अलग टाइमस्टैम्प पर प्रतिबद्धता बनायेंगे।
जब हम रेपो को इनिशियलाइज़ करते हैं, तो Git एक नई शाखा बनाता है (डिफ़ॉल्ट रूप से main
नाम)। औरmain
शाखा है। यदि आपकी कई शाखाएँ हैं तो क्या होगा? गिट कैसे जानता है कि कौन सी शाखा सक्रिय शाखा है?
गिट के पास HEAD
नामक एक और सूचक है, जो एक शाखा को इंगित करता है (आमतौर पर), जो तब एक प्रतिबद्धता को इंगित करता है। वैसे,HEAD
रेपो में और बदलाव लाने का समय!
अब, मैं एक और बनाना चाहता हूँ। तो चलिए एक नई फाइल बनाते हैं, और इसे पहले की तरह इंडेक्स में जोड़ते हैं:
अब, git commit
उपयोग करने का समय आ गया है। महत्वपूर्ण रूप से, git commit
दो काम करता है:
सबसे पहले, यह एक कमिट ऑब्जेक्ट बनाता है, इसलिए Git के आंतरिक ऑब्जेक्ट डेटाबेस में संबंधित SHA-1 मान के साथ एक ऑब्जेक्ट होता है। यह नया कमिट ऑब्जेक्ट पेरेंट कमिट की ओर भी इशारा करता है। जब आप git commit
कमांड लिखते हैं तो HEAD
उस ओर इशारा करता है।
दूसरा, git commit
सक्रिय शाखा के पॉइंटर को ले जाता है - हमारे मामले में, यह main
होगा, नव निर्मित कमिट ऑब्जेक्ट को इंगित करने के लिए।
इतिहास को फिर से लिखने के लिए, आइए कमिट करने की प्रक्रिया को पूर्ववत करके शुरू करें। उसके लिए, हम कमांड git reset
जानेंगे, जो एक सुपर पावरफुल टूल है।
git reset --soft
तो आपके द्वारा पहले किया गया अंतिम चरण git commit
था, जिसका वास्तव में दो अर्थ है - Git ने एक कमिट ऑब्जेक्ट बनाया और main
, सक्रिय शाखा को स्थानांतरित किया। इस चरण को पूर्ववत करने के लिए, git reset --soft HEAD~1
कमांड का उपयोग करें।
सिंटैक्स HEAD~1
HEAD
के पहले जनक को संदर्भित करता है। यदि मेरे पास कमिट-ग्राफ में एक से अधिक कमिट हैं, तो "कमिट 3" को "कमिट 2" की ओर इशारा करते हुए कहें, जो बदले में "कमिट 1" की ओर इशारा करता है।
और कहते हैं कि HEAD
"कमिट 3" की ओर इशारा कर रहा था। आप "कमिट 2" को संदर्भित करने के लिए HEAD~1
का उपयोग कर सकते हैं, और HEAD~2
"कमिट 1" को संदर्भित करेगा।
तो, कमांड पर वापस जाएँ: git reset --soft HEAD~1
यह आदेश गिट को जो भी HEAD
इंगित कर रहा है उसे बदलने के लिए कहता है। (ध्यान दें: नीचे दिए गए आरेखों में, मैं "जो भी HEAD
इंगित कर रहा है" के लिए *HEAD
उपयोग करता हूं)। हमारे उदाहरण में, HEAD
main
की ओर इशारा कर रहा है। तो गिट केवल main
के सूचक को HEAD~1
पर इंगित करने के लिए बदल देगा। यही है, main
"कमिट 1" को इंगित करेगा।
हालाँकि, यह कमांड इंडेक्स या वर्किंग ट्री की स्थिति को प्रभावित नहीं करता है। इसलिए यदि आप git status
उपयोग करते हैं, तो आप देखेंगे कि 2.txt
मंचन किया गया है, ठीक उसी तरह जैसे आपने git commit
किया था।
git log?
यह HEAD
से शुरू होगा, main
पर जाएगा, और फिर "Commit 1" पर जाएगा। ध्यान दें कि इसका मतलब है कि "कमिट 2" अब हमारे इतिहास से उपलब्ध नहीं है।
क्या इसका मतलब है कि "कमिट 2" की प्रतिबद्ध वस्तु हटा दी गई है? 🤔
नहीं, इसे हटाया नहीं गया है। यह अभी भी गिट के ऑब्जेक्ट्स के आंतरिक ऑब्जेक्ट डेटाबेस में रहता है।
यदि आप वर्तमान इतिहास को अभी पुश करते हैं, तो git push
उपयोग करके, Git "कमिट 2" को दूरस्थ सर्वर पर नहीं धकेलेगा, लेकिन रिपॉजिटरी की आपकी स्थानीय प्रति पर कमिट ऑब्जेक्ट अभी भी मौजूद है।
अब, फिर से कमिट करें - और इस नए ऑब्जेक्ट को मूल "कमिट 2" से अलग करने के लिए "कमिट 2.1" के कमिट संदेश का उपयोग करें:
"कमिट 2" और "कमिट 2.1" अलग क्यों हैं? भले ही हम एक ही प्रतिबद्ध संदेश का उपयोग करते हों, और भले ही वे इशारा करते हों1.txt
और 2.txt
वाले रूट फ़ोल्डर में), उनके पास अभी भी अलग-अलग टाइमस्टैम्प हैं, क्योंकि वे अलग-अलग समय पर बनाए गए थे।
ऊपर की ड्राइंग में, मैंने आपको याद दिलाने के लिए "कमिट 2" रखा है कि यह अभी भी Git के आंतरिक ऑब्जेक्ट डेटाबेस में मौजूद है। "कमिट 2" और "कमिट 2.1" दोनों अब "कमिट 1" की ओर इशारा करते हैं, लेकिन केवल "कमिट 2.1" ही HEAD
से उपलब्ध है।
यह और भी पीछे जाने और आगे पूर्ववत करने का समय है। इस बार, git reset --mixed HEAD~1
का उपयोग करें (ध्यान दें: --mixed
git reset
के लिए डिफ़ॉल्ट स्विच है)।
यह आदेश git reset --soft HEAD~1
के समान प्रारंभ होता है। इसका मतलब यह है कि जो कुछ भी HEAD
अब इंगित कर रहा है, जो कि main
शाखा है, का सूचक लेता है, और इसे हमारे उदाहरण में HEAD~1
पर सेट करता है - "कमिट 1"।
इसके बाद, गिट आगे बढ़ता है, इंडेक्स में किए गए परिवर्तनों को प्रभावी ढंग से पूर्ववत करता है। यानी इंडेक्स को बदलना ताकि यह पहले चरण में सेट करने के बाद मौजूदा HEAD
, नए HEAD
के साथ मेल खाए।
अगर हम git reset --mixed HEAD~1
चलाते हैं, तो इसका मतलब है कि HEAD
HEAD~1
("कमिट 1") पर सेट किया जाएगा, और फिर Git इंडेक्स को "कमिट 1" की स्थिति से मिलाएगा - इस मामले में, यह इसका मतलब है कि 2.txt
अब इंडेक्स का हिस्सा नहीं रहेगा।
मूल "कमिट 2" की स्थिति के साथ एक नई प्रतिबद्धता बनाने का समय आ गया है। इस बार हमें इसे बनाने से पहले 2.txt
फिर से चरणबद्ध करने की आवश्यकता है:
आगे बढ़ें, और भी पूर्ववत करें!
आगे बढ़ो और git reset --hard HEAD~1
चलाएं
फिर से, Git --soft
चरण से शुरू होता है, जो कुछ भी HEAD
( main
) की ओर इशारा करता है, उसे HEAD~1
("कमिट 1") पर सेट करता है।
अब तक तो सब ठीक है।
अगला, --mixed
चरण पर आगे बढ़ते हुए, इंडेक्स को HEAD
से मिलाते हुए। यही है, गिट 2.txt
के मंचन को पूर्ववत करता है।
यह --hard
कदम का समय है जहां गिट और भी आगे जाता है और इंडेक्स के चरण के साथ काम कर रहे डीआईआर से मेल खाता है। इस मामले में, इसका अर्थ है 2.txt
कार्यशील डायर से भी हटाना।
(** नोट: इस विशिष्ट मामले में, फ़ाइल अनट्रैक है, इसलिए इसे फ़ाइल सिस्टम से हटाया नहीं जाएगा; हालांकि git reset
समझने के लिए यह वास्तव में महत्वपूर्ण नहीं है)।
इसलिए Git में बदलाव लाने के लिए आपके पास तीन चरण हैं। आप वर्किंग डायर, इंडेक्स या स्टेजिंग एरिया को बदलते हैं, और फिर आप उन बदलावों के साथ एक नया स्नैपशॉट बनाते हैं। इन परिवर्तनों को पूर्ववत करने के लिए:
git reset --soft
उपयोग करते हैं, तो हम कमिट स्टेप को पूर्ववत कर देते हैं।
git reset --mixed
उपयोग करते हैं, तो हम स्टेजिंग चरण को भी पूर्ववत कर देते हैं।
git reset --hard
उपयोग करते हैं, तो हम कार्यशील डायर में परिवर्तन पूर्ववत करते हैं। इसलिए वास्तविक जीवन के परिदृश्य में, "I love Git" को एक फ़ाइल ( love.txt
) में लिखें, जैसा कि हम सभी Git 😍 से प्यार करते हैं। आगे बढ़ो, मंच और इसे भी प्रतिबद्ध करें:
ओह, उफ़!
दरअसल, मैं नहीं चाहता था कि आप इसे प्रतिबद्ध करें।
मैं वास्तव में चाहता था कि आप इसे करने से पहले इस फ़ाइल में कुछ और प्रेम शब्द लिखें।
आप क्या कर सकते हैं?
खैर, इसे दूर करने का एक तरीका git reset --mixed HEAD~1
उपयोग करना होगा, प्रभावी रूप से आपके द्वारा की गई कमिटिंग और स्टेजिंग दोनों क्रियाओं को पूर्ववत करना:
तो फिर से "कमिट 1" के main
बिंदु, और love.txt
अब इंडेक्स का हिस्सा नहीं है। हालाँकि, फ़ाइल कार्यशील निर्देशिका में बनी हुई है। अब आप आगे बढ़ सकते हैं, और इसमें और सामग्री जोड़ सकते हैं:
आगे बढ़ो, मंच और अपनी फ़ाइल प्रतिबद्ध करें:
शाबाश 👏🏻
आपको "कमिट 1" की ओर इशारा करते हुए "कमिट 2.4" का यह स्पष्ट, अच्छा इतिहास मिला।
अब हमारे टूलबॉक्स में एक नया टूल है, git reset
💪🏻
यह उपकरण अत्यंत उपयोगी है, अत्यधिक उपयोगी है, और आप इसके साथ लगभग कुछ भी पूरा कर सकते हैं। यह हमेशा उपयोग करने के लिए सबसे सुविधाजनक उपकरण नहीं होता है, लेकिन यदि आप इसे सावधानीपूर्वक उपयोग करते हैं तो यह लगभग किसी भी पुनर्लेखन-इतिहास परिदृश्य को हल करने में सक्षम है।
नौसिखियों के लिए, मेरा सुझाव है कि जब भी आप गिट में पूर्ववत करना चाहते हैं तो केवल git reset
उपयोग करें। एक बार जब आप इसके साथ सहज महसूस करते हैं, तो अन्य उपकरणों पर जाने का समय आ गया है।
आइए एक और मामले पर विचार करें।
new.txt
नामक एक नई फाइल बनाएं; मंच और प्रतिबद्ध:
उफ़। दरअसल, यह एक गलती है। आप main
पर थे, और मैं चाहता था कि आप इस कमिट को फीचर ब्रांच पर बनाएं। मेरा बुरा 😇
मैं चाहता हूं कि आप इस पोस्ट से दो सबसे महत्वपूर्ण उपकरण लें। दूसरा है git reset
। पहला और कहीं अधिक महत्वपूर्ण यह है कि वर्तमान स्थिति बनाम आप जिस राज्य में रहना चाहते हैं , उसे व्हाइटबोर्ड करना है ।
इस परिदृश्य के लिए, वर्तमान स्थिति और वांछित स्थिति इस तरह दिखती है:
आप तीन बदलाव देखेंगे:
वर्तमान स्थिति में "कमिट 3" (नीला वाला) के main
बिंदु, लेकिन वांछित स्थिति में "कमिट 2.4"।
feature
शाखा वर्तमान स्थिति में मौजूद नहीं है, फिर भी यह मौजूद है और वांछित स्थिति में "कमिट 3" की ओर इशारा करती है।
HEAD
वर्तमान स्थिति में main
की ओर इशारा करता है, और वांछित स्थिति में feature
के लिए।
यदि आप इसे आकर्षित कर सकते हैं और आप git reset
उपयोग करना जानते हैं, तो आप निश्चित रूप से इस स्थिति से बाहर निकल सकते हैं।
तो फिर, सबसे महत्वपूर्ण बात यह है कि सांस लें और इसे बाहर निकालें।
उपरोक्त आरेखण को देखते हुए, हम वर्तमान स्थिति से वांछित स्थिति तक कैसे पहुँच सकते हैं?
बेशक कुछ अलग तरीके हैं, लेकिन मैं प्रत्येक परिदृश्य के लिए केवल एक विकल्प प्रस्तुत करूंगा। अन्य विकल्पों के साथ भी खेलने के लिए स्वतंत्र महसूस करें।
आप git reset --soft HEAD~1
उपयोग करके प्रारंभ कर सकते हैं। यह पिछले कमिट, "कमिट 2.4" को इंगित करने के लिए main
सेट करेगा:
वर्तमान-बनाम-वांछित आरेख पर फिर से झाँकते हुए, आप देख सकते हैं कि आपको एक नई शाखा की आवश्यकता है, है ना? आप इसके लिए git switch -c feature
या git checkout -b feature
(जो एक ही काम करता है) का उपयोग कर सकते हैं:
यह आदेश नई शाखा को इंगित करने के लिए HEAD
भी अद्यतन करता है।
चूंकि आपने git reset --soft
उपयोग किया है, आपने इंडेक्स को नहीं बदला है, इसलिए वर्तमान में यह वही स्थिति है जिसे आप कमिट करना चाहते हैं - कितना सुविधाजनक है! आप बस feature
शाखा के लिए प्रतिबद्ध हो सकते हैं:
और आप वांछित स्थिति में पहुंच गए 🎉
अपने ज्ञान को अतिरिक्त मामलों में लागू करने के लिए तैयार हैं?
love.txt
में कुछ बदलाव जोड़ें, और cool.txt
नाम की एक नई फाइल भी बनाएं। उन्हें चरणबद्ध करें और प्रतिबद्ध करें:
ओह, उफ़, वास्तव में मैं चाहता था कि आप दो अलग-अलग कमिट बनाएं, प्रत्येक परिवर्तन के साथ एक 🤦🏻
इसे स्वयं आजमाना चाहते हैं?
आप कमिटिंग और स्टेजिंग चरणों को पूर्ववत कर सकते हैं:
इस आदेश के बाद, अनुक्रमणिका में अब वे दो परिवर्तन शामिल नहीं हैं, लेकिन वे दोनों अभी भी आपके फ़ाइल सिस्टम में हैं। तो अब, यदि आप केवल love.txt
मंचित करते हैं, तो आप इसे अलग से कर सकते हैं, और फिर cool.txt
के लिए भी ऐसा ही कर सकते हैं:
अच्छा 😎
कुछ पाठ के साथ एक नई फ़ाइल ( new_file.txt
) बनाएँ, और love.txt
में कुछ पाठ जोड़ें। चरण दोनों बदलते हैं, और उन्हें प्रतिबद्ध करते हैं:
उफ़ 🙈🙈
तो इस बार, मैं चाहता था कि यह दूसरी शाखा पर हो, लेकिन एक नई शाखा नहीं, बल्कि पहले से मौजूद शाखा।
तो आप क्या कर सकते हैं?
मैं आपको एक संकेत देता हूँ। उत्तर वास्तव में छोटा और वास्तव में आसान है। हम पहले क्या करते हैं?
नहीं, reset
नहीं। हम चित्र बनाते हैं। यह करने के लिए पहली चीज है, क्योंकि यह बाकी सब कुछ इतना आसान बना देगी। तो ये है मौजूदा स्थिति:
और वांछित अवस्था?
आप वर्तमान स्थिति से वांछित स्थिति में कैसे जाते हैं, सबसे आसान क्या होगा?
तो एक तरीका यह होगा कि आप पहले की तरह git reset
उपयोग करें, लेकिन एक और तरीका है जिसे मैं चाहूंगा कि आप कोशिश करें।
सबसे पहले, existing
शाखा को इंगित करने के लिए HEAD
स्थानांतरित करें:
सहज रूप से, आप जो करना चाहते हैं वह ब्लू कमिट में पेश किए गए परिवर्तनों को लेना है, और इन परिवर्तनों ("कॉपी-पेस्ट") को existing
शाखा के शीर्ष पर लागू करना है। और गिट के पास इसके लिए एक टूल है।
Git को इस कमिट और उसके पैरेंट कमिट के बीच शुरू किए गए परिवर्तनों को लेने के लिए कहने के लिए और इन परिवर्तनों को केवल सक्रिय शाखा पर लागू करने के लिए, आप git cherry-pick
उपयोग कर सकते हैं। यह कमांड निर्दिष्ट संशोधन में पेश किए गए परिवर्तनों को लेता है और उन्हें सक्रिय कमिट पर लागू करता है।
यह एक नई प्रतिबद्ध वस्तु भी बनाता है, और इस नई वस्तु को इंगित करने के लिए सक्रिय शाखा को अद्यतन करता है।
ऊपर दिए गए उदाहरण में, मैंने बनाए गए कमिट के SHA-1 पहचानकर्ता को निर्दिष्ट किया है, लेकिन आप git cherry-pick main
उपयोग भी कर सकते हैं, क्योंकि जिस कमिट के परिवर्तन हम लागू कर रहे हैं, वह एक main
की ओर इशारा कर रहा है।
लेकिन हम नहीं चाहते कि ये परिवर्तन main
शाखा पर मौजूद हों। git cherry-pick
केवल existing
शाखा में परिवर्तन लागू करता है। आप उन्हें main
से कैसे निकाल सकते हैं?
एक तरीका यह होगा कि आप main
पर वापस switch
, और फिर git reset --hard HEAD~1
उपयोग करें:
तुमने यह किया! 💪🏻
ध्यान दें कि git cherry-pick
वास्तव में निर्दिष्ट प्रतिबद्धता और उसके माता-पिता के बीच अंतर की गणना करता है, और उसके बाद उन्हें सक्रिय प्रतिबद्धता पर लागू करता है। इसका अर्थ है कि कभी-कभी, Git उन परिवर्तनों को लागू करने में सक्षम नहीं होगा, क्योंकि आपको विरोध हो सकता है, लेकिन यह किसी अन्य पोस्ट के लिए एक विषय है।
साथ ही, ध्यान दें कि आप गिट को किसी भी प्रतिबद्धता में पेश किए गए परिवर्तनों को cherry-pick
के लिए कह सकते हैं, न केवल शाखा द्वारा संदर्भित।
हमने एक नया टूल हासिल कर लिया है, इसलिए हमारे पास बेल्ट के नीचे git reset
के साथ-साथ git cherry-pick
भी है।
ठीक है, तो एक और दिन, एक और रेपो, एक और समस्या।
कमिट बनाएं:
और इसे दूरस्थ सर्वर पर push
:
उम, उफ़ 😓…
मैंने अभी कुछ देखा। वहां एक टाइपो है। मैंने लिखा This is more tezt
This is more text
अधिक तेज़ है। वूप्स। तो अब बड़ी समस्या क्या है? मैं एड को push
, जिसका अर्थ है कि किसी और ने पहले ही उन परिवर्तनों को pull
होगा।
यदि मैं git reset
उपयोग करके उन परिवर्तनों को ओवरराइड करता हूं, जैसा कि हमने अभी तक किया है, तो हमारे पास अलग-अलग इतिहास होंगे, और सभी नरक ढीले हो सकते हैं। जब तक आप इसे push
तब तक आप रेपो की अपनी कॉपी को जितना चाहें उतना दोबारा लिख सकते हैं।
एक बार जब आप परिवर्तन को push
, तो आपको यह सुनिश्चित करने की आवश्यकता होती है कि यदि आप इतिहास को फिर से लिखने जा रहे हैं तो किसी और ने उन परिवर्तनों को प्राप्त नहीं किया है।
वैकल्पिक रूप से, आप git revert
नामक एक अन्य टूल का उपयोग कर सकते हैं। यह आदेश उस प्रतिबद्धता को लेता है जिसे आप प्रदान कर रहे हैं और डिफ को अपने मूल प्रतिबद्धता से git cherry-pick
की तरह गणना करता है, लेकिन इस बार, यह रिवर्स परिवर्तनों की गणना करता है।
इसलिए यदि निर्दिष्ट कमिट में आपने एक लाइन जोड़ी है, तो रिवर्स लाइन को हटा देगा, और इसके विपरीत।
git revert
एक नई प्रतिबद्ध वस्तु बनाई, जिसका अर्थ है कि यह इतिहास के लिए एक अतिरिक्त है। git revert
उपयोग करके, आपने इतिहास को दोबारा नहीं लिखा। आपने अपनी पिछली गलती को स्वीकार किया, और यह प्रतिबद्धता एक स्वीकारोक्ति है कि आपने गलती की और अब आपने इसे ठीक कर लिया है।
कुछ कहेंगे कि यह अधिक परिपक्व तरीका है। कुछ लोग कहेंगे कि यह उतना साफ इतिहास नहीं है जितना कि अगर आप पिछले कमिट को फिर से लिखने के लिए git reset
इस्तेमाल करते हैं तो आपको मिलेगा। लेकिन यह इतिहास के पुनर्लेखन से बचने का एक तरीका है।
अब आप टाइपो को ठीक कर सकते हैं और दोबारा प्रतिबद्ध कर सकते हैं:
आपका टूलबॉक्स अब एक नए चमकदार टूल से लोड हो गया है, revert
:
कुछ काम पूरा करें, कुछ कोड लिखें और इसे love.txt
में जोड़ें। इस परिवर्तन को चरणबद्ध करें, और इसे प्रतिबद्ध करें:
मैंने अपनी मशीन पर ऐसा ही किया, और मैंने पिछले आदेशों पर वापस स्क्रॉल करने के लिए अपने कीबोर्ड पर Up
तीर कुंजी का उपयोग किया, और फिर मैंने Enter
मारा, और ... वाह।
वूप्स।
क्या मैंने अभी git reset --hard
उपयोग किया है? 😨
वास्तव में क्या हुआ? गिट ने पॉइंटर को HEAD~1
पर ले जाया, इसलिए अंतिम प्रतिबद्धता, मेरे सभी बहुमूल्य कार्यों के साथ, वर्तमान इतिहास से पहुंच योग्य नहीं है। Git ने स्टेजिंग एरिया से सभी बदलावों को भी अनस्टेज किया, और फिर स्टेजिंग एरिया की स्थिति के लिए वर्किंग डायर का मिलान किया।
यानी सब कुछ इस राज्य से मेल खाता है जहां मेरा काम है... चला गया।
अजीब समय। मस्ती कर रहे हैं।
लेकिन, क्या वास्तव में घबराने का कोई कारण है? वास्तव में नहीं... हम निश्चिंत लोग हैं। हम क्या करते हैं? खैर, सहजता से, क्या वास्तव में प्रतिबद्धता वास्तव में चली गई है? क्यों कोई नहीं? यह अभी भी गिट के आंतरिक डेटाबेस के अंदर मौजूद है।
अगर मुझे केवल यह पता होता कि वह कहाँ है, तो मुझे SHA-1 मान पता होगा जो इस कमिट की पहचान करता है, हम इसे पुनर्स्थापित कर सकते हैं। मैं पूर्ववत भी पूर्ववत कर सकता था, और इस प्रतिबद्धता पर वापस आ reset
।
तो केवल एक चीज जिसकी मुझे वास्तव में आवश्यकता है, वह है "हटाए गए" कमिट का SHA-1।
तो सवाल यह है कि मैं इसे कैसे ढूंढूं? क्या git log
उपयोगी होगा?
सचमुच में ठीक नहीं। git log
HEAD
पर जाएगा, जो main
को इंगित करता है, जो उस प्रतिबद्धता की मूल प्रतिबद्धता को इंगित करता है जिसे हम ढूंढ रहे हैं। फिर, git log
मूल श्रृंखला के माध्यम से वापस आ जाएगा, जिसमें मेरे बहुमूल्य काम के साथ प्रतिबद्धता शामिल नहीं है।
शुक्र है, गिट बनाने वाले बहुत ही चतुर लोगों ने हमारे लिए एक बैकअप योजना भी बनाई, और इसे reflog
कहा जाता है।
जब आप गिट के साथ काम करते हैं, जब भी आप HEAD
बदलते हैं, जिसे आप git reset
उपयोग करके कर सकते हैं, लेकिन git switch
या git checkout
जैसे अन्य आदेश भी, गिट reflog
में एक प्रविष्टि जोड़ता है।
हमने अपनी प्रतिबद्धता पाई! यह वह है जो 0fb929e
से शुरू होता है।
हम इसके "उपनाम" - HEAD@{1}
से भी संबंधित हो सकते हैं। तो जैसे कि गिट HEAD
के पहले माता-पिता को पाने के लिए HEAD~1
का उपयोग करता है, और HEAD~2
HEAD
के दूसरे माता-पिता को संदर्भित करने के लिए और इसी तरह, गिट HEAD@{1}
का उपयोग HEAD
के पहले रीफ्लॉग माता-पिता को संदर्भित करने के लिए करता है, जहां HEAD
पिछले चरण में इशारा किया था।
हम इसका मूल्य दिखाने के लिए git rev-parse
भी पूछ सकते हैं:
reflog
देखने का एक और तरीका git log -g
का उपयोग करना है, जो git log
वास्तव में reflog
पर विचार करने के लिए कहता है:
हम ऊपर देखते हैं कि reflog
, ठीक उसी तरह जैसे HEAD
, main
की ओर इशारा करता है, जो "कमिट 2" की ओर इशारा करता है। लेकिन reflog
में उस प्रविष्टि का जनक "कमिट 3" की ओर इशारा करता है।
तो "कमिट 3" पर वापस जाने के लिए, आप बस git reset --hard HEAD@{1}
(या "कमिट 3" का SHA-1 मान) का उपयोग कर सकते हैं:
और अब, अगर हम git log
:
हमने दिन बचा लिया! 🎉👏🏻
यदि मैं इस आदेश का दोबारा उपयोग करूं तो क्या होगा? और git commit --reset HEAD@{1}
चलाया? Git HEAD
उस स्थान पर सेट करेगा जहाँ HEAD
अंतिम reset
से पहले इंगित कर रहा था, जिसका अर्थ है "कमिट 2"। हम पूरे दिन चलते रह सकते हैं:
अब हमारे टूलबॉक्स को देखते हुए, यह ऐसे टूल से भरा हुआ है जो आपको कई मामलों को हल करने में मदद कर सकता है जहां गिट में चीजें गलत हो जाती हैं:
इन उपकरणों के साथ, अब आप बेहतर ढंग से समझ गए हैं कि Git कैसे काम करता है। ऐसे और भी उपकरण हैं जो आपको विशेष रूप से इतिहास को फिर से लिखने की अनुमति देंगे, git rebase
), लेकिन आप इस पोस्ट में पहले ही बहुत कुछ सीख चुके हैं। भविष्य के पदों में, मैं git rebase
में भी गोता लगाऊंगा।
सबसे महत्वपूर्ण उपकरण, इस टूलबॉक्स में सूचीबद्ध पांच टूल से भी अधिक महत्वपूर्ण, वर्तमान स्थिति बनाम वांछित स्थिति को व्हाइटबोर्ड करना है। इस पर मेरा भरोसा करें, यह हर स्थिति को कम चुनौतीपूर्ण और समाधान को अधिक स्पष्ट बना देगा।
मैंने इस पोस्ट की सामग्री को कवर करते हुए एक लाइव वार्ता भी की। यदि आप एक वीडियो पसंद करते हैं (या इसे पढ़ने के साथ-साथ देखना चाहते हैं) - आप इसे पा सकते हैं
सामान्य रूप में,
ओमर ने तेल अवीव विश्वविद्यालय से भाषाविज्ञान में एमए किया है और इसके निर्माता हैं
सबसे पहले यहाँ प्रकाशित हुआ