गेट चेरी पिक बनाम रिबास


120

मैंने हाल ही में गिट के साथ काम करना शुरू किया है।

ऑनलाइन Git पुस्तक पर जाने से मुझे "Git Rebase" अनुभाग के तहत निम्नलिखित मिला:

रीबेस कमांड के साथ, आप उन सभी परिवर्तनों को ले सकते हैं जो एक शाखा पर किए गए थे और उन्हें दूसरे पर फिर से खेलना था।

(यहां से उद्धृत: http://git-scm.com/book/en/Git-Branching-Rebasing )

मुझे लगा कि यह git चेरी-पिक की सटीक परिभाषा है (वर्तमान में जांच की गई शाखा पर फिर से एक प्रतिबद्ध या प्रतिबद्ध वस्तुओं का एक सेट)।

दोनों के बीच क्या अंतर है ?

जवाबों:


166

चूँकि समय git cherry-pickकई कमिट्स को लागू करने में सक्षम होने के लिए सीखा गया था, इसलिए वास्तव में यह अंतर कुछ हद तक मूट हो गया, लेकिन इसे अभिसरण विकास कहा जाता है;;

असली अंतर दोनों उपकरण बनाने के मूल इरादे में है:

  • git rebaseकिसी कार्य को किसी निजी शाखा में, किसी अपस्ट्रीम शाखा के संस्करण X के विरुद्ध, उसी शाखा (Y> X) के संस्करण Y के लिए बनाए गए परिवर्तनों की एक श्रृंखला को फ़ॉरवर्ड-पोर्ट करना है। यह प्रभावी रूप से उस श्रृंखला के आधार को बदल देता है, इसलिए "रिबासिंग" होता है।

    (यह डेवलपर को किसी भी मनमाने तरीके से कमिट की श्रृंखला को ट्रांसप्लांट करने की अनुमति देता है, लेकिन यह कम स्पष्ट उपयोग का है)

  • git cherry-pickविकास की एक पंक्ति से दूसरी में एक दिलचस्प प्रतिबद्धता लाने के लिए है। एक क्लासिक उदाहरण एक अस्थिर विकास शाखा पर एक स्थिर (रखरखाव) शाखा पर किए गए सुरक्षा फिक्स का समर्थन कर रहा है, जहां mergeकोई मतलब नहीं है, क्योंकि यह बहुत सारे अवांछित बदलाव लाएगा।

    अपनी पहली उपस्थिति के बाद से git cherry-pick, एक-एक करके कई कमिट्स लेने में सक्षम है।

इसलिए, संभवतः इन दो आदेशों के बीच सबसे अलग अंतर यह है कि वे उस शाखा का इलाज कैसे करते हैं जिस पर वे काम करते हैं: git cherry-pickआमतौर पर कहीं और से एक प्रतिबद्ध लाता है और इसे आपकी वर्तमान शाखा के शीर्ष पर लागू करता है, एक नई प्रतिबद्धता दर्ज करते हुए, git rebaseआपकी वर्तमान शाखा लेता है और फिर से लिखता है। अपने स्वयं के टिप की एक श्रृंखला एक तरह से या किसी अन्य तरीके से शुरू होती है। हां, यह सामान्य रूप से डूबा हुआ वर्णन है कि क्या git rebaseकर सकते हैं, लेकिन यह सामान्य विचार को सिंक में रखने की कोशिश करने के लिए जानबूझकर किया गया है।

git rebaseचर्चा किए जाने के उपयोग का एक उदाहरण समझाने के लिए अपडेट करें ।

इस स्थिति को देखते हुए,
पुनरावृत्ति से पहले रेपो की स्थिति
पुस्तक बताती है:

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

इस उदाहरण में, आप निम्न कार्य करेंगे:

$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command

यहां "पकड़" यह है कि इस उदाहरण में, "प्रयोग" शाखा (रिबासिंग के लिए विषय) को मूल रूप से "मास्टर" शाखा से कांटा गया था, और इसलिए यह इसके साथ C2 के माध्यम से C0 साझा करता है - प्रभावी रूप से, "प्रयोग" है " मास्टर "ऊपर, और सहित, C2 प्लस इसके ऊपर C3 प्रतिबद्ध है। (यह सबसे सरल संभव मामला है; निश्चित रूप से, "प्रयोग" में इसके मूल आधार के ऊपर कई दर्जनों कमिट हो सकते हैं।)

अब "मास्टर" git rebaseकी वर्तमान टिप पर "प्रयोग" को रीबेस करने के लिए कहा git rebaseजाता है , और इस तरह से जाता है:

  1. git merge-baseयह देखने के लिए दौड़ता है कि "प्रयोग" और "मास्टर" (दूसरे शब्दों में, डायवर्सन का क्या मतलब है) दोनों द्वारा साझा की गई अंतिम प्रतिबद्धता है। यह C2 है।
  2. डायवर्जन बिंदु के बाद से किए गए सभी कमिट को बचाता है; हमारे खिलौना उदाहरण में, यह सिर्फ C3 है।
  3. "मास्टर" की नोक पर इंगित करने के लिए HEAD (जो कि "प्रयोग" के टिप कमिट की ओर इशारा करता है) को "मास्टर" की ओर इंगित करता है - हम इस पर रिबास कर रहे हैं।
  4. सहेजे गए प्रत्येक कमिट को लागू करने की कोशिश करता है (जैसे कि यदि git apply) क्रम में। हमारे खिलौना उदाहरण में यह सिर्फ एक प्रतिबद्ध है, सी 3। मान लीजिए कि इसका एप्लिकेशन एक प्रतिबद्ध C3 का उत्पादन करेगा। '
  5. यदि सब ठीक हो जाता है, तो "प्रयोग" संदर्भ को अंतिम रूप से सहेजे गए कमेंट (हमारे मामले में C3) को लागू करने के परिणामस्वरूप प्रतिबद्ध करने के लिए अद्यतन किया जाता है।

अब वापस अपने सवाल पर। जैसा कि आप देख सकते हैं, यहां तकनीकी रूप से git rebase वास्तव में "प्रयोग" से "मास्टर" की नोक पर आने वाली श्रृंखलाओं का प्रत्यारोपण किया जाता है, इसलिए आप सही तरीके से बता सकते हैं कि वास्तव में प्रक्रिया में "एक और शाखा" है। लेकिन यह है कि टिप "प्रयोग" से प्रतिबद्ध है, "प्रयोग" में नई टिप प्रतिबद्ध होने से समाप्त हो गई, बस इसका आधार बदल गया:
विलय के बाद की स्थिति

फिर, तकनीकी रूप से आप यह बता सकते हैं कि git rebaseयहां "मास्टर" से कुछ निश्चित तरीके शामिल हैं, और यह बिल्कुल सही है।


2
धन्यवाद। मैं अभी भी पूरी तरह से समझ नहीं पाया कि आपका यहाँ क्या मतलब है। पुस्तक में, उदाहरण दिया गया है कि रिबेस एक अन्य शाखा से टिप की एक श्रृंखला लागू करता है, जबकि आप कहते हैं कि यह "उसी शाखा" से है। या शायद कुछ मामले हैं कि यह कैसे काम करता है?
लाइसर्जिक-एसिड

1
मेरे जवाब को अपडेट करके मामले को समझाने की कोशिश की।
कोस्टिक्स

98

चेरी-पिक के साथ, मूल कमिट / शाखा चारों ओर चिपक जाती है और नए कमिट बन जाते हैं। रिबास के साथ, पूरी शाखा को पुनःप्राप्त कमिट्स की ओर इशारा करते हुए शाखा के साथ ले जाया जाता है।

मान लीजिए कि आपने शुरुआत की:

      A---B---C topic
     /
D---E---F---G master

rebase:

$ git rebase master topic

आपको मिला:

              A'--B'--C' topic
             /
D---E---F---G master

चुनना:

$ git checkout master -b topic_new
$ git cherry-pick A^..C

आपको मिला:

      A---B---C topic
     /
D---E---F---G master
             \
              A'--B'--C' topic_new

git के बारे में अधिक जानकारी के लिए इस पुस्तक में इसका अधिकांश हिस्सा है (http://git-scm.com/book)


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

अगर इसके बजाय एक या एक से अधिक कमिट छोड़ने पर इंटरएक्टिव रीबेस हो गया, तो आपके पास आखिर में कौन सी शाखाएँ होंगी? यदि यह केवल topicशीर्ष पर बगावत कर रहा था master, तो इसमें बाईं ओर कमिट नहीं हैं, तो वे किस शाखा का हिस्सा होंगे?
एंथनी

बस एक और चीज जो मैं जोड़ना चाहता हूं: यदि आप git checkout topicऔर फिर git reset --hard C'चेरी पिकिंग के बाद, तो आपके पास रिबासिंग के बाद के समान परिणाम हैं। मैंने अपने आप को बहुत सारे मर्ज संघर्षों से बचाया ताकि चेरी को रीसैसिंग से अधिक उपयोग किया जा सके, क्योंकि आम पूर्वज वापस आ गए थे।
सॉरीमिसजैकसन

@anthony - stackoverflow.com/questions/11835948/… : जहां तक ​​मैं समझता हूं कि वे खो गए हैं। मैं नहीं हूँ, gitलेकिन यह rebase/ मेरे पास cherry-pickउन सभी विवरणों पर है gitजिनसे मुझे समझने में समस्या हुई।
thoni56

1
आपके रेखांकन अच्छे से अधिक नुकसान करते हैं, क्योंकि वे कार्यात्मक रूप से समान हैं। एकमात्र अंतर इसके द्वारा बनाई गई शाखा है git checkout -b, जिसका कोई लेना-देना नहीं है git cherry-pick। एक बेहतर तरीका यह बताने के लिए कि आप जो कहना चाह रहे हैं वह होगा “आप शाखा git rebaseपर चलते हैं topicऔर इसे पास करते हैं master; आप शाखा git cherry-pickपर दौड़ते हैं masterऔर इसे पास करते हैं (से आते हैं) topic। ”
रोरी ओ'केन

14

चेरी-पिकिंग व्यक्तिगत आवागमन के लिए काम करता है

जब आप रिबेसिंग कि यह लागू होता है सब करता शाखा है कि वहाँ याद कर रहे हैं के मुखिया के इतिहास में।


धन्यवाद। क्या आप जानते हैं कि ये कवर के तहत समान काम करते हैं? (उनके मध्यवर्ती आउटपुट को "पैच" फ़ाइलों आदि में संग्रहीत करें)।
गीतकार-एसिड

अफाक हां। यह एक-एक करके सभी पैच लागू करता है। यही कारण है कि आपको कभी-कभी एक संघर्ष के बीच में विलय से पहले संघर्षों को हल करना होगा।
iltempo

6
@iltempo, इसने व्यक्तिगत रूप से Git के पुराने संस्करणों में काम किया; वर्तमान समय में आप कुछ ऐसा कर सकते हैं git cherry-pick foo~3..fooऔर एक "एक" द्वारा उठाए गए "फू" से पेड़ के शीर्ष को प्राप्त कर सकते हैं ।
kostix

1
git-rebase उसी एपीआई का उपयोग करता है जैसे चेरी-पिकिंग कोडबेस में करता है, iirc
वैकल्पिक

मुझे नहीं लगता कि वे वास्तव में कवर के तहत ही काम करते हैं। मैंने हजारों कमिट्स को रिबास करने की कोशिश की है और मुझे लगता है कि git एक बड़ी मेलबॉक्स फ़ाइल बनाता है और फिर उस git amपर चलता है। जबकि एक चेरी पिक कमिट द्वारा लागू होती है (संभवतः प्रत्येक पैच के लिए एकल-संदेश मेलबॉक्स बनाकर)। मेरा रीबेज़ विफल हो रहा था क्योंकि मेलबॉक्स फ़ाइल जो इसे बना रही थी, ड्राइव पर अंतरिक्ष से बाहर भाग गई, लेकिन उसी संशोधन रेंज के साथ चेरी-पिक सफल हुई (और तेज़ी से दौड़ती हुई प्रतीत होती है)।
केवल

11

एक छोटा जवाब:

  • git चेरी-पिक अधिक "निम्न स्तर" है
  • जैसे, यह गिट रीबेस का अनुकरण कर सकता है

ऊपर दिए गए उत्तर अच्छे हैं, मैं सिर्फ उनके अंतर्संबंध को प्रदर्शित करने के प्रयास में एक उदाहरण देना चाहता था।

"गीट रिबेस" को क्रियाओं के इस क्रम से बदलने की अनुशंसा नहीं की जाती है, यह सिर्फ "अवधारणा का प्रमाण" है, जो मुझे आशा है, यह समझने में मदद करता है कि चीजें कैसे काम करती हैं।

निम्नलिखित खिलौना भंडार को देखते हुए:

$ git log --graph --decorate --all --oneline
* 558be99 (test_branch_1) Test commit #7
* 21883bb Test commit #6
| * 7254931 (HEAD -> master) Test commit #5
| * 79fd6cb Test commit #4
| * 48c9b78 Test commit #3
| * da8a50f Test commit #2
|/
* f2fa606 Test commit #1

कहो, हमारे पास कुछ बहुत महत्वपूर्ण परिवर्तन हैं (# 5 के माध्यम से # 2) मास्टर में जो हम अपने test_branch_1 में शामिल करना चाहते हैं। आमतौर पर हम सिर्फ एक शाखा में स्विच करते हैं और "गिट रिबेस मास्टर" करते हैं। लेकिन जैसा कि हम दिखावा कर रहे हैं कि हम केवल "गिट चेरी-पिक" से लैस हैं, हम करते हैं:

$ git checkout 7254931                # Switch to master (7254931 <-- master <-- HEAD)
$ git cherry-pick 21883bb^..558be99   # Apply a range of commits (first commit is included, hence "^")    

इन सभी कार्यों के बाद हमारा कमिटमेंट ग्राफ इस प्रकार होगा:

* dd0d3b4 (HEAD) Test commit #7
* 8ccc132 Test commit #6
* 7254931 (master) Test commit #5
* 79fd6cb Test commit #4
* 48c9b78 Test commit #3
* da8a50f Test commit #2
| * 558be99 (test_branch_1) Test commit #7
| * 21883bb Test commit #6
|/
* f2fa606 Test commit #1

जैसा कि हम देख सकते हैं, 7254931 (मास्टर की एक टिप कमिट) के खिलाफ # 6 और # 7 लागू किए गए थे। हेड को स्थानांतरित किया गया था और एक प्रतिबद्ध इंगित करता है, जो अनिवार्य रूप से, एक विद्रोही शाखा का एक टिप है। अब हमें बस इतना करना है कि एक पुराने ब्रांच पॉइंटर को हटा दें और एक नया बनाएं:

$ git branch -D test_branch_1
$ git checkout -b test_branch_1 dd0d3b4

test_branch_1 अब नवीनतम मास्टर स्थिति से निहित है। किया हुआ!


लेकिन रिबेट गिट चेरी-पिक का अनुकरण भी कर सकता है?
नंबर 945

चूंकि cherry-pickमैं कई प्रकार के आवागमन लागू करने में सक्षम हूं, इसलिए मुझे लगता है, हां। हालाँकि यह काम करने का एक अजीब तरीका है, कुछ भी आपको शीर्ष पर स्थित अपनी सुविधा शाखा में चेरी-पिकिंग को रोकने से रोकता है master, फिर सुविधा शाखा को हटा दें और इसे फिर से बनाएं, ताकि यह टिप की ओर इशारा करे master। आप के git rebaseअनुक्रम के रूप में सोच सकते हैं git cherry-pick feature_branch, git branch -d feature_branchऔर git branch feature_branch master
raiks

7

वे दोनों एक शाखा के दूसरे के शीर्ष पर पुनर्लेखन के लिए आदेश देते हैं: अंतर यह है कि किस शाखा में है - "तुम्हारा" (वर्तमान में बाहर की जाँच की गई HEAD) या "उनका" (शाखा कमांड के तर्क के रूप में पारित) - आधार यह पुनः लेखन के लिए।

git rebaseएक लेता है शुरू करने और रिप्ले अपने बाद आने वाले के रूप में करता उनकी (प्रारंभिक प्रतिबद्ध)।

git cherry-pickआपका (आपके ) आने के बाद कमिट्स का एक सेट लेता है और उनके कमेंट्स को फिर से देखता हैHEAD

दूसरे शब्दों में, दो आदेशों कर रहे हैं, उनके मूल व्यवहार में (उनके अलग-अलग प्रदर्शन विशेषताओं अनदेखी, सम्मेलनों आह्वान करने और वृद्धि विकल्प), सममित : शाखा बाहर की जाँच barऔर चल रहा git rebase fooसेट barशाखा बाहर की जाँच के रूप में एक ही इतिहास के लिए शाखा fooऔर चल git cherry-pick ..barस्थापित करेगा foo, (से परिवर्तन foo, इसके बाद के परिवर्तन bar)।

नाम-वार, दो आदेशों के बीच के अंतर को याद किया जा सकता है कि हर एक यह वर्णन करता है कि वह वर्तमान शाखा का क्या करता है : rebaseदूसरे प्रमुख को आपके परिवर्तनों के लिए नया आधार बनाता है , जबकि cherry-pickअन्य शाखा से परिवर्तन चुनता है और उन्हें सबसे ऊपरHEAD रखता है आपकी (जैसे संडे के ऊपर चेरी)।


1
मैं तुम्हारे सिवाय किसी भी उत्तर को नहीं समझ सका! यह संक्षिप्त है और बिना सही शब्द-बोध के एकदम सही है।
नक्षत्र

4

दोनों बहुत समान चीजें करते हैं; मुख्य वैचारिक अंतर (सरलीकृत शब्दों में) है:

  • रिबास चालें वर्तमान शाखा से दूसरी शाखा में जाती हैं

  • चेरी-पिक प्रतियां दूसरी शाखा से वर्तमान शाखा तक जाती हैं

@ केनी हो के उत्तर के समान आरेखों का उपयोग करना :

इस प्रारंभिक अवस्था को देखते हुए:

A---B---C---D master
     \
      E---F---G topic

... और यह मानते हुए कि आप चाहते हैं topicकि वर्तमान masterशाखा के शीर्ष पर फिर से शाखा में आने से आपको दो विकल्प मिलें:

  1. रिबास का उपयोग करना: आप सबसे पहले इसे topicकरके जाएंगेgit checkout topic , और फिर चलाकर शाखा को स्थानांतरित git rebase master, उत्पादन:

    A---B---C---D master
                 \
                  E'---F'---G' topic
    

    परिणाम: आपकी वर्तमान शाखा topicको विद्रोह (स्थानांतरित) किया गया था master
    topicशाखा अद्यतन किया गया था, जबकि masterशाखा बनाए रखा गया।

  2. चेरी-पिक का उपयोग करना : आप पहले masterकरके जाएंगे git checkout master, और फिर शाखा को कॉपी करके चलाएंगे git cherry-pick topic~3..topic(या, समतुल्य रूप से;git cherry-pick B..G उत्पादन ) : उत्पादन

    A---B---C---D---E'---F'---G' master
         \
          E---F---G topic
    

    परिणाम: से आने वाले कमिट topicको कॉपी किया गया master। शाखा अद्यतन किया गया था, जबकि
    mastertopic शाखा बनाए रखा गया।


बेशक, यहाँ आपको स्पष्ट रूप से चेरी-पिक को रेंज संकेतन का उपयोग करते हुए कमिट्स का एक क्रम चुनना थाfoo..bar । यदि आपने शाखा का नाम केवल पास कर दिया है git cherry-pick topic, तो इसके परिणामस्वरूप, शाखा के सिरे पर केवल कमिट लगा होगा, जिसके परिणामस्वरूप:

A---B---C---D---G' master
     \
      E---F---G topic
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.