2016-05-15 7 views
5

मैं गिट चेरी पिक का उपयोग करने के तरीके सीखने की कोशिश कर रहा हूं, मैंने मैनुअल पेज पढ़े हैं gitgit cherry-pick --help कर रिटर्न देता है लेकिन यह मदद नहीं करता है। मैं नीचे की समस्या का प्रयास और व्याख्या करूंगा। मेरे पास दो शाखाएं master और other हैं।गिट चेरी-पिक विलय के दौरान संघर्ष विलय का कारण बनता है

शाखा master द हिस्ट्री प्रतिबद्ध पर

0x2 Second commit from master branch 
0x1 Initial commit 

और भंडार है कि मैं पर नज़र रखने हूँ readme में केवल फाइल है निम्नलिखित सामग्री

Some text 

शाखा other पर है प्रतिबद्धता इतिहास

012 है
0x5 CHECKPOINT, going to cherry-pick onto master 
0x4 second commit from branch other 
0x3 first commit from other branch: 
0x2 Second commit from master branch 
0x1 Initial commit 

और readme फ़ाइल की सामग्री

Some text. 

Adding some text from other branch. Adding some more text. 

Going to cherry-pick this commit. 

कार्यशील निर्देशिका कोई ट्रैक न किए गए परिवर्तनों के साथ दोनों शाखाओं पर साफ है कर रहे हैं। इस बिंदु से जब मैं मास्टर शाखा में स्विच करता हूं और git merge other के साथ विलय करता हूं तो विलय विलय विवादों के साथ शानदार ढंग से होता है। लेकिन जब मैं git cherry-pick 0x5 कोशिश वहाँ किसी मर्ज विरोध हो, तो मैं से git

error: could not apply 0x5... CHECKPOINT, going to cherry-pick onto master 
hint: after resolving the conflicts, mark the corrected paths 
hint: with 'git add <paths>' or 'git rm <paths>' 
hint: and commit the result with 'git commit' 

निम्नलिखित उत्पादन और readme फ़ाइल निम्न सामग्री

<<<<<<< HEAD 
Some text 
======= 
Some text. 

Adding some text from other branch. Adding some more text. 

Going to cherry-pick this commit. 
>>>>>>> 0x5... CHECKPOINT, going to cherry-pick onto master 

क्यों इस मर्ज संघर्ष है मिल सकता है? मैं समझने की कोशिश कर रहा हूं कि ऐसा क्यों होता है। cherry-pick आईएनजी cherry-pick अपने आप को संपादित करने वाले सभी संपादनों को बनाने की कोशिश करने के समान नहीं होना चाहिए और फिर उस परिवर्तन को शाखा (master इस मामले में) में बदलना चाहिए?

साथ ही git में विलय विवाद होने पर भी? मुझे अजीब समय पर उन्हें लग रहा है। क्या यह कार्यान्वयन निर्भर है (उदाहरण के लिए मर्ज करने के लिए उपयोग किए गए एल्गोरिदम पर निर्भर)?

धन्यवाद!

उत्तर

1

यदि आप merge कहते हैं, तो सभी तीन (3-5) कार्य विलय हो जाते हैं। यदि आप cherry-pick केवल अंतिम का उपयोग किया जाता है। जिन फाइलों में यह चिंताएं हैं, उनमें पहले से ही 3 और/या 4 में परिवर्तन हो सकते हैं, इसलिए प्रारंभिक चरण अपेक्षित मिलान से मेल नहीं खाता है।

यह देखने के लिए संघर्ष की जांच करें कि यह मर्ज टूल के साथ क्यों होता है।

उदाहरण के लिए यह एक संघर्ष का कारण होगा:

Original 
Original 
Original 
Commit3 
Original 
Commit5 
Original 

यहाँ Git के अंतर इंजन है कि आप से वादा 3. चेरी चुन सकते हैं जहाँ नहीं करता है एक लाइन सहित एक लाइन है कि कुछ पंक्तियां से पहले किया जाता है बदल गया है, दिखा देंगे ' टी मूल में उस रेखा को देखते हुए संघर्ष चिल्लाएगा और आपको इसे संभालने के लिए कहेंगे। प्रति विरोधाभासी संपादन नहीं है (उदाहरण के लिए एक ही पंक्ति संपादित की गई थी), गिट बस यह सुनिश्चित नहीं है कि संपादित भाग कहां रखा जाए।

बेशक आप फ़ाइलों को मैन्युअल रूप से संपादित कर सकते हैं हालांकि आप चाहते हैं।केवल विलय शाखाओं में समस्याएं और संघर्ष होंगे और सभी संघर्षों का अर्थ यह नहीं है कि "आप यह नहीं कर सकते", उनका मतलब है "मुझे नहीं पता कि वास्तव में क्या करना है, आप इसे स्वयं संभालते हैं।"

+1

लेकिन अगर मैं आगे बढ़ता हूं और मैन्युअल रूप से बदलाव करता हूं जो चेरी-पिक के माध्यम से किए जाते हैं तो ऐसा कोई मुद्दा नहीं है, तो जब मैं चेरी-पिक लेता हूं तो फिर कोई समस्या क्यों होती है? दोनों दोनों अर्थात् समान नहीं होना चाहिए? – Curious

+1

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

+0

मैंने आपके उत्तर को ऊपर उठाया लेकिन मुझे अभी भी इसे समझने में कुछ परेशानी हो रही है। लेकिन फिर जब मैं विलय हुआ तो कोई विलय संघर्ष क्यों नहीं हुआ? मैंने फ़ाइल को 'अन्य' शाखा में सभी कामों में अंत में संपादित किया है, इसलिए वहां एक मर्ज भी होना चाहिए था? – Curious

3

मैं सिर्फ उस परिदृश्य परीक्षण किया है, पढ़ने के बाद:

तो पहली पंक्ति के लिए संशोधन (Some text के बजाय Some text.) तुरंत किया गया था 0x2 के बाद, 0x3 में, git cherry-pick 0x3 बिना किसी संघर्ष के काम करता है।

लेकिन यदि वही परिवर्तन किया जाता है तो कुछ बाद में काम करता है, git cherry-pick 0x2 की सामग्री के साथ संगत पैच उत्पन्न नहीं करेगा।

यहां "सामान्य पूर्वज" की कोई धारणा नहीं है (as incorrectly stated here): केवल "पैच" का।

एक git cherry-pick, भले ही यह विलय रणनीतियों का उपयोग करता है, नहीं एक git merge है।

  • एक git merge एक आम पूर्वज के लिए दिखेगा (0x5 के प्रतिबद्ध के इतिहास में वापस जा रहा, पता लगाने के लिए एक आम 0x2 के साथ प्रतिबद्ध: यहाँ 0x2 ही)
  • एक git cherry-pick केवल एक एकीकृत करके एक पैच बनाता है दो प्रतिबद्धताओं के बीच भिन्नता (डिफ़ॉल्ट रूप से, आपके द्वारा उल्लिखित प्रतिबद्धता और उसके तत्काल माता-पिता 0x4)

बिंदु यह है कि पैच 0x2 के शीर्ष पर लागू नहीं किया जा सकेगा।

अपने लिए प्रयास करें: git cherry-pick 0x5git diff -p 0x4..0x5 करने जैसा है।
आप उस पैच लाइनों में देखेंगे जो 0x2 का हिस्सा नहीं है, और 0x3 या 0x4 से आने वाले परिवर्तनों को प्रतिबिंबित करता है।

इस तरह के पैच को 0x2 पर लागू नहीं किया जा सकता है, क्योंकि यह ऐसी सामग्री पर आधारित है जो 0x2 के लिए मौजूद नहीं है।

मैंने एक टेस्ट रेपो बनाया है जिसमें मैंने मास्टर दो संशोधनों से बनाया है।

  • एक दूसरे पहली पंक्ति को संशोधित करने, अन्य शाखा से कुछ पाठ (पहली पंक्ति के लिए कोई संशोधन)
  • जोड़ा जा रहा है तो फिर।
यहाँ

मेरी पैच कैसा दिखाई देता है:

C:\Users\vonc\prog\git\tests\cp>git diff -p dev~..dev 
diff --git a/f b/f 
index 2b6dd7b..1c4bb79 100644 
--- a/f 
+++ b/f 
@@ -1,4 +1,4 @@ 
-"Some text" 
+"Some text."^M 

Adding some text from other branch. Adding some more text. 

मैं, लागू नहीं कर सकते (चेरी ले) कि 0x2 पर प्रतिबद्ध के रूप में 0x2 कोई लाइन "Adding some text from other branch" अभी बाकी है। इसमें केवल एक पंक्ति "Some text" है।

यही कारण है कि गिट एक संघर्ष की रिपोर्ट करता है: सामग्री अलग हो गई है, और उस पैच को "Adding some text from other branch" सहित फ़ाइल के शीर्ष पर पंक्ति 1 को बदलना है, जो 0x2 नहीं है।

यह git merge से बिल्कुल अलग है, क्योंकि एक गिट विलय एक सामान्य पूर्वजों (यहां 0x2) की तलाश करेगा और किसी भी मुद्दे के बिना 0x2 पर 0x2 के बाद सभी संशोधनों की रिपोर्ट करेगा।

+1

मैं "सामान्य पूर्वजों" या "पैच" की धारणा से बहुत परिचित नहीं हूं, क्या आप उन्हें समझा सकते हैं? – Curious

+0

@ क्रिएटिव यह समझने में महत्वपूर्ण है कि क्यों गिट चेरी-पिक * गिट विलय नहीं है (भले ही यह विलय रणनीति का उपयोग करता हो)। एक आम पूर्वज का अर्थ है प्रतिबद्ध इतिहास में वापस जाना। एक पैच दो कामों के बीच एक एकीकृत अंतर है। वहां कोई इतिहास नहीं है। – VonC

+0

तो क्या चेरी-पिक हमेशा बड़ी परियोजनाओं में एक विलय संघर्ष उत्पन्न करेगा जिसमें हर एक फाइल बदल दी गई थी? – Curious

1

चलिए आपके मामले का एक छोटा प्रयोग करते हैं।

mkdir tmp 
cd tmp 
git init 
echo "root" >> hello 
git add hello 
git commit -m 'root commit' 
git branch exp 
#open the file hello and write 111 in the 2nd line 
git add hello 
git commit -m '111' 
#open the file hello and modify 111 to 112 in the 2nd line 
git add hello 
git commit -m '222' 
#now we have 3 commits in the master branch 
git log --oneline 
6b86a6d 112 
663a36b 111 
28b2e12 root commit 
git checkout exp 
#now we are in the exp branch, which has only 1 root commit. 
git log --oneline 
28b2e12 root commit 
#now we try to cherry pick 6b86a6d 
git cherry-pick 6b86ad6 
error: could not apply 6b86a6d... 112 
hint: after resolving the conflicts, mark the corrected paths 
hint: with 'git add <paths>' or 'git rm <paths>' 
hint: and commit the result with 'git commit' 
#a conflict occurs,why? 

2 मास्टर शाखा में प्रतिबद्ध modify the 2nd line, from empty to 111 3 मास्टर शाखा में प्रतिबद्ध करने के लिए बराबर है हम देख सकते हैं 3 2 पर निर्भर करता है modify the 2nd line, from 111 to 112

के बराबर है। यदि कोई 111 नहीं था, तो हम 111 से 112 अपडेट नहीं कर सके। जब हमने दूसरे के बिना तीसरे स्थान पर चेरी को चुना, तो कोई भी एक्सप शाखा के फाइल हैलो में कोई 111 नहीं पाया जा सकता था, जिससे संघर्ष हुआ।

हम चेरी उठाया 2 पहले, नमस्कार के 2 पंक्ति रिक्त से 111. करने के लिए और फिर हम करने के लिए 3, नमस्कार के 2 लाइन 111 से अपडेट किया जाएगा चेरी उठाया अगर 112

आइए अद्यतन किया जा चाहते हैं प्रयोग के साथ चलते हैं।

#abor the cherry-pick first 
git cherry-pick --abort 
#go back to the master branch 
git checkout master 
> world 
git add world 
git commit -m 'add new file world' 
git log --oneline 
1cf8f90 add new file world 
6b86a6d 112 
663a36b 111 
28b2e12 root commit 
#now we have 4 commits in the master branch 
#cherry pick the 4th commit into the exp branch 
git checkout exp 
git cherry-pick 1cf8f90 
[exp 79a34bb] add new file world 
Date: Sun May 15 20:55:39 2016 +0800 
1 file changed, 0 insertions(+), 0 deletions(-) 
create mode 100644 world 
#no error 

चौथी प्रतिबद्धता add a new file world के बराबर है। यह परिवर्तन दूसरे या तीसरे प्रतिबद्धता पर निर्भर नहीं है। इसे बिना किसी परेशानी के एक्सप ब्रांच में चेरी-चुना जा सकता है।

चलो संघर्ष परिदृश्य पर वापस जाएं।

#cherry pick the 3rd commit again 
git cherry-pick 6b86a6d 
error: could not apply 6b86a6d... 112 
hint: after resolving the conflicts, mark the corrected paths 
hint: with 'git add <paths>' or 'git rm <paths>' 
hint: and commit the result with 'git commit' 
git status 
On branch exp 
You are currently cherry-picking commit 6b86a6d. 
    (fix conflicts and run "git cherry-pick --continue") 
    (use "git cherry-pick --abort" to cancel the cherry-pick operation) 

Unmerged paths: 
    (use "git add <file>..." to mark resolution) 

    both modified: hello 
#we can see conflict ocurrs in the file hello. open hello with text editor 
hello world 
<<<<<<< HEAD 
======= 
112 
>>>>>>> 6b86a6d... 112 

< < < और >>> हिस्सा संघर्ष संदर्भ है। < < < और === हिस्सा वर्तमान शाखा में है, जो एक्स शाखा है। यह खाली है === और >>> भाग 6b86a6d प्रतिबद्धता में है। यह 112 है। चेरी-पिक प्रक्रिया यह तय नहीं कर सकती कि कौन सा हिस्सा लागू करना है, इसलिए हमें इसे अपने आप बनाना है। हम जोर देते हैं, तो यह रिक्त होना चाहिए, तो बस < < < की तर्ज, ===, >>> हटाने, और 112 हम 112 के बजाय चाहते हैं, तो बस की तर्ज हटाने < < <, ===,> >>। बेशक हम कुछ मामलों में < < <, ===, और >>> को छोड़कर सभी को रख सकते हैं। एक शब्द में, जो भी आप चाहते हैं उसे रखें और जो आवश्यक नहीं है उसे हटा दें। सुरषित और बहार। git add hello;git cherry-pick --continue तब सब कुछ किया जाता है। अधिक जानकारी के लिए कृपया git merge --help में 'कैसे कॉन्फ़्रेंस प्रस्तुत किए गए हैं' देखें।

एक और मामले में, यदि दो शाखाओं से दो कार्य करता है तो अलग-अलग सामग्रियों और गिट चेरी के साथ समान रेखा या रेखाएं अपडेट करें- दूसरी शाखा में एक प्रतिबद्धता चुनें, इससे भी संघर्ष होता है।

1

मैं अन्य तकनीकी की तुलना में कम तकनीकी, और अधिक "सामान्य ज्ञान" होने जा रहा हूं। (जो हमेशा करने के लिए सही काम नहीं है, लेकिन मुझे लगता है कि यह इस मामले में है।)

आप सोच रहे हैं, "यह स्पष्ट है कि मैं जो बदलाव चाहता हूं वह फ़ाइल के अंत तक एक रेखा जोड़ता है। क्या यह सिर्फ ऐसा नहीं कर सकता? "

गिट एक पैच लगा रहा है। पैच लगाने के लिए पैच को जाना चाहिए, यह पता लगाने की कोशिश करना शामिल है। इसमें अनुमानित लाइन नंबर को देखने और परिवर्तन के पहले और बाद में समान संदर्भ की n लाइनों की तलाश करना शामिल है। इस मामले में, बाद का संदर्भ फ़ाइल का अंत है। लेकिन पहले संदर्भ "अन्य शाखा से कुछ पाठ जोड़ना। कुछ और पाठ जोड़ना।" गंतव्य फ़ाइल में नहीं मिल सकता है।इसलिए गिट इस बात को झुकाता है, "मैं इस बदलाव के संदर्भ में पहले और बाद में कुछ मैच नहीं कर सकता, इसलिए मैं संघर्ष के निशान डालूंगा जहां परिवर्तन संभवतः जाना चाहिए, लेकिन अंतिम संकल्प करने के लिए इसे मानव बुद्धि में छोड़ दें।"

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

यदि यह ऐसा कुछ है जो आप अक्सर चलाएंगे, तो गिट आपको फाइलों के लिए कस्टम मर्ज हैंडलर लिखने की अनुमति देता है ताकि यदि आप अपेक्षित और स्वीकृत मर्ज पैटर्न और अपनी फ़ाइलों के सिंटैक्स के बारे में अधिक जानते हैं, तो आप इसे मर्ज हैंडलर में कोड कर सकते हैं ।

संबंधित मुद्दे