मैं git rebase - Santiago के व्यवहार को नहीं समझ सकता


169

मैंने देखा है कि निम्नलिखित git कमांड के दो ब्लॉक में अलग-अलग व्यवहार होते हैं और मुझे समझ नहीं आता कि क्यों।

मैं एक है Aऔर एक Bशाखा है, जो एक के साथ हट जानाcommit

---COMMIT--- (A)
\
 --- (B)

मैं Bनवीनतम पर शाखा को फिर से बनाना चाहता हूं A(और शाखा पर प्रतिबद्ध है B)

---COMMIT--- (A)
         \
          --- (B)

कोई समस्या नहीं अगर मैं:

checkout B
rebase A

लेकिन अगर मैं:

checkout B
rebase --onto B A

यह बिल्कुल काम नहीं करता है, कुछ भी नहीं होता है। मुझे समझ में नहीं आता कि दो व्यवहार अलग क्यों हैं।

Phpstorm git क्लाइंट दूसरे सिंटैक्स का उपयोग करता है, और इसलिए मुझे लगता है कि यह पूरी तरह से टूट गया है, इसीलिए मैं इस सिंटैक्स समस्या के लिए पूछता हूं।


जवाबों:


412

tl; डॉ

आपके मामले में उपयोग Bकरने के शीर्ष पर रिबेस करने का सही सिंटैक्स है:Agit rebase --onto

git checkout B
git rebase --onto A B^

या उस संदर्भ से शुरू करने के शीर्ष पर रिबास जोBAB संदर्भ के साथ B^या उसके माता-पिता हैB~1

यदि आप बीच के अंतर में रुचि रखते हैं git rebase <branch>और git rebase --onto <branch>पढ़ते हैं।

द क्विक: गिट रिबेस

git rebase <branch>शाखा आप अभी चेक आउट कर दिया है, के द्वारा संदर्भित rebase करने जा रहा है HEAD, ऊपर से नवीनतम के लिए प्रतिबद्ध है कि पहुंचा जा सकता है से <branch>लेकिन नहीं से HEAD
रिबासिंग का यह सबसे आम मामला है और यकीनन सामने वाले को कम प्लानिंग की जरूरत होती है।

          Before                           After
    A---B---C---F---G (branch)        A---B---C---F---G (branch)
             \                                         \
              D---E (HEAD)                              D---E (HEAD)

इस उदाहरण में, Fऔर Gऐसे कमिट हैं जो कि branchनहीं बल्कि से पहुंच योग्य हैं HEAD। कहने git rebase branchका Dमतलब यह होगा कि ब्रांचिंग प्वाइंट के बाद यह पहला कमिटमेंट है , और इसे री - लेस ( इसके माता-पिता को बदल दें ) लेटेस्ट कमेट के ऊपर branchसे HEAD, लेकिन जो नहीं है , उससे अलग है G

सटीक: git rebase - २ तर्क सहित

git rebase --ontoआपको एक विशिष्ट प्रतिबद्ध से शुरू करने की अनुमति देता है । यह आपको इस बात पर सटीक नियंत्रण देता है कि किस चीज पर छूट दी जा रही है और कहां। यह उन परिदृश्यों के लिए है जहाँ आपको सटीक होना चाहिए।

उदाहरण के लिए, आइए कल्पना करें कि हमें शुरुआत से HEADशीर्ष पर ठीक से पुन: स्थापित करने की आवश्यकता है । हम केवल अपनी कार्यशील शाखा में लाने में रुचि रखते हैं , साथ ही, हम नहीं रखना चाहते क्योंकि इसमें कुछ असंगत परिवर्तन होते हैं।FEFD

          Before                           After
    A---B---C---F---G (branch)        A---B---C---F---G (branch)
             \                                     \
              D---E---H---I (HEAD)                  E---H---I (HEAD)

इस मामले में, हम कहेंगे git rebase --onto F D। इसका मतलब है की:

HEADजिनके माता-पिता Dशीर्ष पर हैं , वे पहुंच से बाहर होने के लिए प्रतिबद्ध करें F

दूसरे शब्दों में, माता पिता को बदलने की Eसे Dकरने के लिए F। का सिंटैक्स git rebase --ontoहै git rebase --onto <newparent> <oldparent>

एक और परिदृश्य जहां यह काम आता है जब आप एक इंटरैक्टिव रिबेस करने के लिए बिना वर्तमान शाखा से कुछ कमिट्स को जल्दी से निकालना चाहते हैं :

          Before                       After
    A---B---C---E---F (HEAD)        A---B---F (HEAD)

इस उदाहरण में, निकालने के लिए Cऔर Eअनुक्रम से आप कहेंगे git rebase --onto B E, या जहां पुराने माता-पिता थे HEAD, Bवहां से रिबेस करें E

सर्जन: git rebase - 3 तर्कों के साथ पोंटो

git rebase --ontoपरिशुद्धता के संदर्भ में एक कदम आगे जा सकते हैं। वास्तव में, यह आपको किसी अन्य के शीर्ष पर आने वाली एक अनियंत्रित श्रेणी को फिर से बनाने की अनुमति देता है ।

यहाँ एक उदाहरण है:

          Before                                     After
    A---B---C---F---G (branch)                A---B---C---F---G (branch)
             \                                             \
              D---E---H---I (HEAD)                          E---H (HEAD)

इस मामले में, हम E---Hशीर्ष सीमा पर सटीक सीमा को फिर से भरना चाहते हैं, यह देखते हुए कि वर्तमान में Fकहां HEADइंगित कर रहा है। हम ऐसा करके कह सकते हैं git rebase --onto F D H, जिसका अर्थ है:

करता है जिसकी मूल की सीमा rebase Dअप करने के लिए Hकी चोटी पर F

git rebase --ontoएक सीमा के साथ वाक्य रचना तब बन जाती है git rebase --onto <newparent> <oldparent> <until>। चाल यहाँ याद है कि द्वारा संदर्भित प्रतिबद्ध <until>है शामिल रेंज में और नए बन जाएगा HEADके बाद रिबेस पूरा हो गया है।


1
अच्छा उत्तर। सामान्य मामले के लिए बस एक छोटा सा जोड़: <oldparent>यदि श्रेणी के दो हिस्से अलग-अलग शाखाओं पर हों तो नाम टूट जाता है। आम तौर पर यह है: "शामिल होने वाले हर कमिट को शामिल करें, <until>लेकिन इसमें से आने वाली हर कमिटी को बाहर करें <oldparent>।"
मुस्कीक

50
git rebase --onto <newparent> <oldparent>मैंने जो देखा है - सर्वोत्तम व्यवहार की व्याख्या!
रोनकोट

4
धन्यवाद! मैं थोड़े --ontoविकल्प के साथ संघर्ष कर रहा था लेकिन इसने इसे स्पष्ट कर दिया! मुझे यह भी नहीं मिलता कि मैं इसे पहले कैसे समझ नहीं पाया: डी "उत्कृष्ट" ट्यूटोरियल के लिए धन्यवाद :-)
927 में

3
हालांकि यह उत्तर उत्कृष्ट है, मुझे लगता है कि यह सभी संभावित मामलों को कवर नहीं करता है। अंतिम सिंटैक्स फॉर्म का उपयोग अधिक सूक्ष्म प्रकार के रिबास को व्यक्त करने के लिए भी किया जा सकता है। Pro Git (2nd Ed।) में उदाहरण से हटकर, D को H के पूर्वज होने की आवश्यकता नहीं है। इसके बजाय, D और H एक सामान्य पूर्वज के साथ भी काम कर सकते हैं - इस मामले में, Git अपने सामान्य पूर्वज का पता लगाएगा। और उस पूर्वज से एच पर एफ पर फिर से खेलना
पास्ताफैरियन जूल

1
यह मददगार था। मैन पेज तर्कों की व्याख्या नहीं करता है।
a544jh

61

यह आपको समझने के लिए जानने की जरूरत है --onto:

git rebase --onto <newparent> <oldparent>

आप एक माता-पिता को कमिट पर स्विच कर रहे हैं, लेकिन आप कमिट की छाया प्रदान नहीं कर रहे हैं, केवल यह वर्तमान (बूढ़ा) माता-पिता की छाया है।


4
छोटा और आसान। वास्तव में, यह महसूस करते हुए कि मुझे उस व्यक्ति के माता-पिता की प्रतिबद्धता प्रदान करनी है जिसे मैं इसके बजाय फिर से तैयार करना चाहता हूं जिसने मुझे सबसे लंबा समय लिया।
एंटोनियोसस

1
विस्तार से महत्वपूर्ण बात यह है कि आप करंट ब्रांच के एक बूढ़े बच्चे को गोद लेते हैं क्योंकि एक कमिट कई अभिभावकों के लिए अभिभावक हो सकता है लेकिन जब आप खुद को करंट ब्रांच तक सीमित रखते हैं तो कमिट केवल एक कमिट के लिए माता-पिता हो सकते हैं। दूसरे शब्दों में, मूल संबंध जहाज शाखा पर अद्वितीय है, लेकिन यदि आप शाखा निर्दिष्ट नहीं करते हैं, तो ऐसा नहीं है।
ट्रिस्मैगिस्तोस

2
ध्यान देने के लिए: आपको शाखा में होने की आवश्यकता है, या शाखा का नाम 3rd पैरामीटर git rebase के रूप में जोड़ना है - अटलांटा <newparent> <oldparent> <सुविधा-शाखा>
Jason Portnoy

1
यह उत्तर आश्चर्यजनक है, इस सूत्र में आवश्यकतानुसार बिंदु पर सीधे
जॉन कुलविनर

13

शीघ्र ही डालें, दिया गया:

      Before rebase                             After rebase
A---B---C---F---G (branch)                A---B---C---F---G (branch)
         \                                         \   \
          D---E---H---I (HEAD)                      \   E'---H' (HEAD)
                                                     \
                                                      D---E---H---I

git rebase --onto F D H

जो एक ही है (क्योंकि --ontoएक तर्क लेता है):

git rebase D H --onto F

मतलब रेंज में प्रतिबद्ध rebase (डी, एच] एफ सूचना के शीर्ष पर सीमा है बाईं ओर के अनन्य। यह विशेष है क्योंकि यह निर्दिष्ट करने के लिए 1 टाइपिंग जैसे द्वारा प्रतिबद्ध आसान है branchयह बताने के लिए git1 को खोजने की दिशा अलग से प्रतिबद्ध branchयानी Dजो करने के लिए सुराग H

ओपी का मामला

    o---o (A)
     \
      o (B)(HEAD)

git checkout B
git rebase --onto B A

एकल आदेश में बदला जा सकता है:

git rebase --onto B A B

यहाँ पर त्रुटि क्या दिखती है, Bइसका अर्थ है "कुछ चालें चलें जो Bशीर्ष पर शाखा को ले जाएं B"। सवाल यह है कि "कुछ कमिट्स" क्या हैं। यदि आप -iझंडा जोड़ते हैं तो आप देखेंगे कि यह एकल प्रतिबद्ध द्वारा इंगित किया गया है HEAD। कमिट को छोड़ दिया जाता है क्योंकि यह पहले से ही --ontoलक्ष्य पर लागू Bहोता है और इसलिए कुछ भी नहीं होता है।

कमांड किसी भी मामले में बकवास है जहां शाखा का नाम उस तरह दोहराया जाता है। ऐसा इसलिए है क्योंकि कमिट्स की रेंज कुछ कमिट्स होंगी जो पहले से ही उस ब्रांच में हैं और रिबेस के दौरान इन सभी को छोड़ दिया जाएगा।

आगे की व्याख्या और लागू उपयोग git rebase <upstream> <branch> --onto <newbase>

git rebase चूक।

git rebase master

या तो फैलता है:

git rebase --onto master master HEAD
git rebase --onto master master current_branch

रिबास के बाद स्वचालित चेकआउट।

जब मानक तरीके से उपयोग किया जाता है, जैसे:

git checkout branch
git rebase master

आप ध्यान नहीं देंगे कि रिबेस के बाद सबसे हाल ही में रिबेट किए गए कमिट और gitमूव्स ( इतिहास देखें )। क्या दिलचस्प है जब दूसरा तर्क हैश के बजाय शाखा नाम रिबास अभी भी काम करता है, लेकिन स्थानांतरित करने के लिए कोई शाखा नहीं है, इसलिए आप स्थानांतरित शाखा के लिए जाँच किए जाने के बजाय "अलग एचएएडी" में समाप्त होते हैं।branchgit checkout branchgit reflog

ओमित प्राथमिक डायवर्ट किया गया।

masterमें --onto1 से लिया जाता है git rebaseतर्क।

                   git rebase master
                              /    \
         git rebase --onto master master

तो व्यावहारिक रूप से यह किसी भी अन्य प्रतिबद्ध या शाखा हो सकता है। इस तरह आप लेटेस्ट रीमेस कमिट्स को लेटेस्ट लेवल और प्राइमरी डाइवर्टेड कमिट्स को छोड़ सकते हैं।

git rebase --onto master HEAD~
git rebase --onto master HEAD~ HEAD  # Expanded.

द्वारा किए HEADगए सिंगल कमिट masterको "डिसेक्टेड हेड" में समाप्त कर देगा।

स्पष्ट चेकआउट से बचें।

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

(branch) $ git rebase master
(branch) $ git rebase master branch  # Expanded.
(branch) $ git rebase master $(git rev-parse --abbrev-ref HEAD)  # Kind of what git does.

इसका मतलब है कि आप किसी भी जगह से कमिट और ब्रांच को रिजेक्ट कर सकते हैं । तो रिबास के बाद स्वचालित चेकआउट के साथ आपको रिबास से पहले या बाद में अलग से चेकआउट की गई शाखा को अलग करने की आवश्यकता नहीं है।

(master) $ git rebase master branch
(branch) $ # Rebased. Notice checkout.

8

सीधे शब्दों में कहें, git rebase --ontoएक सीमा का चयन करता है और उन्हें पैरामीटर के रूप में दी गई प्रतिबद्धताओं पर विद्रोह करता है।

के लिए आदमी पृष्ठों पढ़ें git rebase, "पर" के लिए खोजें। उदाहरण बहुत अच्छे हैं:

example of --onto option is to rebase part of a branch. If we have the following situation:

                                   H---I---J topicB
                                  /
                         E---F---G  topicA
                        /
           A---B---C---D  master

   then the command

       git rebase --onto master topicA topicB

   would result in:

                        H'--I'--J'  topicB
                       /
                       | E---F---G  topicA
                       |/
           A---B---C---D  master

इस मामले में आप गिट को ऊपर से कमिट्स को फिर से बनाने के topicAलिए कहते topicBहैं master


8

के बीच अंतर को बेहतर ढंग से समझने के लिए git rebaseऔर git rebase --ontoयह जानना अच्छा है कि दोनों आज्ञाओं के लिए संभावित व्यवहार क्या हैं। git rebaseहमें चयनित शाखा के शीर्ष पर अपने कमिट को स्थानांतरित करने की अनुमति दें। जैसे यहाँ:

git rebase master

और परिणाम है:

Before                              After
A---B---C---F---G (master)          A---B---C---F---G (master)
         \                                           \
          D---E (HEAD next-feature)                   D'---E' (HEAD next-feature)

git rebase --ontoअधिक उपजी है। यह हमें विशिष्ट प्रतिबद्ध चुनने की अनुमति देता है जहां हम शुरू करना चाहते हैं और यह भी कि हम कहां खत्म करना चाहते हैं। जैसे यहाँ:

git rebase --onto F D

और परिणाम है:

Before                                    After
A---B---C---F---G (branch)                A---B---C---F---G (branch)
         \                                             \
          D---E---H---I (HEAD my-branch)                E'---H'---I' (HEAD my-branch)

अधिक विवरण प्राप्त करने के लिए, मैं आपको git rebase - Santiago सिंहावलोकन के बारे में अपना लेख देखने की सलाह देता हूं


@ मैकीने ज़रूर, मैं इसे भविष्य में ध्यान में
रखूंगा

तो, हम पढ़ सकते हैं git rebase --onto F Dके रूप में एफ के रूप में D के माता-पिता के सेट बच्चे , हम नहीं कर सकते?
प्रिहक्स

2

आपके लिए ontoदो अतिरिक्त शाखाओं की आवश्यकता है। उस कमांड के साथ आप branchBउस से कमिट लगा सकते हैं जो branchAकिसी दूसरी शाखा पर आधारित है जैसे master। नीचे दिए गए नमूने branchBपर आधारित है branchAऔर आप के परिवर्तनों को लागू किए बिना branchBपर परिवर्तन लागू करना चाहते हैं ।masterbranchA

o---o (master)
     \
      o---o---o---o (branchA)
                   \
                    o---o (branchB)

आदेशों का उपयोग करके:

checkout branchB
rebase --onto master branchA 

आपको निम्नलिखित पदानुक्रम मिलेंगे।

      o'---o' (branchB)
     /
o---o (master)
     \
      o---o---o---o (branchA)

1
क्या आप कृपया थोड़ा और समझा सकते हैं, अगर हम मास्टर पर रिबास करना चाहते हैं, तो यह कैसे चालू शाखा बन जाता है? यदि आप ऐसा करते हैं तो rebase --onto branchA branchBपूरी मास्टर ब्रांच को ब्रांच के सिर पर रख देंगे?
पॉलिमरेज़

8
क्या यह नहीं होना चाहिए checkout branchB: rebase --onto master branchA?
सुनहरा अनुपात

4
इसे क्यों उखाड़ा गया है? यह वह नहीं करता है जो यह कहता है कि यह करता है।
डी नोवो

मैंने जवाब को संपादित किया और तय किया, इसलिए लोगों को पहले अपनी रेपो शाखाओं को तोड़ने की ज़रूरत नहीं है और उसके बाद ही आकर टिप्पणियों को पढ़ें ... 34
कामाफेदर

0

एक और मामला है जहां git rebase --ontoसमझ पाना मुश्किल है: जब आप एक सममित अंतर चयनकर्ता (तीन डॉट्स) के परिणामस्वरूप एक प्रतिबद्ध पर छूट देते हैं... ') के

Git 2.24 (Q4 2019) उस मामले को प्रबंधित करने का एक बेहतर काम करता है:

प्रतिबद्ध देखें 414d924 , 4effc5b कमिट करें , c0efb4c , 2b318aa (27 अगस्त 2019), और 793ac7e कमिट करें , डेंटन लियू ( ) द्वारा 359eceb (25 अगस्त 2019 ) । मदद द्वारा: एरिक सनशाइन ( ) , Junio सी Hamano ( ) , Ævar Arnfjörð Bjarmason ( ) , और जोहानिस Schindelin ( ) । देखें प्रतिबद्ध 6330209 , c9efc21 प्रतिबद्ध (27 अगस्त 2019), और 4336d36 प्रतिबद्ध द्वारा (25 अगस्त 2019) Ævar Arnfjörð Bjarmason ( )Denton-L
sunshinecogitsteravardscho
avar
मदद द्वारा: एरिक सनशाइन ( sunshineco) , Junio सी Hamano ( gitster) , Ævar Arnfjörð Bjarmason ( avar) , और जोहानिस Schindelin ( dscho)
(द्वारा विलय Junio सी Hamano - gitster- में प्रतिबद्ध 640f9cd , 30 सितं, 2019)

rebase: --ontoअधिक मामलों में तेजी से आगे बढ़ना

इससे पहले, जब हमारे पास निम्नलिखित ग्राफ था,

A---B---C (master)
     \
      D (side)

रनिंग ' git rebase --onto master... master side' के परिणामस्वरूप Dहमेशा बगावत होगी, चाहे जो भी हो।

इस बिंदु पर, "गेट-डिफ कम रेंज में " " डबल-डॉट ..'और ट्रिपल-डॉट के बीच अंतर क्या हैं ...? "

https://sphinx.mythic-beasts.com/~mark/git-diff-help.png

यहाँ: " master..." से तात्पर्य है master...HEAD, जो है B: HEAD अगल हैड (वर्तमान में चेक आउट): आप रिबास कर रहे हैं B
आप क्या कर रहे हैं? कोई भी मास्टर में प्रतिबद्ध नहीं है, और sideशाखा से पहुंच योग्य नहीं है : केवल एक ही प्रतिबद्ध फिटिंग है जो विवरण: D... जो पहले से ही शीर्ष पर है B!

2.24 से पहले फिर से, इस तरह के rebase --ontoपरिणाम Dहमेशा बगावत किया जाएगा, कोई फर्क नहीं पड़ता।

हालांकि, वांछित व्यवहार यह है कि रिबेस को नोटिस करना चाहिए कि यह तेजी से अग्रेषित करने योग्य है और इसके बजाय ऐसा करें।

वह rebase --onto B Aओपी का दीवाना है, जिसने कुछ नहीं किया।

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

options.upstream &&
!oidcmp(&options.upstream->object.oid, &options.onto->object.oid)

शर्तों को हटा दिया गया था cmd_rebase, हम एक विकल्प को फिर से प्रस्तुत करते हैं can_fast_forward
विशेष रूप से, के मर्ज ठिकानों की जांच करना upstreamऔर headएक असफल मामले को ठीक करता है t3416

T3416 के लिए संक्षिप्त ग्राफ़ निम्नानुसार है:

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

और असफल आदेश था

git rebase --onto master...topic F topic

इससे पहले, Git यह देखेगा कि एक मर्ज बेस ( C, परिणाम master...topic), और मर्ज और समान थे इसलिए यह गलत तरीके से 1 लौटाएगा, यह दर्शाता है कि हम तेजी से आगे बढ़ सकते हैं। इसके कारण बगावत का ग्राफ ' ABCFG' होगा जब हम उम्मीद कर रहे थे ' ABCG'।

एक rebase --onto C F topicसाधन किसी भी प्रतिबद्ध के बाद F , तक पहुंचा जा सकता topicHEAD: वह यह है कि Gकेवल, नहीं Fही।
इस मामले में तेजी से आगे Fबढ़ने से विद्रोही शाखा में शामिल होगा , जो गलत है।

अतिरिक्त तर्क के साथ, हम पता लगाते हैं कि अपस्ट्रीम और हेड का मर्ज बेस है F। चूंकि ऐसा नहीं है F, इसका मतलब यह है कि हम कमिट्स के पूरे सेट को रिबास नहीं कर रहे हैं master..topic
चूंकि हम कुछ कमिट्स को शामिल नहीं कर रहे हैं, इसलिए एक फास्ट-फ़ॉरवर्ड नहीं किया जा सकता है और इसलिए हम सही तरीके से 0 लौटाते हैं।

-fइस परिवर्तन के परिणामस्वरूप विफल हुए मामलों की जांच करने के लिए ' ' जोड़ें क्योंकि वे तेजी से आगे बढ़ने की उम्मीद नहीं कर रहे थे ताकि एक रिबास मजबूर हो जाए।

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