अतीत में कुछ दो मनमाने तरीके से किए गए कमिट के बीच कमिटमेंट कैसे इंजेक्ट करें?


126

मान लीजिए कि मेरी स्थानीय-एकमात्र शाखा में मेरा निम्नलिखित प्रतिबद्ध इतिहास है:

A -- B -- C

मैं Aऔर के बीच एक नई प्रतिबद्धता कैसे डालूं B?


3
कहा जाता है प्रतिबद्ध एक ? :)
Antek

मेरा एक बहुत ही समान प्रश्न है कि कमिट के बजाय अतीत में नया संस्करण कैसे डालें
पावेल पी।

जवाबों:


178

यह ओपी के जवाब से भी आसान है।

  1. git rebase -i <any earlier commit>। यह आपके कॉन्फ़िगर किए गए पाठ संपादक में कमिट की एक सूची प्रदर्शित करता है।
  2. वह कमिटमेंट खोजें जिसे आप बाद में डालना चाहते हैं (मान लें कि यह है a1b2c3d)। आपके संपादक में, उस पंक्ति के लिए, में परिवर्तन pickकरें edit
  3. अपने पाठ संपादक (अपने परिवर्तन सहेजें) को बंद करके रिबास शुरू करें। साथ शीघ्र एक आदेश में यह पत्ते आप प्रतिबद्ध आप पहले चुना गया ( a1b2c3d) के रूप में अगर यह सिर्फ किया गया है
  4. अपने परिवर्तन करें और git commit( ज्यादातर एस के विपरीत, संशोधन नहींedit )। यह आपके द्वारा चुने जाने के बाद एक नई प्रतिबद्धता बनाता है ।
  5. git rebase --continue। यह पुनरावृत्ति को आगे बढ़ाता है, जिससे आपकी नई प्रतिबद्धता सही जगह पर आ जाती है।

खबरदार कि यह इतिहास को फिर से लिखेगा, और जो कोई भी खींचने की कोशिश करेगा उसे तोड़ देगा।


1
इसने कमिट के बाद नया कमिट जोड़ा, जो एक के बाद है जिस पर मैं रिबासिंग कर रहा था (अंतिम प्रतिबद्ध भी), इसके बजाय राइट के बाद जिस पर मैं रिबास कर रहा था। परिणाम वही था जैसे कि मैंने केवल उन बदलावों के साथ अंत में एक नई प्रतिबद्धता बनाई थी जिन्हें मैं सम्मिलित करना चाहता था। मेरा इतिहास A -- B -- C -- Dवांछित के बजाय बन गया A -- D -- B -- C
XedinUnogn

2
@XedinUnaware: तब आपने रिबेस का सही इस्तेमाल नहीं किया।
SLaks

3
अब Dकहीं भी कमिटमेंट हो सकती है। मान लीजिए कि हमारे पास है A - B - Cऔर हमारे पास कुछ प्रतिबद्ध है Dजो इस शाखा में भी नहीं है। हम इसके SHA को जानते हैं, लेकिन हम कर सकते हैं git rebase -i HEAD~3। अब Aऔर B pickलाइनों के बीच , हम एक नई pick लाइन सम्मिलित करते हैं जो कहती है pick SHA, वांछित का हैश दे रही है D। यह पूर्ण हैश होने की जरूरत नहीं है, बस छोटा हो गया है। git rebase -iबस चेरी जो कुछ भी करता pickहै उसे बफर में लाइनों द्वारा सूचीबद्ध किया जाता है ; उन्हें आपके द्वारा सूचीबद्ध मूल शब्द नहीं होना चाहिए।
कज़

1
@ काज़ यह एक अलग, मान्य उत्तर की तरह दिखता है।
बार्टोसजेक

3
और भी आसान, आप breakसंपादक में कीवर्ड का उपयोग अपनी लाइन में दो कमिट्स (या पहली लाइन पर, अपनी निर्दिष्ट कमिट से पहले कमिट डालने के लिए) के बीच में कर सकते हैं।
साइमन

30

जवाब काफी सरल है, यहाँ जवाब मिला । मान लीजिए आप एक शाखा पर हैं branch। इन चरणों को करें:

  • जब आप नई कमिट सम्मिलित करना चाहते हैं, तो कमिट से एक अस्थायी शाखा बनाएं (इस मामले में कमिट A):

    git checkout -b temp A
    
  • परिवर्तनों को निष्पादित करें और उन्हें प्रतिबद्ध करें, कमिट बनाएं, इसे कॉल करें N:

    git commit -a -m "Message"
    

    (या git addउसके बाद git commit)

  • नई कमिट के बाद आपके द्वारा किए गए कमिट को फिर से शुरू करें (इस मामले में कमिट ) Bऔर Cनई कमिट पर:

    git rebase temp branch
    

(संभवतः आपको -pमर्ज को संरक्षित करने के लिए उपयोग करने की आवश्यकता है , अगर कोई था - ciekawy द्वारा अब कोई मौजूदा टिप्पणी के लिए धन्यवाद )

  • अस्थायी शाखा हटाएं:

    git branch -d temp
    

इसके बाद, इतिहास इस प्रकार है:

A -- N -- B -- C

यह निश्चित रूप से संभव है कि पुनरावृत्ति करते समय कुछ संघर्ष दिखाई देंगे।

यदि आपकी शाखा स्थानीय नहीं है, केवल यह इतिहास को फिर से लिखेगा, तो इससे गंभीर समस्याएं हो सकती हैं।


2
मैं SLaks द्वारा स्वीकृत उत्तर का पालन नहीं कर सकता, लेकिन यह मेरे लिए काम करता है। मेरे द्वारा इच्छित इतिहास प्राप्त करने के बाद, मुझे git push --forceरिमोट रेपो को बदलना पड़ा ।
22

1
रिक्शे का उपयोग करते समय -Xtheirs विकल्प ऑटो का उपयोग करके सही ढंग से टकरावों को हल करता है, इसलिए git rebase temp branch -Xtheirs। एक स्क्रिप्ट में इंजेक्शन लगाने के लिए सहायक उत्तर!
डेविड सी

अपने जैसे नोक-झोंक के लिए मैं उसके बाद जोड़ना चाहूंगा git rebase temp branch, लेकिन इससे पहले git branch -d temp, आपको बस इतना करना है कि फ़िक्स और स्टेज मर्जिंग टकराव और मुद्दा है git rebase --continue, यानी कुछ भी करने की ज़रूरत नहीं है, आदि
Pugsley

19

और भी आसान उपाय:

  1. अंत में अपनी नई कमेटी बनाएं, अब आपके पास:

    A -- B -- C -- D
    
  2. फिर भागो:

    $ git rebase -i hash-of-A
    
  3. Git आपके संपादक को खोलेगा और यह इस तरह दिखेगा:

    pick 8668d21 B
    pick 650f1fc C
    pick 74096b9 D
    
  4. बस इस तरह डी को शीर्ष पर ले जाएं, फिर सहेजें और छोड़ें

    pick 74096b9 D
    pick 8668d21 B
    pick 650f1fc C
    
  5. अब आपके पास होगा:

    A -- D -- B -- C
    

6
अच्छा विचार है, हालांकि, जब आप इन परिवर्तनों को लिखने का इरादा रखते हैं, तो C पर D को लागू करना कठिन हो सकता है। से।
बार्टोज़केपी

मेरे पास एक स्थिति है जहां मेरे पास 3 कमिट हैं कि मैं एक साथ रिबेट करना चाहता हूं और बीच में एक प्रतिबद्ध है जो असंबंधित है। यह सुपर अच्छा है कि बस कमिट करें जो पहले या बाद में कमिट की रेखा से नीचे जाने में सक्षम हो।
10

13

यह मानते हुए कि प्रतिबद्ध इतिहास है preA -- A -- B -- C, यदि आप Aऔर के बीच एक कमिट डालना चाहते हैं B, तो चरण निम्नानुसार हैं:

  1. git rebase -i hash-of-preA

  2. Git आपके संपादक को खोल देगा। सामग्री इस तरह हो सकती है:

    pick 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    

    पहले pickको इसमें बदलें edit:

    edit 8668d21 A
    pick 650f1fc B
    pick 74096b9 C
    

    सुरषित और बहार।

  3. अपना कोड और फिर संशोधित करें git add . && git commit -m "I"

  4. git rebase --continue

अब आपका Git कमिटमेंट हिस्ट्री है preA -- A -- I -- B -- C


यदि आप एक संघर्ष का सामना करते हैं, तो Git इस प्रतिबद्ध पर रुक जाएगा। आप git diffसंघर्ष मार्करों का पता लगाने और उन्हें हल करने के लिए उपयोग कर सकते हैं। सभी संघर्षों को हल करने के बाद, आपको git add <filename>गिट को यह बताने के लिए उपयोग करने की आवश्यकता है कि संघर्ष हल हो गया है और फिर पुनर्मिलन git rebase --continue

यदि आप छूट को पूर्ववत करना चाहते हैं, तो उपयोग करें git rebase --abort


10

यहां एक रणनीति है जो मैंने पढ़े गए अन्य उत्तरों में देखे गए रिबेस के दौरान "एडिट हैक" करने से बचती है।

का उपयोग करके git rebase -iआप उस कमिट के बाद से कमिट्स की एक सूची प्राप्त करते हैं। बस फ़ाइल के शीर्ष पर एक "ब्रेक" जोड़ें, इससे उस बिंदु पर रिबेस टूट जाएगा।

break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>

एक बार लॉन्च होने के बाद, git rebaseअब "ब्रेक" के बिंदु पर रुक जाएगा। अब आप अपनी फ़ाइलों को संपादित कर सकते हैं और अपनी प्रतिबद्धता सामान्य रूप से बना सकते हैं। फिर आप के साथ छूट जारी रख सकते हैं git rebase --continue। इसके कारण आपको ठीक करने के लिए संघर्ष हो सकते हैं। यदि आप खो जाते हैं, तो भूलकर भी आप हमेशा गर्भपात नहीं कर सकते git rebase --abort

इस रणनीति को कहीं भी कमिट करने के लिए सामान्यीकृत किया जा सकता है, बस उस जगह पर "ब्रेक" डालें जहां आप कमिट डालना चाहते हैं।

इतिहास को फिर से लिखने के बाद, मत भूलना git push -f। आपकी शाखा को लाने वाले अन्य लोगों के बारे में सामान्य चेतावनी लागू होती है।


क्षमा करें, लेकिन मुझे यह समझने में परेशानी हो रही है कि यह "रिबेस से कैसे बचा जाए"। आप यहां भाग रहे rebaseहैं। यह ज्यादा अंतर नहीं है कि आप रिबास के दौरान कमिटमेंट बनाएंगे या पहले से।
बार्टोज़केपी

वाह, मेरा मतलब था कि रिबास के दौरान "एडिट हैक" से बचें, मुझे लगता है कि मैंने खराब प्रदर्शन किया।
axerologementy

सही। मेरा उत्तर भी रिबेस के "एडिट" फीचर का उपयोग नहीं करता है। फिर भी, यह अभी तक एक और वैध दृष्टिकोण है - धन्यवाद! :-)
बार्टोसज़पीपी

6

कई अच्छे जवाब यहाँ पहले से ही। मैं सिर्फ 4 आसान चरणों में "नो रिबेस" समाधान जोड़ना चाहता था।


सारांश

git checkout A
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD

व्याख्या

(नोट: इस समाधान का एक फायदा यह है कि आप अपनी शाखा को अंतिम चरण तक नहीं छूते हैं, जब आप 100% सुनिश्चित होते हैं कि आप अंतिम परिणाम के साथ ठीक हैं, तो आपके पास बहुत आसान "पूर्व-पुष्टि" चरण है एबी परीक्षण के लिए अनुमति ।)


प्रारंभिक स्थिति (मैंने masterआपकी शाखा नाम के लिए मान लिया है )

A -- B -- C <<< master <<< HEAD

1) सही जगह पर HEAD को इंगित करके शुरू करें

git checkout A

     B -- C <<< master
    /
   A  <<< detached HEAD

(वैकल्पिक रूप से यहां, HEAD का पता लगाने के बजाय, हम एक अस्थायी शाखा बना सकते हैं git checkout -b temp A, जिसके साथ हमें प्रक्रिया के अंत में डिलीट करने की आवश्यकता होगी। दोनों वेरिएंट काम करते हैं, जैसा कि आप पसंद करते हैं क्योंकि बाकी सब समान रहता है)


2) डाला जाने वाला नया कमिट डी बनाएं

# at this point, make the changes you wanted to insert between A and B, then

git commit -am "Message for commit D"

     B -- C <<< master
    /
   A -- D <<< detached HEAD (or <<< temp <<< HEAD)

3) उसके बाद अंतिम अनुपलब्ध बी और सी की प्रतियाँ लाएँ (यदि अधिक कमिट थीं तो वही लाइन होगी)

git cherry-pick A..C

# (if any, resolve any potential conflicts between D and these last commits)

     B -- C <<< master
    /
   A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)

(यदि आवश्यक हो तो यहां आरामदायक एबी परीक्षण)

अब आपके कोड का निरीक्षण करने का क्षण है, किसी भी चीज का परीक्षण करें जिसे परीक्षण करने की आवश्यकता है, और आप ऑपरेशन के बाद आपको क्या मिला और क्या मिला, इसकी तुलना / निरीक्षण कर सकते हैं ।


4) के बीच Cऔर आपके परीक्षणों के आधार पर C', या तो यह ठीक है या यह केओ है।

(EITHER) 4-ठीक है) अंत में, रेफरी को स्थानांतरित करेंmaster

git branch -f master HEAD

     B -- C <<< (B and C are candidates for garbage collection)
    /
   A -- D -- B' -- C' <<< master

(या) 4-KO) बस masterअपरिवर्तित छोड़ दें

यदि आपने एक अस्थायी शाखा बनाई है, तो बस इसे हटा दें git branch -d <name>, लेकिन अगर आप अलग किए गए HEAD मार्ग के लिए गए हैं, तो इस बिंदु पर किसी भी कार्रवाई की आवश्यकता नहीं है, नए कमिट कचरा संग्रह के लिए योग्य होंगे, जब आप HEADए के साथ रीटेट करते हैंgit checkout master

उन दोनों मामलों (ओके या केओ) में, इस बिंदु पर बस masterफिर से चेकआउट करना है HEAD

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.