चेरी-पिक काम के बाद गिट कैसे विलीन हो जाता है?


190

आइए कल्पना करें कि हमारे पास एक masterशाखा है।

फिर हम एक निर्माण करते हैं newbranch

git checkout -b newbranch

और दो नए कमिट करें newbranch: कमिट 1 और कमिट 2

फिर हम मास्टर और बनाने के लिए स्विच करते हैं cherry-pick

git checkout master
git cherry-pick hash_of_commit1

में देख gitkहम देखते हैं कि commit1 तो तकनीकी रूप से वे दो अलग करता हैं और उसके चेरी उठाया संस्करण अलग हैश है,।

अंत में हम विलय newbranchमें master:

git merge newbranch

और देखते हैं कि अलग-अलग हैश के साथ इन दो कामों को समस्याओं के बिना विलय कर दिया गया था, हालांकि वे कहते हैं कि समान परिवर्तन दो बार लागू किए जाने चाहिए, इसलिए उनमें से एक को विफल होना चाहिए।

क्या वास्तव में मर्ज करते समय कमिट की सामग्री का स्मार्ट विश्लेषण करते हैं और यह निर्णय लेते हैं कि परिवर्तनों को दो बार लागू नहीं किया जाना चाहिए या इन कमिटों को आंतरिक रूप से एक साथ लिंक के रूप में चिह्नित किया गया है?

जवाबों:


131

संक्षिप्त जवाब

चिंता मत करो, इसे संभाल लेंगे।

लंबा जवाब

उदाहरण के लिए SVN 1 के विपरीत , Git डेल्टा फॉर्मेट में कमिट्स को स्टोर नहीं करता है, लेकिन स्नैपशॉट-आधारित 2,3 है । हालांकि SVN प्रत्येक मर्ज किए गए कमिट को एक पैच के रूप में लागू करने का प्रयास करेगा (और आपके द्वारा बताए गए सटीक कारण के लिए विफल), Git आमतौर पर इस परिदृश्य को संभालने में सक्षम है।

विलय करते समय, Git दोनों HEAD के स्नैपशॉट को एक नए स्नैपशॉट में संयोजित करने का प्रयास करेगा। यदि कोड या फ़ाइल का एक हिस्सा दोनों स्नैपशॉट में समान है (यानी क्योंकि एक प्रतिबद्ध पहले से ही चेरी उठाया गया था), गिट इसे छू लेंगे।

सूत्रों का कहना है

1 छोड़ - तोड़फोड़ तोड़फोड़ में
2 गिट मूल बातें
3 गिट वस्तु मॉडल


40
वास्तव में, मैं कहूंगा कि आपको विलय के बारे में चिंता करनी चाहिए और "गिट इसे संभाल लेंगे" अंगूठे का एक अच्छा नियम नहीं है।
cregox

4
वास्तव में मर्ज कुछ मामलों में डुप्लिकेट सामग्री का परिणाम हो सकता है। गिट इसे कभी-कभी संभालता है, लेकिन कभी-कभी यह नहीं होता है।
donquixote

यह बहुत ही गलत है। बहुत सारे भंडार योग्य रूपों में फ़ाइल फ़ाइलों को संग्रहीत करता है। और अगर मुझे याद है कि SVN स्नैपशॉट्स को स्टोर करता था।
he_the_great

2
@he_the_great, नहीं। SVN के स्किप-डेल्टा स्टोरेज फॉर्मेट (! = स्नैपशॉट) को मैनुअल में अच्छी तरह से प्रलेखित किया गया है । और मुझे वास्तव में वह नहीं मिल रहा है, जिसका आप द्वारा मतलब है । मैं एक देशी वक्ता नहीं हूँ, लेकिन मुझे पूरा यकीन है कि यह एक वास्तविक शब्द नहीं है।
हैलमेट

2
@he_the_great लेकिन पूर्ण फ़ाइल में फ़ाइल परिणामों के लिए किसी भी दिए गए हैश के रूप में भी packfiles। हाँ, यह डेल्टा का उपयोग करके संपीड़ित करता है, लेकिन यह एक प्रतिबद्धताओं में बदलाव के लिए एक डेल्टा नहीं है, बल्कि एक फ़ाइल के लिए हैश के बीच एक डेल्टा है। जहां तक ​​प्रतिबद्ध वस्तु का संबंध है, यह एक पेड़ का संदर्भ दे रही है जो एक पूर्ण फ़ाइल के लिए हैश का संदर्भ दे रहा है। हुड के तहत डेटा संपीड़ित होता है जो गिट के काम करने के तरीके को प्रभावित नहीं करता है। जहाँ तक एक कमिट की बात है, तो git पूरी फ़ाइलों को स्टोर करता है, SVN मेरी समझ में आने के लिए डेल्टा स्टोर करता है।
पीटर ओल्सन

44

इस तरह के मर्ज के बाद आपको इतिहास में दो बार चेरी-चुना हुआ हो सकता है।

इसे रोकने के लिए समाधान मैं लेख से उद्धरण करता हूं जो कि डुप्लिकेट (चेरी-उठाया) के साथ शाखाओं के लिए सिफारिश करता है मर्ज से पहले रिबास का उपयोग करता है:

git चेरी-पिक के बाद git मर्ज: डुप्लिकेट कमिट्स से बचना

कल्पना कीजिए कि हमारे पास मास्टर शाखा और शाखा b है:

   o---X   <-- master
    \
     b1---b2---b3---b4   <-- b

अब हमें तत्काल मास्टर में बी 1 और बी 3 को कमिट करने की आवश्यकता है, लेकिन शेष बी में कमिट नहीं। तो हम क्या करते हैं मास्टर शाखा और चेरी-पिक कमिट बी 1 और बी 3 चेकआउट करते हैं:

$ git checkout master
$ git cherry-pick "b1's SHA"
$ git cherry-pick "b3's SHA"

परिणाम होगा:

   o---X---b1'---b3'   <-- master
    \
     b1---b2---b3---b4   <-- b

मान लीजिए कि हम मास्टर पर एक और कमिट करते हैं और हम प्राप्त करते हैं:

   o---X---b1'---b3'---Y   <-- master
    \
     b1---b2---b3---b4   <-- b

यदि अब हम शाखा बी को मास्टर में विलय करेंगे:

$ git merge b

हमें निम्नलिखित मिलेगा:

   o---X---b1'---b3'---Y--- M  <-- master
     \                     /
      b1----b2----b3----b4   <-- b

इसका मतलब है कि बी 1 और बी 3 द्वारा पेश किए गए परिवर्तन इतिहास में दो बार दिखाई देंगे। इस बात से बचने के लिए कि हम मर्ज के बजाय पुन: उत्पन्न कर सकते हैं:

$ git rebase master b

जो उपज देगा:

   o---X---b1'---b3'---Y   <-- master
                        \
                         b2'---b4'   <-- b

आखिरकार:

$ git checkout master
$ git merge b

हमें देता है:

   o---X---b1'---b3'---Y---b2'---b4'   <-- master, b

EDIT सुधार डेविड लेमन की टिप्पणी से माना जाता है


1
पुनर्जन्म के बारे में महान संकेत! यह सभी चेरी-उठाया स्वचालित रूप से 'स्किप' करेगा।
iTake

2
ईमानदारी से, यह सच होने के लिए बहुत अच्छा लगता है, मुझे इसे अपनी आंखों से देखना होगा। इसके अलावा रिबास कमिट्स को संशोधित करता है, आपकी अंतिम समयरेखा होनी चाहिए---Y---b2'---b4'
डेविड लेमन

अच्छी तरह से काम। बहुत उपयोगी है अगर आप इतिहास में दो बार चेरी-उठाया जाना नहीं चाहते हैं।
user2350644

1
क्या यह ध्यान नहीं दिया जाना चाहिए कि जब रिबास सुंदर होता है, तो इसका उपयोग करने के साथ खतरा यह है कि पुरानी बी से बनाई गई कोई कांटे या शाखाएं सिंक से बाहर हो जाएंगी, और उपयोगकर्ताओं को गिट रीसेट और भार जैसे सामान का सहारा लेना पड़ सकता है। धक्का-मुक्की?
जेएचएच

1
@ जेएचएच यही कारण है कि हम यहां स्थानीय शाखा को फिर से रद्द कर देते हैं
एपिसोड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.