आप स्क्वैश को git फॉर्मेट-पैच के साथ एक पैच में कैसे करते हैं?


163

मुझे एक शाखा पर आठ कमिट्स मिले हैं, जिन्हें मैं कुछ ऐसे लोगों को ईमेल करना चाहूंगा जो अभी तक प्रबुद्ध नहीं हैं। अब तक, मैं जो कुछ भी करता हूं वह मुझे 8 पैच फाइलें देता है, या मुझे शाखा इतिहास में हर प्रतिबद्ध के लिए पैच फाइलें देना शुरू करता है, समय की शुरुआत के बाद से। मैंने कमिट स्क्वैश करने के लिए git rebase --interactive का उपयोग किया, लेकिन अब मैं जो कुछ भी कोशिश करता हूं वह मुझे समय की शुरुआत से पैच के zillions देता है। मैं क्या गलत कर रहा हूं?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master

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

4
मैं Rob Di Marco द्वारा सुझाए गए git diff का उपयोग करूंगा। लेकिन मैंने दो सप्ताह के लिए काम बंद कर दिया है, कल रात मेरी दूसरी बच्ची के जन्म का गवाह है, इसलिए इसे इस्तेमाल करने से पहले थोड़ी देर हो जाएगी! :)
स्किप्पॉपी

2
मैं
ssquash

1
एक रेव-रेंज निर्दिष्ट करने के लिए मास्टर की कोशिश करें।
कोनराड क्लेन

जवाबों:


186

मैं इस तरह से एक भगोड़ा शाखा पर ऐसा करने की सलाह दूंगा। यदि आपके कमिट "न्यूलाइन्स" शाखा में हैं और आपने पहले ही अपनी "मास्टर" शाखा में वापस आ गए हैं, तो यह ट्रिक करना चाहिए:

[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"

[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
 test.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch

उम्मीद है की यह मदद करेगा!


2
यह वह है जो मैं तब उपयोग करता हूं जब मैं इतिहास को स्थानीय रूप से रखना चाहता हूं (यदि मुझे पैच को संपादित करने की आवश्यकता है)। अन्यथा मैं सिर्फ रिबास-आई का उपयोग करता हूं और कमिट स्क्वैश करता हूं।
sebnow

5
मेरे लिए, इसने और अधिक विश्वसनीय के साथ काम किया git comit -m "My squashed commits"अन्यथा यह अन्य अनुपयोगी फ़ाइलों को जोड़ देगा
सेबस्टियन

Additonally, आप मास्टर के बजाय एक विशिष्ट कमिट पर जा सकते हैं और ऐसा करने के लिए प्रतिबद्ध से एक पैच बनाने के लिए कर सकते हैं:git checkout 775ec2a && git checkout -b patch && git merge --squash branchname
Berry M.

131

पॉट में एक और समाधान जोड़ने के लिए: यदि आप इसके बजाय इसका उपयोग करते हैं:

git format-patch master --stdout > my_new_patch.diff

तब यह अभी भी 8 पैच होगा ... लेकिन वे सभी एक ही पैचफ़िल में होंगे और एक के साथ एक के रूप में लागू होंगे:

git am < my_new_patch.diff

13
मुझे यह समाधान पसंद है। यह ध्यान देने योग्य है कि यह कभी-कभी @ अदम अलेक्जेंडर द्वारा वर्णित विधि की तुलना में बहुत बड़ा पैच बना सकता है। ऐसा इसलिए है क्योंकि कुछ फाइलों को कमिट के माध्यम से एक से अधिक बार संपादित किया जा सकता है। यह विधि प्रत्येक कमिट को अलग-अलग मानती है, भले ही कुछ फ़ाइल वापस कर दी गई हो। लेकिन ज्यादातर समय यह एक मुद्दा नहीं है।
गुमिक

1
यदि आप विलय से बचने की कोशिश कर रहे हैं तो यह विकल्प बहुत अच्छा है! (जैसे आप कुछ कमिट्स को छोड़ना चाहते हैं)। आप अभी भी कर सकते हैं git rebase -i ...और उन सभी को एक के नीचे स्क्वैश कर सकते हैं ।
जॉर्ज ऑर्पीनेल

21

मैं हमेशा आपके उदाहरण में git diff का उपयोग करता हूं, जैसे कुछ

git diff master > patch.txt

15
सिवाय इसके कि आप सभी प्रतिबद्ध संदेशों और मेटाडेटा को ढीला कर दें। गिट प्रारूप-पैच की सुंदरता यह है कि पैच के एक सेट से पूरी शाखा को फिर से बनाना संभव है।
14

क्रिएट-ब्रांच-एंड-स्क्वैश मेथड में सभी कमिट मैसेज को एक में मिलाने का लाभ है, लेकिन यदि आप अपना खुद का मैसेज लिखना चाहते हैं तो यह तरीका बहुत तेज़ है
woojoo666

वास्तव में, एक संयुक्त संदेश का उपयोग करके किया जा सकता है git log, उदाहरण के लिए मेरा उत्तर देखें
woojoo666

2
अच्छा विकल्प, लेकिन विचार करें कि 'git diff' में बाइनरी अंतर शामिल नहीं हो सकता है (शायद ऐसा करने का विकल्प है)।
सैंटियागो विल्लाफोर्ट

18

यदि आपका परिवर्तन मास्टर शाखा में है, तो यह अलेक्जेंडर के उत्तर का एक अनुकूलन है। यह निम्नलिखित करें:

  • हम चाहते हैं कि बिंदु से एक नई फेंकने वाली शाखा "tmpsquash" बनाता है (SHA कुंजी चल "git --log" के लिए या gitg के साथ देखें) उस कमिट का चयन करें जिसे आप tmpsquash शीर्ष होना चाहते हैं, जो बाद में मास्टर में होगा। स्क्वैश करता है)।
  • मास्टर से tmpsquash में परिवर्तन को जोड़ता है।
  • Tmpsquash में स्क्वैश किए गए परिवर्तनों को पूरा करता है।
  • स्क्वैश के साथ पैच बनाता है।
  • मास्टर शाखा में वापस जाता है

laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD

[snip, changed files]

11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example  (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example  (master)$

यदि आप अपने आप को दूरस्थ करने के लिए उन्हें धक्का नहीं दे रहे हैं, तो मास्टर में परिवर्तन करना एक विरोधी पैटर्न है। और अगर तुम, तुम शायद उनके लिए पैच फ़ाइलें उत्पन्न करने की आवश्यकता नहीं है।
ivan_pozdeev

18

जैसा कि आप पहले से ही जानते हैं, एक git format-patch -8 HEADवसीयत आपको आठ पैच देगी।

यदि आप चाहते हैं कि आपके 8 कमिट एक के रूप में दिखाई दें, और अपनी शाखा के इतिहास को फिर से लिखने का मन न करें ( o-o-X-A-B-C-D-E-F-G-H), तो आप कर सकते हैं:

git rebase -i
// squash A, B, C, D, E ,F, G into H

या, और यह एक बेहतर समाधान होगा, एक नई शाखा पर अपने 8 कमिट्स ( अपने 8 कमिट्स से Xपहले कमिट) से फिर से खेलना

git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD

इस तरह, आपके पास केवल "डिलीवरी" शाखा पर एक प्रतिबद्ध है, और यह आपके सभी अंतिम 8 का प्रतिनिधित्व करता है


git merge masterकेवल एक तेजी से आगे बढ़ता है और एक में स्क्वैश नहीं करता है। git merge --squash masterमंचित क्षेत्र में सभी कमिटेड और दृश्यमान प्राप्त करने के लिए बदलें । इस परिवर्तन के साथ आपका प्रवाह काम करेगा। (मैं git संस्करण 2.1.0 का उपयोग कर रहा हूं।)
Stunner

5

दो टैग के बीच प्रारूप-पैच:

git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>

5

सबसे आसान तरीका उपयोग करना है git diff, और git logयदि आप संयुक्त प्रतिबद्ध संदेश चाहते हैं कि स्क्वैश विधि आउटपुट करेगी तो इसमें जोड़ें । उदाहरण के लिए, प्रतिबद्ध abcdऔर के बीच पैच बनाने के लिए 1234:

git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt

तो जब पैच लागू:

git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt

गैर-पाठ फ़ाइलों, जैसे छवियों या वीडियो के साथ काम करते समय --binaryतर्क को मत भूलना git diff


0

एडम अलेक्जेंडर के जवाब पर आधारित:

git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.