paint-brush
विश्वास के साथ गिट इतिहास का पुनर्लेखन: एक गाइडद्वारा@omerosenbaum
2,007 रीडिंग
2,007 रीडिंग

विश्वास के साथ गिट इतिहास का पुनर्लेखन: एक गाइड

द्वारा Omer Rosenbaum18m2023/04/27
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

Git एक फाइलसिस्टम के स्नैपशॉट को समय पर रिकॉर्ड करने के लिए एक प्रणाली है। Git रिपॉजिटरी में तीन "स्टेट्स" या "ट्रीज़" होते हैं: इंडेक्स, स्टेजिंग एरिया और वर्किंग ट्री। एक कार्यशील निर्देशिका (एक्ट्रोरी) हमारे फाइल सिस्टम पर कोई निर्देशिका है जिसमें इसके साथ गिट रेपो जुड़ा हुआ है।
featured image - विश्वास के साथ गिट इतिहास का पुनर्लेखन: एक गाइड
Omer Rosenbaum HackerNoon profile picture

एक डेवलपर के रूप में, आप हर समय गिट के साथ काम करते हैं।


क्या आप कभी उस बिंदु पर पहुंचे जहां आपने कहा: "उह-ओह, मैंने अभी क्या किया?"

जब गिट के साथ चीजें गलत हो जाती हैं, तो कई इंजीनियर असहाय महसूस करते हैं (स्रोत: XKCD)


यह पोस्ट आपको विश्वास के साथ इतिहास को फिर से लिखने के लिए टूल देगी।

शुरू करने से पहले नोट्स

  1. मैंने इस पोस्ट की सामग्री को कवर करते हुए एक लाइव वार्ता भी की। यदि आप एक वीडियो पसंद करते हैं (या इसे पढ़ने के साथ-साथ देखना चाहते हैं) - आप इसे पा सकते हैं .


  2. मैं गिट के बारे में एक किताब पर काम कर रहा हूं! क्या आप शुरुआती संस्करणों को पढ़ने और प्रतिक्रिया देने में रुचि रखते हैं? मुझे एक ईमेल भेजें: [email protected]

Git में रिकॉर्डिंग परिवर्तन

Git में चीजों को पूर्ववत करने के तरीके को समझने से पहले, आपको पहले यह समझना चाहिए कि हम Git में परिवर्तनों को कैसे रिकॉर्ड करते हैं । यदि आप पहले से ही सभी शर्तें जानते हैं, तो बेझिझक इस भाग को छोड़ दें।


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

गिट रेपो के तीन "पेड़" (स्रोत: https://youtu.be/ozA1V00GIT8)


आमतौर पर, जब हम अपने सोर्स कोड पर काम करते हैं, तो हम एक वर्किंग डायरेक्टर से काम करते हैं। एक कार्यकारी निदेशक (एक्ट्रोरी) (या काम करने वाला पेड़ ) हमारे फाइल सिस्टम में कोई निर्देशिका है जिसमें इसके साथ एक भंडार जुड़ा हुआ है।


इसमें हमारे प्रोजेक्ट के फोल्डर और फाइलें होती हैं और .git नामक एक डायरेक्टरी भी होती है। मैंने .git फ़ोल्डर की सामग्री का अधिक विस्तार से वर्णन किया है एक पिछली पोस्ट .


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


एक रिपॉजिटरी में हमारी कोड फ़ाइलों के अलावा अन्य चीज़ें भी शामिल होती हैं, जैसे कि HEAD , शाखाएँ, आदि।


बीच में, हमारे पास इंडेक्स या स्टेजिंग एरिया है; ये दो शब्द विनिमेय हैं। जब हम एक शाखा checkout , तो गिट इंडेक्स को उन सभी फ़ाइल सामग्री के साथ पॉप्युलेट करता है जिन्हें पिछली बार हमारी कार्यशील निर्देशिका में चेक आउट किया गया था और मूल रूप से चेक आउट होने पर वे क्या दिखते थे।


जब हम git commit उपयोग करते हैं, तो इंडेक्स की स्थिति के आधार पर कमिट बनाया जाता है।


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


हाथ मिलाने का समय 🙌🏻


नए रिपॉजिटरी को इनिशियलाइज़ करने के लिए git init उपयोग करें। 1.txt नामक फ़ाइल में कुछ टेक्स्ट लिखें:

एक नया रेपो शुरू करना और उसमें पहली फ़ाइल बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


ऊपर बताए गए तीन ट्री स्टेट्स में से अब 1.txt कहां है?


वर्किंग ट्री में, क्योंकि इसे अभी तक इंडेक्स में पेश नहीं किया गया है।

फ़ाइल `1.txt` अब केवल कार्यशील निर्देशिका का हिस्सा है (स्रोत: https://youtu.be/ozA1V00GIT8)


इसे चरणबद्ध करने के लिए, इसे अनुक्रमणिका में जोड़ने के लिए, git add 1.txt का उपयोग करें।

`git ऐड` का उपयोग करने से फ़ाइल चरणबद्ध हो जाती है, इसलिए अब यह अनुक्रमणिका में भी है (स्रोत: https://youtu.be/ozA1V00GIT8)


अब, हम रिपॉजिटरी में अपने परिवर्तन करने के लिए git commit उपयोग कर सकते हैं।

`गिट कमिट` का उपयोग रिपॉजिटरी में एक कमिट ऑब्जेक्ट बनाता है (स्रोत: https://youtu.be/ozA1V00GIT8)


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


गिट में वस्तुओं के बारे में अधिक जानकारी के लिए (जैसे कमिट और पेड़), मेरी पिछली पोस्ट देखें .


(हां, "चेक आउट", यमक इरादा 😇)


Git हमें इस प्रतिबद्ध वस्तु का SHA-1 मान भी बताता है। मेरे मामले में, यह c49f4ba था (जो कुछ स्थान बचाने के लिए SHA-1 मान के केवल पहले 7 वर्ण हैं)।


यदि आप इस आदेश को अपनी मशीन पर चलाते हैं, तो आपको एक अलग SHA-1 मान मिलेगा, क्योंकि आप एक अलग लेखक हैं; साथ ही, आप एक अलग टाइमस्टैम्प पर प्रतिबद्धता बनायेंगे।


जब हम रेपो को इनिशियलाइज़ करते हैं, तो Git एक नई शाखा बनाता है (डिफ़ॉल्ट रूप से main नाम)। और गिट में एक शाखा एक प्रतिबद्धता के लिए सिर्फ एक नामित संदर्भ है . तो डिफ़ॉल्ट रूप से, आपके पास केवल main शाखा है। यदि आपकी कई शाखाएँ हैं तो क्या होगा? गिट कैसे जानता है कि कौन सी शाखा सक्रिय शाखा है?


गिट के पास HEAD नामक एक और सूचक है, जो एक शाखा को इंगित करता है (आमतौर पर), जो तब एक प्रतिबद्धता को इंगित करता है। वैसे, हुड के नीचे, HEAD सिर्फ एक फाइल है। इसमें कुछ उपसर्गों के साथ शाखा का नाम शामिल है।


रेपो में और बदलाव लाने का समय!


अब, मैं एक और बनाना चाहता हूँ। तो चलिए एक नई फाइल बनाते हैं, और इसे पहले की तरह इंडेक्स में जोड़ते हैं:

फ़ाइल `2.txt` वर्किंग डायर में है और इसे `git add` के साथ स्टेज करने के बाद इंडेक्स (स्रोत: https://youtu.be/ozA1V00GIT8)


अब, git commit उपयोग करने का समय आ गया है। महत्वपूर्ण रूप से, git commit दो काम करता है:


सबसे पहले, यह एक कमिट ऑब्जेक्ट बनाता है, इसलिए Git के आंतरिक ऑब्जेक्ट डेटाबेस में संबंधित SHA-1 मान के साथ एक ऑब्जेक्ट होता है। यह नया कमिट ऑब्जेक्ट पेरेंट कमिट की ओर भी इशारा करता है। जब आप git commit कमांड लिखते हैं तो HEAD उस ओर इशारा करता है।

एक नया कमिट ऑब्जेक्ट बनाया गया है, पहले - `मेन` अभी भी पिछले कमिट की ओर इशारा करता है (स्रोत: https://youtu.be/ozA1V00GIT8)


दूसरा, git commit सक्रिय शाखा के पॉइंटर को ले जाता है - हमारे मामले में, यह main होगा, नव निर्मित कमिट ऑब्जेक्ट को इंगित करने के लिए।

`गिट कमिट` नए बनाए गए कमिट ऑब्जेक्ट को इंगित करने के लिए सक्रिय शाखा को भी अपडेट करता है (स्रोत: https://youtu.be/ozA1V00GIT8)


परिवर्तनों को पूर्ववत करना

इतिहास को फिर से लिखने के लिए, आइए कमिट करने की प्रक्रिया को पूर्ववत करके शुरू करें। उसके लिए, हम कमांड 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 किया था।

`मुख्य` को "कमिट 1" पर रीसेट करना (स्रोत: https://youtu.be/ozA1V00GIT8)


git log? यह HEAD से शुरू होगा, main पर जाएगा, और फिर "Commit 1" पर जाएगा। ध्यान दें कि इसका मतलब है कि "कमिट 2" अब हमारे इतिहास से उपलब्ध नहीं है।


क्या इसका मतलब है कि "कमिट 2" की प्रतिबद्ध वस्तु हटा दी गई है? 🤔


नहीं, इसे हटाया नहीं गया है। यह अभी भी गिट के ऑब्जेक्ट्स के आंतरिक ऑब्जेक्ट डेटाबेस में रहता है।


यदि आप वर्तमान इतिहास को अभी पुश करते हैं, तो git push उपयोग करके, Git "कमिट 2" को दूरस्थ सर्वर पर नहीं धकेलेगा, लेकिन रिपॉजिटरी की आपकी स्थानीय प्रति पर कमिट ऑब्जेक्ट अभी भी मौजूद है।


अब, फिर से कमिट करें - और इस नए ऑब्जेक्ट को मूल "कमिट 2" से अलग करने के लिए "कमिट 2.1" के कमिट संदेश का उपयोग करें:

एक नई प्रतिबद्धता बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


"कमिट 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"।

`गिट रीसेट --मिश्रित` का पहला चरण `गिट रीसेट --सॉफ्ट` के समान है (स्रोत: https://youtu.be/ozA1V00GIT8)


इसके बाद, गिट आगे बढ़ता है, इंडेक्स में किए गए परिवर्तनों को प्रभावी ढंग से पूर्ववत करता है। यानी इंडेक्स को बदलना ताकि यह पहले चरण में सेट करने के बाद मौजूदा HEAD , नए HEAD के साथ मेल खाए।


अगर हम git reset --mixed HEAD~1 चलाते हैं, तो इसका मतलब है कि HEAD HEAD~1 ("कमिट 1") पर सेट किया जाएगा, और फिर Git इंडेक्स को "कमिट 1" की स्थिति से मिलाएगा - इस मामले में, यह इसका मतलब है कि 2.txt अब इंडेक्स का हिस्सा नहीं रहेगा।

`गिट रीसेट --मिक्स्ड` का दूसरा चरण नए `हेड` के साथ इंडेक्स का मिलान करना है (स्रोत: https://youtu.be/ozA1V00GIT8)


मूल "कमिट 2" की स्थिति के साथ एक नई प्रतिबद्धता बनाने का समय आ गया है। इस बार हमें इसे बनाने से पहले 2.txt फिर से चरणबद्ध करने की आवश्यकता है:

"कमिट 2.2" बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


गिट रीसेट - हार्ड

आगे बढ़ें, और भी पूर्ववत करें!


आगे बढ़ो और git reset --hard HEAD~1 चलाएं


फिर से, Git --soft चरण से शुरू होता है, जो कुछ भी HEAD ( main ) की ओर इशारा करता है, उसे HEAD~1 ("कमिट 1") पर सेट करता है।

`गिट रीसेट --हार्ड` का पहला चरण `गिट रीसेट --सॉफ्ट` के समान है (स्रोत: https://youtu.be/ozA1V00GIT8)


अब तक तो सब ठीक है।


अगला, --mixed चरण पर आगे बढ़ते हुए, इंडेक्स को HEAD से मिलाते हुए। यही है, गिट 2.txt के मंचन को पूर्ववत करता है।

`गिट रीसेट --हार्ड` का दूसरा चरण `गिट रीसेट --मिश्रित` के समान है (स्रोत: https://youtu.be/ozA1V00GIT8)


यह --hard कदम का समय है जहां गिट और भी आगे जाता है और इंडेक्स के चरण के साथ काम कर रहे डीआईआर से मेल खाता है। इस मामले में, इसका अर्थ है 2.txt कार्यशील डायर से भी हटाना।

`गिट रीसेट --हार्ड` का तीसरा चरण इंडेक्स के साथ काम कर रहे डीआईआर की स्थिति से मेल खाता है (स्रोत: https://youtu.be/ozA1V00GIT8)


(** नोट: इस विशिष्ट मामले में, फ़ाइल अनट्रैक है, इसलिए इसे फ़ाइल सिस्टम से हटाया नहीं जाएगा; हालांकि git reset समझने के लिए यह वास्तव में महत्वपूर्ण नहीं है)।


इसलिए Git में बदलाव लाने के लिए आपके पास तीन चरण हैं। आप वर्किंग डायर, इंडेक्स या स्टेजिंग एरिया को बदलते हैं, और फिर आप उन बदलावों के साथ एक नया स्नैपशॉट बनाते हैं। इन परिवर्तनों को पूर्ववत करने के लिए:


  • यदि हम git reset --soft उपयोग करते हैं, तो हम कमिट स्टेप को पूर्ववत कर देते हैं।


  • यदि हम git reset --mixed उपयोग करते हैं, तो हम स्टेजिंग चरण को भी पूर्ववत कर देते हैं।


  • यदि हम git reset --hard उपयोग करते हैं, तो हम कार्यशील डायर में परिवर्तन पूर्ववत करते हैं।

वास्तविक जीवन परिदृश्य!

परिद्रश्य 1

इसलिए वास्तविक जीवन के परिदृश्य में, "I love Git" को एक फ़ाइल ( love.txt ) में लिखें, जैसा कि हम सभी Git 😍 से प्यार करते हैं। आगे बढ़ो, मंच और इसे भी प्रतिबद्ध करें:

"कमिट 2.3" बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


ओह, उफ़!


दरअसल, मैं नहीं चाहता था कि आप इसे प्रतिबद्ध करें।


मैं वास्तव में चाहता था कि आप इसे करने से पहले इस फ़ाइल में कुछ और प्रेम शब्द लिखें।

आप क्या कर सकते हैं?


खैर, इसे दूर करने का एक तरीका git reset --mixed HEAD~1 उपयोग करना होगा, प्रभावी रूप से आपके द्वारा की गई कमिटिंग और स्टेजिंग दोनों क्रियाओं को पूर्ववत करना:

स्टेजिंग और कमिटिंग स्टेप्स को पूर्ववत करना (स्रोत: https://youtu.be/ozA1V00GIT8)


तो फिर से "कमिट 1" के main बिंदु, और love.txt अब इंडेक्स का हिस्सा नहीं है। हालाँकि, फ़ाइल कार्यशील निर्देशिका में बनी हुई है। अब आप आगे बढ़ सकते हैं, और इसमें और सामग्री जोड़ सकते हैं:

अधिक प्रेम गीत जोड़ना (स्रोत: https://youtu.be/ozA1V00GIT8)


आगे बढ़ो, मंच और अपनी फ़ाइल प्रतिबद्ध करें:

वांछित स्थिति के साथ नई प्रतिबद्धता बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


शाबाश 👏🏻


आपको "कमिट 1" की ओर इशारा करते हुए "कमिट 2.4" का यह स्पष्ट, अच्छा इतिहास मिला।


अब हमारे टूलबॉक्स में एक नया टूल है, git reset 💪🏻

git रीसेट अब हमारे टूलबॉक्स में है (स्रोत: https://youtu.be/ozA1V00GIT8)


यह उपकरण अत्यंत उपयोगी है, अत्यधिक उपयोगी है, और आप इसके साथ लगभग कुछ भी पूरा कर सकते हैं। यह हमेशा उपयोग करने के लिए सबसे सुविधाजनक उपकरण नहीं होता है, लेकिन यदि आप इसे सावधानीपूर्वक उपयोग करते हैं तो यह लगभग किसी भी पुनर्लेखन-इतिहास परिदृश्य को हल करने में सक्षम है।


नौसिखियों के लिए, मेरा सुझाव है कि जब भी आप गिट में पूर्ववत करना चाहते हैं तो केवल git reset उपयोग करें। एक बार जब आप इसके साथ सहज महसूस करते हैं, तो अन्य उपकरणों पर जाने का समय आ गया है।

परिदृश्य # 2

आइए एक और मामले पर विचार करें।


new.txt नामक एक नई फाइल बनाएं; मंच और प्रतिबद्ध:

`new.txt` और “Commit 3” बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


उफ़। दरअसल, यह एक गलती है। आप main पर थे, और मैं चाहता था कि आप इस कमिट को फीचर ब्रांच पर बनाएं। मेरा बुरा 😇


मैं चाहता हूं कि आप इस पोस्ट से दो सबसे महत्वपूर्ण उपकरण लें। दूसरा है git reset । पहला और कहीं अधिक महत्वपूर्ण यह है कि वर्तमान स्थिति बनाम आप जिस राज्य में रहना चाहते हैं , उसे व्हाइटबोर्ड करना है


इस परिदृश्य के लिए, वर्तमान स्थिति और वांछित स्थिति इस तरह दिखती है:

परिदृश्य #2: वर्तमान-बनाम-वांछित स्थिति (स्रोत: https://youtu.be/ozA1V00GIT8)


आप तीन बदलाव देखेंगे:


  1. वर्तमान स्थिति में "कमिट 3" (नीला वाला) के main बिंदु, लेकिन वांछित स्थिति में "कमिट 2.4"।


  2. feature शाखा वर्तमान स्थिति में मौजूद नहीं है, फिर भी यह मौजूद है और वांछित स्थिति में "कमिट 3" की ओर इशारा करती है।


  3. HEAD वर्तमान स्थिति में main की ओर इशारा करता है, और वांछित स्थिति में feature के लिए।


यदि आप इसे आकर्षित कर सकते हैं और आप git reset उपयोग करना जानते हैं, तो आप निश्चित रूप से इस स्थिति से बाहर निकल सकते हैं।


तो फिर, सबसे महत्वपूर्ण बात यह है कि सांस लें और इसे बाहर निकालें।


उपरोक्त आरेखण को देखते हुए, हम वर्तमान स्थिति से वांछित स्थिति तक कैसे पहुँच सकते हैं?


बेशक कुछ अलग तरीके हैं, लेकिन मैं प्रत्येक परिदृश्य के लिए केवल एक विकल्प प्रस्तुत करूंगा। अन्य विकल्पों के साथ भी खेलने के लिए स्वतंत्र महसूस करें।


आप git reset --soft HEAD~1 उपयोग करके प्रारंभ कर सकते हैं। यह पिछले कमिट, "कमिट 2.4" को इंगित करने के लिए main सेट करेगा:

'मुख्य' बदलना; "कमिट 3 धुंधला है क्योंकि यह अभी भी वहां है, बस पहुंच योग्य नहीं है (स्रोत: https://youtu.be/ozA1V00GIT8)


वर्तमान-बनाम-वांछित आरेख पर फिर से झाँकते हुए, आप देख सकते हैं कि आपको एक नई शाखा की आवश्यकता है, है ना? आप इसके लिए git switch -c feature या git checkout -b feature (जो एक ही काम करता है) का उपयोग कर सकते हैं:

`फीचर` शाखा बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


यह आदेश नई शाखा को इंगित करने के लिए HEAD भी अद्यतन करता है।


चूंकि आपने git reset --soft उपयोग किया है, आपने इंडेक्स को नहीं बदला है, इसलिए वर्तमान में यह वही स्थिति है जिसे आप कमिट करना चाहते हैं - कितना सुविधाजनक है! आप बस feature शाखा के लिए प्रतिबद्ध हो सकते हैं:

`फीचर` शाखा के लिए प्रतिबद्ध (स्रोत: https://youtu.be/ozA1V00GIT8)


और आप वांछित स्थिति में पहुंच गए 🎉

परिदृश्य #3

अपने ज्ञान को अतिरिक्त मामलों में लागू करने के लिए तैयार हैं?


love.txt में कुछ बदलाव जोड़ें, और cool.txt नाम की एक नई फाइल भी बनाएं। उन्हें चरणबद्ध करें और प्रतिबद्ध करें:

"कमिट 4" बनाना (स्रोत: https://youtu.be/ozA1V00GIT8)


ओह, उफ़, वास्तव में मैं चाहता था कि आप दो अलग-अलग कमिट बनाएं, प्रत्येक परिवर्तन के साथ एक 🤦🏻

इसे स्वयं आजमाना चाहते हैं?


आप कमिटिंग और स्टेजिंग चरणों को पूर्ववत कर सकते हैं:

`गिट रीसेट --मिश्रित हेड~1` का उपयोग करके कमिटिंग और स्टेजिंग पूर्ववत करें (स्रोत: https://youtu.be/ozA1V00GIT8)


इस आदेश के बाद, अनुक्रमणिका में अब वे दो परिवर्तन शामिल नहीं हैं, लेकिन वे दोनों अभी भी आपके फ़ाइल सिस्टम में हैं। तो अब, यदि आप केवल love.txt मंचित करते हैं, तो आप इसे अलग से कर सकते हैं, और फिर cool.txt के लिए भी ऐसा ही कर सकते हैं:

अलग से प्रतिबद्ध (स्रोत: https://youtu.be/ozA1V00GIT8)


अच्छा 😎

परिदृश्य # 4

कुछ पाठ के साथ एक नई फ़ाइल ( new_file.txt ) बनाएँ, और love.txt में कुछ पाठ जोड़ें। चरण दोनों बदलते हैं, और उन्हें प्रतिबद्ध करते हैं:

एक नई प्रतिबद्धता (स्रोत: https://youtu.be/ozA1V00GIT8)


उफ़ 🙈🙈


तो इस बार, मैं चाहता था कि यह दूसरी शाखा पर हो, लेकिन एक नई शाखा नहीं, बल्कि पहले से मौजूद शाखा।


तो आप क्या कर सकते हैं?


मैं आपको एक संकेत देता हूँ। उत्तर वास्तव में छोटा और वास्तव में आसान है। हम पहले क्या करते हैं?


नहीं, reset नहीं। हम चित्र बनाते हैं। यह करने के लिए पहली चीज है, क्योंकि यह बाकी सब कुछ इतना आसान बना देगी। तो ये है मौजूदा स्थिति:

`मेन` पर नया कमिट नीला दिखाई देता है (स्रोत: https://youtu.be/ozA1V00GIT8)


और वांछित अवस्था?

हम चाहते हैं कि "ब्लू" कमिट दूसरी, `मौजूदा`, शाखा पर हो (स्रोत: https://youtu.be/ozA1V00GIT8)


आप वर्तमान स्थिति से वांछित स्थिति में कैसे जाते हैं, सबसे आसान क्या होगा?


तो एक तरीका यह होगा कि आप पहले की तरह git reset उपयोग करें, लेकिन एक और तरीका है जिसे मैं चाहूंगा कि आप कोशिश करें।


सबसे पहले, existing शाखा को इंगित करने के लिए HEAD स्थानांतरित करें:

`मौजूदा` शाखा में स्विच करें (स्रोत: https://youtu.be/ozA1V00GIT8)


सहज रूप से, आप जो करना चाहते हैं वह ब्लू कमिट में पेश किए गए परिवर्तनों को लेना है, और इन परिवर्तनों ("कॉपी-पेस्ट") को existing शाखा के शीर्ष पर लागू करना है। और गिट के पास इसके लिए एक टूल है।


Git को इस कमिट और उसके पैरेंट कमिट के बीच शुरू किए गए परिवर्तनों को लेने के लिए कहने के लिए और इन परिवर्तनों को केवल सक्रिय शाखा पर लागू करने के लिए, आप git cherry-pick उपयोग कर सकते हैं। यह कमांड निर्दिष्ट संशोधन में पेश किए गए परिवर्तनों को लेता है और उन्हें सक्रिय कमिट पर लागू करता है।


यह एक नई प्रतिबद्ध वस्तु भी बनाता है, और इस नई वस्तु को इंगित करने के लिए सक्रिय शाखा को अद्यतन करता है।

`गिट चेरी-पिक` का उपयोग करना (स्रोत: https://youtu.be/ozA1V00GIT8)


ऊपर दिए गए उदाहरण में, मैंने बनाए गए कमिट के SHA-1 पहचानकर्ता को निर्दिष्ट किया है, लेकिन आप git cherry-pick main उपयोग भी कर सकते हैं, क्योंकि जिस कमिट के परिवर्तन हम लागू कर रहे हैं, वह एक main की ओर इशारा कर रहा है।


लेकिन हम नहीं चाहते कि ये परिवर्तन main शाखा पर मौजूद हों। git cherry-pick केवल existing शाखा में परिवर्तन लागू करता है। आप उन्हें main से कैसे निकाल सकते हैं?


एक तरीका यह होगा कि आप main पर वापस switch , और फिर git reset --hard HEAD~1 उपयोग करें:

रीसेट करना `मुख्य` (स्रोत: https://youtu.be/ozA1V00GIT8)


तुमने यह किया! 💪🏻


ध्यान दें कि git cherry-pick वास्तव में निर्दिष्ट प्रतिबद्धता और उसके माता-पिता के बीच अंतर की गणना करता है, और उसके बाद उन्हें सक्रिय प्रतिबद्धता पर लागू करता है। इसका अर्थ है कि कभी-कभी, Git उन परिवर्तनों को लागू करने में सक्षम नहीं होगा, क्योंकि आपको विरोध हो सकता है, लेकिन यह किसी अन्य पोस्ट के लिए एक विषय है।


साथ ही, ध्यान दें कि आप गिट को किसी भी प्रतिबद्धता में पेश किए गए परिवर्तनों को cherry-pick के लिए कह सकते हैं, न केवल शाखा द्वारा संदर्भित।


हमने एक नया टूल हासिल कर लिया है, इसलिए हमारे पास बेल्ट के नीचे git reset के साथ-साथ git cherry-pick भी है।

परिदृश्य # 5

ठीक है, तो एक और दिन, एक और रेपो, एक और समस्या।


कमिट बनाएं:

एक और कमिट (स्रोत: https://youtu.be/ozA1V00GIT8)


और इसे दूरस्थ सर्वर पर push :

(स्रोत: https://youtu.be/ozA1V00GIT8)


उम, उफ़ 😓…


मैंने अभी कुछ देखा। वहां एक टाइपो है। मैंने लिखा This is more tezt This is more text अधिक तेज़ है। वूप्स। तो अब बड़ी समस्या क्या है? मैं एड को push , जिसका अर्थ है कि किसी और ने पहले ही उन परिवर्तनों को pull होगा।


यदि मैं git reset उपयोग करके उन परिवर्तनों को ओवरराइड करता हूं, जैसा कि हमने अभी तक किया है, तो हमारे पास अलग-अलग इतिहास होंगे, और सभी नरक ढीले हो सकते हैं। जब तक आप इसे push तब तक आप रेपो की अपनी कॉपी को जितना चाहें उतना दोबारा लिख सकते हैं।


एक बार जब आप परिवर्तन को push , तो आपको यह सुनिश्चित करने की आवश्यकता होती है कि यदि आप इतिहास को फिर से लिखने जा रहे हैं तो किसी और ने उन परिवर्तनों को प्राप्त नहीं किया है।


वैकल्पिक रूप से, आप git revert नामक एक अन्य टूल का उपयोग कर सकते हैं। यह आदेश उस प्रतिबद्धता को लेता है जिसे आप प्रदान कर रहे हैं और डिफ को अपने मूल प्रतिबद्धता से git cherry-pick की तरह गणना करता है, लेकिन इस बार, यह रिवर्स परिवर्तनों की गणना करता है।


इसलिए यदि निर्दिष्ट कमिट में आपने एक लाइन जोड़ी है, तो रिवर्स लाइन को हटा देगा, और इसके विपरीत।

परिवर्तनों को पूर्ववत करने के लिए `गिट रिवर्ट` का उपयोग करना (स्रोत: https://youtu.be/ozA1V00GIT8)


git revert एक नई प्रतिबद्ध वस्तु बनाई, जिसका अर्थ है कि यह इतिहास के लिए एक अतिरिक्त है। git revert उपयोग करके, आपने इतिहास को दोबारा नहीं लिखा। आपने अपनी पिछली गलती को स्वीकार किया, और यह प्रतिबद्धता एक स्वीकारोक्ति है कि आपने गलती की और अब आपने इसे ठीक कर लिया है।


कुछ कहेंगे कि यह अधिक परिपक्व तरीका है। कुछ लोग कहेंगे कि यह उतना साफ इतिहास नहीं है जितना कि अगर आप पिछले कमिट को फिर से लिखने के लिए git reset इस्तेमाल करते हैं तो आपको मिलेगा। लेकिन यह इतिहास के पुनर्लेखन से बचने का एक तरीका है।


अब आप टाइपो को ठीक कर सकते हैं और दोबारा प्रतिबद्ध कर सकते हैं:

परिवर्तनों को फिर से करना (स्रोत: https://youtu.be/ozA1V00GIT8)


आपका टूलबॉक्स अब एक नए चमकदार टूल से लोड हो गया है, revert :

हमारा टूलबॉक्स (स्रोत: https://youtu.be/ozA1V00GIT8)


परिदृश्य #6

कुछ काम पूरा करें, कुछ कोड लिखें और इसे love.txt में जोड़ें। इस परिवर्तन को चरणबद्ध करें, और इसे प्रतिबद्ध करें:

एक और कमिट (स्रोत: https://youtu.be/ozA1V00GIT8)


मैंने अपनी मशीन पर ऐसा ही किया, और मैंने पिछले आदेशों पर वापस स्क्रॉल करने के लिए अपने कीबोर्ड पर Up तीर कुंजी का उपयोग किया, और फिर मैंने Enter मारा, और ... वाह।


वूप्स।

क्या मैंने अभी `गिट रीसेट - हार्ड` किया? (स्रोत: https://youtu.be/ozA1V00GIT8)


क्या मैंने अभी git reset --hard उपयोग किया है? 😨


वास्तव में क्या हुआ? गिट ने पॉइंटर को HEAD~1 पर ले जाया, इसलिए अंतिम प्रतिबद्धता, मेरे सभी बहुमूल्य कार्यों के साथ, वर्तमान इतिहास से पहुंच योग्य नहीं है। Git ने स्टेजिंग एरिया से सभी बदलावों को भी अनस्टेज किया, और फिर स्टेजिंग एरिया की स्थिति के लिए वर्किंग डायर का मिलान किया।


यानी सब कुछ इस राज्य से मेल खाता है जहां मेरा काम है... चला गया।


अजीब समय। मस्ती कर रहे हैं।

लेकिन, क्या वास्तव में घबराने का कोई कारण है? वास्तव में नहीं... हम निश्चिंत लोग हैं। हम क्या करते हैं? खैर, सहजता से, क्या वास्तव में प्रतिबद्धता वास्तव में चली गई है? क्यों कोई नहीं? यह अभी भी गिट के आंतरिक डेटाबेस के अंदर मौजूद है।


अगर मुझे केवल यह पता होता कि वह कहाँ है, तो मुझे SHA-1 मान पता होगा जो इस कमिट की पहचान करता है, हम इसे पुनर्स्थापित कर सकते हैं। मैं पूर्ववत भी पूर्ववत कर सकता था, और इस प्रतिबद्धता पर वापस आ reset


तो केवल एक चीज जिसकी मुझे वास्तव में आवश्यकता है, वह है "हटाए गए" कमिट का SHA-1।


तो सवाल यह है कि मैं इसे कैसे ढूंढूं? क्या git log उपयोगी होगा?


सचमुच में ठीक नहीं। git log HEAD पर जाएगा, जो main को इंगित करता है, जो उस प्रतिबद्धता की मूल प्रतिबद्धता को इंगित करता है जिसे हम ढूंढ रहे हैं। फिर, git log मूल श्रृंखला के माध्यम से वापस आ जाएगा, जिसमें मेरे बहुमूल्य काम के साथ प्रतिबद्धता शामिल नहीं है।

इस मामले में `गिट लॉग` मदद नहीं करता है (स्रोत: https://youtu.be/ozA1V00GIT8)


शुक्र है, गिट बनाने वाले बहुत ही चतुर लोगों ने हमारे लिए एक बैकअप योजना भी बनाई, और इसे reflog कहा जाता है।


जब आप गिट के साथ काम करते हैं, जब भी आप HEAD बदलते हैं, जिसे आप git reset उपयोग करके कर सकते हैं, लेकिन git switch या git checkout जैसे अन्य आदेश भी, गिट reflog में एक प्रविष्टि जोड़ता है।


`git reflog` हमें दिखाता है कि `HEAD` कहाँ था (स्रोत: https://youtu.be/ozA1V00GIT8)


हमने अपनी प्रतिबद्धता पाई! यह वह है जो 0fb929e से शुरू होता है।


हम इसके "उपनाम" - HEAD@{1} से भी संबंधित हो सकते हैं। तो जैसे कि गिट HEAD के पहले माता-पिता को पाने के लिए HEAD~1 का उपयोग करता है, और HEAD~2 HEAD के दूसरे माता-पिता को संदर्भित करने के लिए और इसी तरह, गिट HEAD@{1} का उपयोग HEAD के पहले रीफ्लॉग माता-पिता को संदर्भित करने के लिए करता है, जहां HEAD पिछले चरण में इशारा किया था।


हम इसका मूल्य दिखाने के लिए git rev-parse भी पूछ सकते हैं:

(स्रोत: https://youtu.be/ozA1V00GIT8)


reflog देखने का एक और तरीका git log -g का उपयोग करना है, जो git log वास्तव में reflog पर विचार करने के लिए कहता है:

`गिट लॉग-जी` का आउटपुट (स्रोत: https://youtu.be/ozA1V00GIT8)


हम ऊपर देखते हैं कि reflog , ठीक उसी तरह जैसे HEAD , main की ओर इशारा करता है, जो "कमिट 2" की ओर इशारा करता है। लेकिन reflog में उस प्रविष्टि का जनक "कमिट 3" की ओर इशारा करता है।


तो "कमिट 3" पर वापस जाने के लिए, आप बस git reset --hard HEAD@{1} (या "कमिट 3" का SHA-1 मान) का उपयोग कर सकते हैं:

(स्रोत: https://youtu.be/ozA1V00GIT8)


और अब, अगर हम git log :

हमारा इतिहास वापस आ गया है!!! (स्रोत: https://youtu.be/ozA1V00GIT8)


हमने दिन बचा लिया! 🎉👏🏻


यदि मैं इस आदेश का दोबारा उपयोग करूं तो क्या होगा? और git commit --reset HEAD@{1} चलाया? Git HEAD उस स्थान पर सेट करेगा जहाँ HEAD अंतिम reset से पहले इंगित कर रहा था, जिसका अर्थ है "कमिट 2"। हम पूरे दिन चलते रह सकते हैं:

(स्रोत: https://youtu.be/ozA1V00GIT8)


अब हमारे टूलबॉक्स को देखते हुए, यह ऐसे टूल से भरा हुआ है जो आपको कई मामलों को हल करने में मदद कर सकता है जहां गिट में चीजें गलत हो जाती हैं:

हमारा टूलबॉक्स काफी व्यापक है! (स्रोत: https://youtu.be/ozA1V00GIT8)


इन उपकरणों के साथ, अब आप बेहतर ढंग से समझ गए हैं कि Git कैसे काम करता है। ऐसे और भी उपकरण हैं जो आपको विशेष रूप से इतिहास को फिर से लिखने की अनुमति देंगे, git rebase ), लेकिन आप इस पोस्ट में पहले ही बहुत कुछ सीख चुके हैं। भविष्य के पदों में, मैं git rebase में भी गोता लगाऊंगा।


सबसे महत्वपूर्ण उपकरण, इस टूलबॉक्स में सूचीबद्ध पांच टूल से भी अधिक महत्वपूर्ण, वर्तमान स्थिति बनाम वांछित स्थिति को व्हाइटबोर्ड करना है। इस पर मेरा भरोसा करें, यह हर स्थिति को कम चुनौतीपूर्ण और समाधान को अधिक स्पष्ट बना देगा।

गिट के बारे में और जानें

मैंने इस पोस्ट की सामग्री को कवर करते हुए एक लाइव वार्ता भी की। यदि आप एक वीडियो पसंद करते हैं (या इसे पढ़ने के साथ-साथ देखना चाहते हैं) - आप इसे पा सकते हैं .


सामान्य रूप में, मेरा YouTube चैनल गिट और इसके इंटर्नल के कई पहलुओं को शामिल करता है; आपका स्वागत है इसकी जांच - पड़ताल करें (यमक इरादा 😇)

लेखक के बारे में

ओमर रोसेनबाम के सीटीओ और सह-संस्थापक हैं तैरना , एक devtool जो डेवलपर्स और उनकी टीमों को अप-टू-डेट आंतरिक दस्तावेज़ीकरण के साथ उनके कोडबेस के बारे में ज्ञान प्रबंधित करने में सहायता करता है। ओमेर चेक प्वाइंट सुरक्षा अकादमी के संस्थापक हैं और आईटीसी में साइबर सुरक्षा लीड थे, जो एक शैक्षिक संगठन है जो प्रतिभाशाली पेशेवरों को प्रौद्योगिकी में करियर विकसित करने के लिए प्रशिक्षित करता है।


ओमर ने तेल अवीव विश्वविद्यालय से भाषाविज्ञान में एमए किया है और इसके निर्माता हैं संक्षिप्त यूट्यूब चैनल .


सबसे पहले यहाँ प्रकाशित हुआ