मैं इतिहास में दफन एक Git प्रतिबद्ध कैसे विभाजित कर सकते हैं?


292

मैं अपने इतिहास से रूबरू हुआ और उसमें कुछ बदलाव करना चाहता हूं। समस्या यह है, मेरे पास दो असंबंधित परिवर्तनों के साथ एक प्रतिबद्ध है, और यह प्रतिबद्ध मेरे स्थानीय (गैर-धक्का) इतिहास में कुछ अन्य परिवर्तनों से घिरा हुआ है।

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


जवाबों:


450

रिबास मैनपेज में विभाजन करने के लिए एक गाइड है । त्वरित सारांश है:

  • लक्ष्य प्रतिबद्ध (उदाहरण के लिए git rebase -i <commit-to-split>^ branch) सहित एक इंटरैक्टिव रिबेस करें और इसे संपादित करने के लिए चिह्नित करें।

  • जब रिबास उस कमिट तक पहुँच जाता है, git reset HEAD^तो कमिट से पहले रिसेट करने के लिए उपयोग करें, लेकिन अपने कार्य ट्री को अक्षुण्ण रखें।

  • आकस्मिक रूप से परिवर्तन जोड़ते हैं और उन्हें प्रतिबद्ध करते हैं, जिससे वांछित के रूप में कई हिट होते हैं। add -pकिसी फ़ाइल में केवल कुछ परिवर्तन जोड़ने के लिए उपयोगी हो सकता है। commit -c ORIG_HEADयदि आप एक निश्चित प्रतिबद्ध के लिए मूल प्रतिबद्ध संदेश का फिर से उपयोग करना चाहते हैं तो उपयोग करें ।

  • यदि आप यह परीक्षण करना चाहते हैं कि आप क्या कर रहे हैं (अच्छा विचार!) git stashजो हिस्सा आपने नहीं किया है उसे छिपाने के लिए उपयोग करें (या stash --keep-indexइससे पहले कि आप इसे भी प्रतिबद्ध करें), परीक्षण करें, फिर git stash popबाकी को काम के पेड़ पर लौटा दें। जब तक आप सभी संशोधन नहीं करवाते, तब तक कमिट करते रहें, यानी एक साफ-सुथरा काम करने वाला पेड़ हो।

  • भागो git rebase --continueअब-विभाजन के बाद प्रतिबद्ध लागू करने के लिए प्रतिबद्ध आगे बढ़ने के लिए।


17
... लेकिन अगर आपने पहले ही इतिहास को विभाजित करने के लिए धकेल दिया है तो इसका कोई मतलब नहीं है।
विल्हेल्मटेल

29
@wilhelmtell: मैंने अपने सामान्य "संभावित रूप से खतरनाक" को छोड़ दिया; 'अपस्ट्रीम रिबेस से उबरने' को देखें "बॉयलरप्लेट क्योंकि ओपी ने स्पष्ट रूप से कहा कि उसने इस इतिहास को आगे नहीं बढ़ाया।
Cascabel

2
और आपने सही पढ़ा। मैं 'बॉयलरप्लेट' से बचने की कोशिश कर रहा था जब मैंने निर्दिष्ट किया कि यह अभी तक साझा इतिहास नहीं है :) किसी भी संबंध में, मुझे आपके सुझाव से सफलता मिली है। हालांकि इस तथ्य के बाद इस सामान को करना एक बड़ा दर्द है। मैंने यहां एक सबक सीखा है, और यह सुनिश्चित करने के लिए कि कमिट को सही तरीके से शुरू करने के लिए रखा गया है!
बेन

2
पहले चरण को बेहतर बताया जा सकता है git rebase -i <sha1_of_the_commit_to_split>^ branch। और git guiबंटवारे के कार्य के लिए एक अच्छा उपकरण है, जिसका उपयोग फ़ाइल के विभिन्न हिस्सों को अलग-अलग कमिट में जोड़ने के लिए किया जा सकता है।
Qiang जू

3
@QiangXu: पहला एक उचित सुझाव है। दूसरा ठीक यही कारण है कि मैंने सुझाव दिया git add -p, जो git guiइस विभाग में अधिक से अधिक कर सकते हैं (विशेष रूप से एडिटिंग हंक, वर्तमान हंक से शुरू होने वाली हर चीज का मंचन और रेक्स द्वारा हक्स की खोज)।
कैस्केबेल

3

यहाँ यह मैगिट के साथ कैसे करना है

कहो ed417ae वह है जिसे आप बदलना चाहते हैं; इसमें दो असंबंधित परिवर्तन शामिल हैं और इसे एक या अधिक कमिट्स के तहत दफनाया गया है। llलॉग दिखाने के लिए मारो , और ed417ae पर नेविगेट करें:

प्रारंभिक लॉग

फिर rरिबास पॉपअप खोलने के लिए मारा

रिबास पॉपअप

तथा m बिंदु पर प्रतिबद्ध को संशोधित करने के लिए।

ध्यान दें कि @आप जिस विभाजन को चाहते हैं, उस पर अब क्या है - इसका मतलब है कि HEAD अब उस प्रतिबद्ध में है:

कमिट करना

हम माता-पिता को HEAD स्थानांतरित करना चाहते हैं, इसलिए माता-पिता (47e18b3) पर नेविगेट करें और हिट करें x( यदि आप उपयोग कर रहे हैं तो magit-reset-quicklyबाध्य oहैं evil-magit) और "हां मैं बिंदु पर प्रतिबद्ध था" कहने के लिए दर्ज करें। आपका लॉग अब दिखना चाहिए:

रीसेट करने के बाद लॉग इन करें

अब, qरेगुलर मैगिट स्टेटस में जाने के लिए हिट करें, उसके बाद रेगुलर अनस्टेज uकमांड का उपयोग करें, जो पहले कमिट में नहीं जाता है, cबाकी को हमेशा की तरह कमिट करें, फिर sटेज और commit दूसरी कमिट में जाता है, और जब किया जाता है: rरिबास पॉपअप खोलने के लिए मारा

रिबास पॉपअप

और एक rऔर जारी रखने के लिए, और आप कर रहे हैं! llअब दिखाता है:

सभी किया लॉग


1

एक कमिट को विभाजित करने <commit>और इस से पहले नई कमेट को जोड़ने के लिए , और लेखक की तारीख को बचाएं <commit>, - चरण निम्नलिखित हैं:

  1. पहले संपादित करें <commit>

    git rebase -i <commit>^^
    

    NB: शायद यह भी <commit>रूप में अच्छी तरह से संपादित करने की आवश्यकता होगी ।

  2. <commit>सूचकांक में चेरी उठाओ

    git cherry-pick -n <commit>
    
  3. अंतःक्रियात्मक रूप से अनुक्रमणित से अनावश्यक परिवर्तन को रीसेट करें और कार्य ट्री को रीसेट करें

    git reset -p && git checkout-index -f -a
    

    वैकल्पिक रूप से, बस अनावश्यक रूप से परिवर्तनों को रोकें: git stash push -p -m "tmp other changes"

  4. अन्य परिवर्तन (यदि कोई हो) करें और नई कमिट बनाएं

    git commit -m "upd something" .
    

    वैकल्पिक रूप से, अधिक मध्यवर्ती कमिट जोड़ने के लिए आइटम 2-4 दोहराएं।

  5. रिबासिंग जारी रखें

    git rebase --continue
    

0

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

  1. अपने संपादक का उपयोग करें और उन पंक्तियों को हटा दें जिन्हें आप निकालना चाहते हैं the_file। बंद करें the_file। यह एकमात्र संस्करण है जिसकी आपको आवश्यकता है, बाकी सभी सिर्फ git कमांड हैं।
  2. सूचकांक में विलोपन की अवस्था:

    git  add  the_file
    
  3. अनुक्रमणिका को प्रभावित किए बिना आपने फ़ाइल में वापस डाली गई लाइनों को पुनर्स्थापित करें !

    git show HEAD:./the_file > the_file
    
  4. "SHA1" वह रेखा है जिसे आप लाइनों से निकालना चाहते हैं:

    git commit -m 'fixup! SHA1' 
    
  5. चरण 3 द्वारा बहाल की गई सामग्री को निकालने के लिए दूसरी, बिल्कुल नई प्रतिबद्धता बनाएं:

    git commit -m 'second and new commit' the_file 
    
  6. संपादित न करें, बंद न करें / जारी रखें - बस सब कुछ स्वीकार करें:

    git rebase --autosquash -i SHA1~1
    

निश्चित रूप से तब और भी तेज हो सकता है जब निकालने की प्रतिबद्धता अंतिम वचन है:

4. git commit -C HEAD --amend
5. git commit -m 'second and new commit' thefile
6. no rebase, nothing

यदि आप उपयोग करते हैं magitतो चरण 4, 5 और 6 एक एकल क्रिया है: कमिट, तुरंत फिक्स


-2

यदि आपने अभी तक धक्का नहीं दिया है, तो बस उपयोग करें git rebase। और भी बेहतर, git rebase -iस्थानांतरित करने के लिए उपयोग अंतःक्रियात्मक रूप से करता है। आप अपमानजनक कमेंट को सामने की ओर ले जा सकते हैं, फिर इसे अपनी इच्छानुसार विभाजित कर सकते हैं और पैच को पीछे ले जा सकते हैं (यदि आवश्यक हो)।


14
इसे कहीं भी स्थानांतरित करने की आवश्यकता नहीं है। जहां है वहीं बांट दो।
Cascabel

1
दुर्भाग्य से, यह मेरे लिए काम नहीं करता है क्योंकि कमिट के बाद का कुछ इतिहास इस पर निर्भर है, इसलिए मैं थोड़ा प्रतिबंधित हूं। हालाँकि, यह मेरी पहली पसंद होती।
बेन

@ बान: यह ठीक है - बाद में आने पर बदलने की ज़रूरत नहीं होगी (यह मानते हुए कि आप सभी बदलावों को दूर रखें, बल्कि उनमें से कुछ को फेंक दें)। यहां अधिक जानकारी - stackoverflow.com/questions/1440050/…
ईथर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.