2009-11-12 23 views
49

मैं एक इंटरैक्टिव रिबेस के दौरान दो विलय प्रतिबद्धताओं को स्क्वैश करने का एक आसान समाधान चाहता था।गिट रिबेस इंटरैक्टिव: स्क्वैश विलय एक साथ काम करता है

मेरे भंडार लगता है:

X --- Y --------- M1 -------- M2 (my-feature) 
/    /  /
/    /  /
a --- b --- c --- d --- e --- f (stable) 

है कि, मैं, एक my-feature शाखा है, जो दो बार हाल ही में विलय कर दिया गया है से कोई वास्तविक के बीच में करता है। मैं नहीं है सिर्फ my-feature शाखा rebase करने के बाद से यह अपने आप में एक प्रकाशित शाखा है चाहता हूँ, मैं सिर्फ एक साथ छुटकारा पाने के लिए पिछले दो मर्ज में प्रतिबद्ध चाहते हैं (अभी तक उन प्रतिबद्ध प्रकाशित नहीं किया है)

X --- Y ---- M (my-feature) 
/  /
/  /
a --- ... -- f (stable) 

मैंने कोशिश की:

git rebase -p -i M1^ 

लेकिन मुझे मिल गया:

Refusing to squash a merge: M2 

क्या मैं अंत में किया है:

git checkout my-feature 
git reset --soft HEAD^ # remove the last commit (M2) but keep the changes in the index 
git commit -m toto  # redo the commit M2, this time it is not a merge commit 
git rebase -p -i M1^ # do the rebase and squash the last commit 
git diff M2 HEAD  # test the commits are the same 

अब, नए विलय प्रतिबद्धता को अब विलय प्रतिबद्धता नहीं माना जाता है (यह केवल पहले माता-पिता को रखा गया है)। तो:

git reset --soft HEAD^    # get ready to modify the commit 
git stash       # put away the index 
git merge -s ours --no-commit stable # regenerate merge information (the second parent) 
git stash apply      # get the index back with the real merge in it 
git commit -a      # commit your merge 
git diff M2 HEAD      # test that you have the same commit again 

लेकिन अगर मेरे पास बहुत से काम हैं तो यह जटिल हो सकता है, क्या आपके पास बेहतर समाधान है? धन्यवाद।

मिल्ड्रेड

+0

खैर, जब लागू होगी आप अपना दूसरा विलय करें, आप हमेशा प्रतिबद्धता बनाने से बचने के लिए '--squash' का उपयोग कर सकते हैं, और उसके बाद पिछले विलय को संशोधित करने के लिए 'git commit --amend' का उपयोग करें। – Mildred

+0

यह काम नहीं करेगा, यह – Mildred

उत्तर

8

अगर आप प्रकाशित नहीं किया है पिछले दो मर्ज करता है, तो आप एक रीसेट और एक साधारण मर्ज कर सकता है।

git reset --hard Y 
git merge stable 
+2

प्रतिबद्धता में आपके द्वारा विलय की गई शाखा के नए संस्करण को सहेज नहीं पाएगा, लेकिन विलय मुश्किल था, मैं जितना संभव हो उतना परिवर्तन विलय करना चाहता हूं। मैं संघर्षों को हल नहीं करना चाहता हूं जिन्हें मैंने पहले ही हल कर लिया है। – Mildred

+9

यदि आप विवादों को फिर से हल नहीं करना चाहते हैं, तो आपको गिट-रीरेयर का उपयोग करने की आवश्यकता है (और "इसका उपयोग करके" मेरा मतलब वास्तव में "इसे चालू करना" है क्योंकि गिट हैंडल स्वचालित रूप से समान संघर्षों को फिर से ठीक करने के बाद सक्षम)। –

47

यह एक पुराना विषय है, लेकिन मैं इसी तरह की जानकारी की तलाश करते समय बस इसे पार कर गया।

एक चाल Subtree octopus merge में वर्णित एक के समान इस प्रकार की समस्या के लिए एक बहुत अच्छा समाधान है:

git checkout my-feature 
git reset --soft Y 
git rev-parse f > .git/MERGE_HEAD 
git commit 

कि सूचकांक ले जाएगा के रूप में यह मेरी-सुविधा की नोक पर मौजूद है, और इसका इस्तेमाल करते हैं वाई के साथ एक नया प्रतिबद्धता बनाने के लिए, 'एफ' के साथ दूसरे माता-पिता के रूप में। नतीजा यह है कि आपने कभी एम 1 नहीं किया था, लेकिन सीधे एम 2 करने के लिए चला गया।

+0

ध्यान दें कि इस तरह के विलय के पास उपट्री या ऑक्टोपस विलय के साथ कुछ लेना देना नहीं है। जिस ब्लॉग से आप लिंक करते हैं, वह * एक सबट्री विलय * को जोड़ता है और एक ऑक्टोपस विलय को एक विलय प्रतिबद्धता में जोड़ता है (क्योंकि गिट दोनों सीधे एक ही विलय में विलय नहीं कर सकता)। – sleske

+0

इसका दोष यह है कि गिट उचित प्रतिबद्ध संदेश उत्पन्न करने में सक्षम नहीं होगा। मैंने पुराने विलय की गतिविधियों से संदेशों की प्रतिलिपि बनाई। अन्यथा एक अच्छा, आसान समाधान। –

+0

इतना ऊंचा! हमने अभी एक बहुत ही मुश्किल विलय किया है और मेरे सहयोगियों का दृष्टिकोण एक ही समय में प्रत्येक पेड़ से अपने पेड़ में विलय करना था। फिर स्क्वैशिंग आया और हमें यह समाधान मिल गया। यह एक शर्म की बात है कि आपको अपना खुद का प्रतिबद्ध संदेश लिखना होगा। – Sam

0

हाल ही में किसी भी गिट संस्करण के साथ मेरे लिए कोई भी विधि मेरे लिए काम नहीं करती है।

git reset --soft Y 
git reset --hard $(git commit-tree $(git write-tree) -p HEAD -p stable < commit_msg) 

आप फ़ाइल commit_msg पहले करने के लिए प्रतिबद्ध संदेश लिखने के लिए हालांकि होगा: मेरे मामले में निम्नलिखित चाल किया था।

5

मैं इस विषय पर आया था कि वह एक विलय प्रतिबद्धता को स्क्वैश करना चाहता है; तो मेरा जवाब मूल प्रश्न के लिए उपयोगी नहीं है।

   X 
       \ 
       \ 
a --- b --- c --- M1 (subtree merge) 

मैं क्या चाहता था एम 1 मर्ज और एक एकल के रूप में स्क्वैश सब कुछ rebase करने के लिए ख के शीर्ष पर प्रतिबद्ध था।

a --- b --- S (include the changes from c, X and M1) 

मैं विभिन्न संयोजनों के सभी प्रकार की कोशिश की लेकिन यह क्या काम किया है:

git checkout -b rebase b (checkout a working branch at point b) 
git merge --squash M1 

यह सूचकांक जहां वे प्रतिबद्ध किया जा सकता है में परिवर्तन Git प्रतिबद्ध

+1

इस मामले के लिए, आप 'गिट diff b> diff.patch' कर सकते हैं, फिर' गिट चेकआउट बी', 'cat diff.patch | पैच -पी 1' और फिर 'गिट प्रतिबद्ध'। यह काम करता है अगर * मर्ज * संकल्प शामिल हैं। मूल प्रश्न अलग है; लेकिन मुझे लगता है कि आप यहां मेरे जैसा ही खोज रहे थे। आप हाथ से पहले 'गिट लॉग' के साथ चेक-इन संदेश प्राप्त कर सकते हैं। –

+0

यदि आप अपने मास्टर की स्थिति चाहते हैं तो अतिरिक्त चरणों की आवश्यकता है: 'गिट चेकआउट मास्टर और गिट रीसेट - हार्ड बी एंड जी गिट रिबेस रीबेस'। यह सिर्फ खुद को reming है। आप "रिबेस" की तुलना में शाखा के लिए एक और नाम चुन सकते थे :) – eis

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