2010-02-18 17 views
18

जब मैं git format-patch का उपयोग करता हूं, तो इसमें विलय शामिल नहीं लगता है। मैं विलय कैसे कर सकता हूं और फिर इसे पैच के सेट के रूप में किसी को ईमेल कर सकता हूं?गिट: मर्ज के लिए पैच कैसे बनाएं?

B 
/ \ 
A  M - D 
    \ /
    C 

अब मैं चेकआउट करने के लिए प्रयास करें:

git init 

echo "initial file" > test.txt 
git add test.txt 
git commit -m "Commit A" 

git checkout -b foo master 
echo "foo" > test.txt 
git commit -a -m "Commit B" 

git checkout -b bar master 
echo "bar" > test.txt 
git commit -a -m "Commit C" 

git merge foo 
echo "foobar" > test.txt 
git commit -a -m "Commit M" 

echo "2nd line" >> test.txt 
git commit -a -m "Commit D" 

यह निम्न पेड़ बनाता है:

उदाहरण के लिए, मान लें कि मैं दो शाखाओं विलय और प्रदर्शन एक और मर्ज के शीर्ष पर प्रतिबद्ध जाने प्रारंभिक प्रतिबद्धता और उपरोक्त परिवर्तनों को दोबारा दोहराएं:

git checkout -b replay master 
git format-patch --stdout master..bar | git am -3 

यह एक विलय confl पैदा करता है आईसीटी। इस परिदृश्य में, git format-patch master..bar केवल "कमिट एम" को छोड़कर 3 पैच उत्पन्न करता है। इससे मैं कैसे निपटूं?

-Geoffrey ली

उत्तर

5

आप पहले दो पैच की सामग्री की जांच यदि आप इस मुद्दे को देखेंगे: शाखा आप समय पर काम कर रहे थे (foo और बार) के नजरिए से

diff --git a/test.txt b/test.txt 
--- a/test.txt 
+++ b/test.txt 
@@ -1 +1 @@ 
-initial file 
+foo 

diff --git a/test.txt b/test.txt 
index 7c21ad4..5716ca5 100644 
--- a/test.txt 
+++ b/test.txt 
@@ -1 +1 @@ 
-initial file 
+bar 

इन प्रतिबद्ध के दोनों "प्रारंभिक फ़ाइल" रेखा को हटा दिया है और इसे पूरी तरह से किसी और चीज़ से बदल दिया है। AFAIK, इस तरह के संघर्ष से बचने का कोई तरीका नहीं है जब आप ओवरलैपिंग परिवर्तनों के साथ एक गैर-रैखिक प्रगति का पैच उत्पन्न करते हैं (आपकी शाखा इस मामले में बी और सी करता है)।

लोग आमतौर पर एक ज्ञात अच्छी पूर्व कार्य स्थिति से एक सुविधा या बग फिक्स जोड़ने के लिए पैच का उपयोग करते हैं - पैच प्रोटोकॉल बस गिट इतिहास जैसे मर्ज इतिहास को संभालने के लिए पर्याप्त परिष्कृत नहीं है। यदि आप चाहते हैं कि कोई आपके विलय को देखने के लिए है तो आपको शाखाओं के बीच धक्का/खींचने की आवश्यकता है जो वापस diff/पैच नहीं छोड़ती है।

+0

नकारात्मक साबित करना मुश्किल है लेकिन सीह की तरह, मैंने इस समस्या पर एक झटका लगा और मुझे लगता है कि आप सही हैं। – JasonSmith

+0

हां, मैं पैच फ़ाइलों के साथ मुद्दों को समझता हूं। मैं उम्मीद कर रहा था कि एक कामकाज होगा, क्योंकि कोई यह मान लेगा कि लिनक्स या गिट परियोजनाओं में इसी तरह की स्थितियों का सामना करना पड़ा है, और वे पूरी तरह से पुश/पुल के बजाय ई-मेल के माध्यम से पैच सबमिट करने पर भरोसा करते हैं। मैं गिट मेलिंग सूची पिंग करूँगा और देख सकता हूं कि उनके पास कोई अतिरिक्त प्रतिक्रिया है या नहीं। धन्यवाद। – geofflee

+0

यदि आप के बजाय ऊपर $ Git के साथ विलय --squash foo $ Git प्रतिबद्ध -एक -m मर्ज लाइन प्रतिस्थापित किया था कि "कमिट एम" अपने पैच सफाई से लागू किया गया होता ... – omnisis

8

ध्यान दें कि एक नंगे git log -p नहीं दिखाएगा मर्ज के लिए किसी भी पैच सामग्री के लिए प्रतिबद्ध "एम", लेकिन git log -p -c का उपयोग कर इसे बाहर मनाना है। हालांकि, git format-patch-c (या --combined, -cc) के अनुरूप किसी भी तर्क को स्वीकार नहीं करता है git log द्वारा स्वीकार किया गया है।

मैं भी स्टंप हो गया हूं।

+1

धन्यवाद, यह सही जवाब था जिसे मैं देख रहा था कि क्यों गिट लॉग -p विलय करने के लिए पैच नहीं दिखाता था। –

21

वहाँ एक समाधान का निर्माण अलग-अलग ला git format-patch करता है, लेकिन Fwiw, आप एक पैच युक्त प्रभावी मर्ज git am साथ प्रतिबद्ध, उपयुक्त/संगत फ़ॉर्मेट कर सकते हैं होने के लिए प्रतीत नहीं होता:

जाहिर है, Git Reference मार्गदर्शन प्रदान करता है पहले संकेत:

Git शो पैच प्रत्येक में पेश किया -p लॉग ऑन करने

[...] इसका मतलब है कि किसी भी प्रतिबद्ध के लिए आप प्राप्त कर सकते हैं पैच जो परियोजना से पेश किया गया है। आप या तो एक विशिष्ट प्रतिबद्धता SHA के साथ git show [SHA] चलाकर ऐसा कर सकते हैं, या आप git log -p चला सकते हैं, जो गिट को प्रत्येक प्रतिबद्धता के बाद पैच लगाने के लिए कहता है। [...]

अब, git-log के मैनुअल पृष्ठ दूसरा संकेत देता है:

git log -p -m --first-parent

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

कौन सा बदले में ठोस कदम में अर्थ है:

# Perform the merge: 
git checkout master 
git merge feature 
... resolve conflicts or whatever ... 
git commit 

# Format a patch: 
git log -p --reverse --pretty=email --stat -m --first-parent origin/master..HEAD > feature.patch 

और यह के रूप में लागू किया जा सकता इरादा:

git am feature.patch 

फिर, यह शामिल नहीं होंगे व्यक्ति करता है, लेकिन यह पैदा करता है एक मर्ज प्रतिबद्धता से git am संगत पैच।


बेशक

, अगर आप पहली जगह में एक git am संगत पैच की जरूरत नहीं है, तो यह तरीका आसान है:

git diff origin/master > feature.patch 

लेकिन मुझे लगता है कि आप पहले से ही के रूप में ज्यादा लगा, और अगर आप उतरा इस पृष्ठ पर, आप वास्तव में ऊपर वर्णित वर्कअराउंड/समाधान की खोज कर रहे हैं। ;)

+0

गिट diff [रिमोट शाखा का नाम] बहुत अच्छा काम करता है। –

+1

ग्रेट उत्तर, बहुत बहुत धन्यवाद! मुझे डर है कि यह अधूरा है, क्योंकि आपको भी आवश्यकता है - गिट लॉग में विपरीत, अन्यथा "git am feature.patch" काम नहीं करेगा। तो, इस तरह: गिट लॉग --reverse -p --pretty = ईमेल --stat -m - फर्स्ट-पैरेंट मूल/मास्टर..हेड> फीचर.patch –

+0

धन्यवाद @ डार्कोमोक्सिमोविक, तदनुसार समाधान अपडेट किया गया। '--reverse' पहले शामिल नहीं किया गया था, क्योंकि वर्णित प्रक्रिया में केवल एक ही प्रतिबद्धता शामिल थी। लेकिन तुम बिल्कुल सही हो! – sun

4

विस्तार sun के जवाब, मैं एक आदेश है कि क्या git format-patch के लिए इसी तरह के धब्बे का उत्पादन होता अगर यह हो सकता की एक श्रृंखला का उत्पादन कर सकते हैं, और आप git am को खिलाने के व्यक्ति के साथ करता है एक इतिहास का उत्पादन कर सकते हैं कि करने के लिए आया था:

git log -p --pretty=email --stat -m --first-parent --reverse origin/master..HEAD | \ 
csplit -b %04d.patch - '/^From [a-z0-9]\{40\} .*$/' '{*}' 
rm xx0000.patch 

पैच फिलिप डी Muyter के समाधान से कार्य करना xxLAST.patch

+0

आपके उत्तर के लिए धन्यवाद! यह बहुत अच्छा काम करता है! :) – mkdong

+0

यदि आप '-z' और' -f '' के साथ csplit को कॉल करते हैं, तो आपको पहले पैच को हटाने की आवश्यकता नहीं है और इसमें "xx" उपसर्ग नहीं होगा। "मैं वास्तव में उस गिट-प्रारूप की कामना करता हूं -पैच इस तरह कुछ करने के लिए एक एकीकृत विकल्प था ... – Compholio

0

करने के लिए xx0001.patch नाम दिया जाएगा मैं एक संस्करण है कि पैच Git प्रारूप-पैच के रूप में एक ही तरह से (जहाँ तक मैं बता सकता हूँ) प्रारूप बनाया है। बस प्रतिबद्ध के वांछित सीमा (जैसे origin..HEAD) तक की सीमा तय करने और जाना:

LIST=$(git log --oneline --first-parent --reverse ${RANGE}); 
I=0; 
IFS=$'\n'; 
for ITEM in ${LIST}; do 
    NNNN=$(printf "%04d\n" $I); 
    COMMIT=$(echo "${ITEM}" | sed 's|^\([^ ]*\) \(.*\)|\1|'); 
    TITLE=$(echo "${ITEM}" | sed 's|^\([^ ]*\) \(.*\)|\2|' | sed 's|[ -/~]|-|g' | sed 's|--*|-|g' | sed 's|^\(.\{52\}\).*|\1|'); 
    FILENAME="${NNNN}-${TITLE}.patch"; 
    echo "${FILENAME}"; 
    git log -p --pretty=email --stat -m --first-parent ${COMMIT}~1..${COMMIT} > ${FILENAME}; 
    I=$(($I+1)); 
done 

ध्यान दें कि अगर आप Git-quiltimport के साथ इस प्रयोग कर रहे हैं तो आप किसी भी खाली मर्ज करता है या आप करेंगे बाहर करने के लिए की आवश्यकता होगी त्रुटि प्राप्त करें "पैच खाली है। क्या यह गलत विभाजित था?"।

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