2008-10-15 17 views
23

मान लीजिए आपके पास:Git: स्क्वैश/Fixup पहले प्रतिबद्ध

A-B-C 

अब अपने निर्माण/परीक्षण विफल रहता है। ठीक ए में विलय कर दिया जाना चाहिए मेरे वर्तमान काम प्रवाह इस तरह है: एक में

$ git commit -m "fixA" 

A-B-C-fixA 

$ git rebase -i A~1 

और स्क्वैश fixA, परिणाम में:

A'-B-C 

वहाँ की तरह कुछ करने के लिए एक कमांड है:

A-B-C + (index with fix for A) 

$ git commit -supperdupper A 

परिणाम:

A'-B-C 
+1

क्यों ए को ठीक करने की अजीब आवश्यकता ए में विलय करनी है? –

+9

क्योंकि यह पहले स्थान पर ए में होना चाहिए था। – elmarco

+4

मैं वही काम करता हूं; मुझे यकीन नहीं है कि लोग क्यों सोचते हैं कि यह अजीब है। यदि आप छोटे, तार्किक रूप से समूहित टुकड़ों में काम करने की कोशिश कर रहे हैं, तो एक बार में कई अप्रकाशित कामों की तैयारी करना स्वाभाविक है। (आप शायद यह नहीं जानते कि आप वास्तव में ए के साथ क्या कर रहे हैं जब तक आप सी खत्म नहीं करते)। – andy

उत्तर

19

यदि आप पहले की तरह काम करने के लिए आसान समाधान ढूंढ रहे हैं, तो प्रश्न पढ़ें! यह सब बताता है। लेकिन चूंकि Elmarco एक चालाक रास्ता के लिए पूछ रहा था, ये हम चले:

Git 1.7.0 के रूप में, rebase के लिए एक --autosquash विकल्प है, जो करता है कि आप क्या चाहते है। चीजों को आसान बनाने के लिए --fixup और --squash विकल्पों के लिए commit भी विकल्प हैं। कुछ अलियासिंग के साथ आप शायद पूरी चीज को एक ही कमांड में भी प्राप्त कर सकते हैं।

मैं अधिकतम awesomeness के लिए नवीनतम Git के उन्नयन का सुझाव चाहते हैं: आप तो पिछले दो करता छुटकारा पाने के लिए आप को लागू करने की

git rebase --interactive <3rd last commit> 

फिर आप लेने के लिए की जरूरत है चाहते हैं

git/Documentation/RelNotes $ grep -i -A1 autosquash\\\|fixup * 
1.7.0.txt: * "git rebase -i" learned new action "fixup" that squashes the change 
1.7.0.txt- but does not affect existing log message. 
-- 
1.7.0.txt: * "git rebase -i" also learned --autosquash option that is useful 
1.7.0.txt: together with the new "fixup" action. 
1.7.0.txt- 
-- 
1.7.3.txt: * "git rebase -i" peeks into rebase.autosquash configuration and acts as 
1.7.3.txt: if you gave --autosquash from the command line. 
1.7.3.txt- 
-- 
1.7.4.txt: * "git commit" learned --fixup and --squash options to help later invocation 
1.7.4.txt- of the interactive rebase. 
-- 
1.7.4.txt: * "git rebase --autosquash" can use SHA-1 object names to name which 
1.7.4.txt: commit to fix up (e.g. "fixup! e83c5163"). 
1.7.4.txt- 
+1

अच्छा उदाहरण: http://technosorcery.net/blog/2010/02/07/fun-with-the-upcoming-1-7-release-of-git-rebase---interactive---autosquash/ –

+0

यह एक प्रासंगिक ब्लॉग भी है http://netsplit.com/2012/02/06/git-smash/ – elmarco

+0

एक ही कमांड में: http://stackoverflow.com/a/13671819/1456578 – Deiwin

0

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

इस तथ्य के कारण, गिट डेवलपर्स ने जानबूझकर ऐसा करना आसान नहीं किया है क्योंकि आपको ऐसा ऑपरेशन करने के परिणामों से अवगत होना चाहिए।

+4

मुझे परिणामों के बारे में पता है, मैं उन लोगों को साझा नहीं करना चाहता हूं। – elmarco

+2

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

+0

समस्या यहां दिखाया गया है - http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#problems-with-rewriting- इतिहास –

2

अंतिम प्रतिबद्धता और दूसरी-से-आखिरी प्रतिबद्धता को स्क्वैश करें। आप इतिहास के शीर्षतम प्रतिबद्धता को स्क्वैश नहीं कर सकते हैं।

1

I created some aliasesgit commit --fixup और git commit --squash आदेशों का उपयोग करना आसान बनाने के लिए गिट 1.7 में जोड़ा गया। अपने ~/.gitconfig करने के लिए इन करें:

[alias] 
    fixup = !sh -c 'REV=$(git rev-parse $1) && git commit --fixup [email protected] && git rebase -i --autosquash $REV^' - 
    squash = !sh -c 'REV=$(git rev-parse $1) && git commit --squash [email protected] && git rebase -i --autosquash $REV^' - 

उपयोग:

$ git commit -am 'bad commit' 
$ git commit -am 'good commit' 

$ git add .   # Stage changes to correct the bad commit 
$ git fixup HEAD^ # HEAD^ can be replaced by the SHA of the bad commit 

बुरा प्रतिबद्ध कई हो सकता है वापस करता है।

3

मेरे वर्तमान Git कार्य प्रवाह इतना --fixup/--squash गहन है, कि मैं एक नया git-fixup आदेश है कि कष्टप्रद बिट्स के सबसे स्वचालित रूप से संभालती लिखा है:

  • git fixup से पता चलता करता संशोधित कि नवीनतम के अंतर्गत वर्गीकृत फ़ाइलों को छूने कि एक ही फाइल को
  • git fixup -a उनकी संगत "जनक" के साथ --fixup परिवर्तन के रूप में उन सभी परिवर्तनों को प्रतिबद्ध करता
  • git fixup -r करता है एक स्वत: git rebase --autosquash सभी Fixup के लिए प्रतिबद्ध

परिवर्तन का एक बहुत ऐसी है कि सिर्फ तीन आदेशों ऊपर काम कर पाने के लिए पर्याप्त हैं कर रहे हैं, के लिए प्रतिबद्ध-आईडी का का कोई कॉपी-पेस्ट या git log के माध्यम से पढ़ने सही --fixup लक्ष्य खोजें।

स्रोत: https://github.com/ohmu/git-crust

0

मुझे लगता है कि समस्या के मूल कि Git (और संस्करण नियंत्रण आम तौर पर) बलों आप परिवर्तनों के दृश्यों के मामले में सोचने के लिए है, लेकिन एक changeset या सुविधा शाखा या जो भी आप एक फोन संबंधित परिवर्तनों का एकजुट समूह आम तौर पर तर्कसंगत अनुक्रमिक नहीं है। जिस क्रम में कोड लिखा गया था वह आकस्मिक है और आवश्यक रूप से उस क्रम से संबंधित नहीं है जिसमें इसे पढ़ा जाना चाहिए।

मेरे पास इसका कोई समाधान नहीं है, लेकिन मैंने पुनर्लेखन इतिहास की प्रक्रिया को स्वचालित करने में सहायता के लिए Perl script लिखा है। यह @MikaEloranta की पाइथन लिपि के समान है जिसे मैंने लिखा था जब मैंने इसे नहीं देखा था।

commit --fixup और rebase --autosquash बहुत अच्छे हैं, लेकिन वे पर्याप्त नहीं करते हैं। जब मेरे पास A-B-C का अनुक्रम होता है और मैं अपने काम करने वाले पेड़ में कुछ और बदलाव लिखता हूं जो कि उनमें से एक या अधिक मौजूदा कामों में से एक है, तो मुझे इतिहास को मैन्युअल रूप से देखना होगा, तय करना होगा कि कौन से परिवर्तन संबंधित हैं, उन्हें मंच बनाएं और बनाएं fixup! काम करता है। लेकिन गिट के पास पहले से ही पर्याप्त जानकारी तक पहुंच है जो मेरे लिए यह सब करने में सक्षम है।

प्रत्येक हंक के लिए git diff में स्क्रिप्ट के लिए प्रतिबद्ध है कि पिछले प्रासंगिक लाइनों को छुआ लगता है git blame का उपयोग करता है, और git commit --fixup कॉल उचित fixup! प्रतिबद्ध लिखने के लिए अनिवार्य रूप से एक ही बात मैं मैन्युअल रूप से पहले कर रहा था कर।

यदि स्क्रिप्ट एक एकल, स्पष्ट प्रतिबद्धता के लिए एक हंक को हल नहीं कर सकती है, तो यह एक असफल हंक के रूप में इसकी रिपोर्ट करेगा और आपको उस के लिए मैन्युअल दृष्टिकोण पर वापस आना होगा। यदि आपने दो अलग-अलग कामों में दो बार एक पंक्ति बदल दी है, तो स्क्रिप्ट उन पंक्तियों में से किसी एक बदलाव को हल करेगी जो कि हाल ही में सही रिज़ॉल्यूशन नहीं है। आईएमएचओ एक "सामान्य रूप" फीचर शाखा में आपको दो अलग-अलग कामों में दो बार लाइन नहीं बदलनी चाहिए, प्रत्येक प्रतिबद्धता समीक्षाकर्ताओं की सहायता के लिए लाइनों के अंतिम संस्करण को प्रस्तुत करना चाहिए। हालांकि, यह एक बगफिक्स शाखा में हो सकता है, उदाहरण के लिए लाइन foo(bar()); को प्रतिबद्ध ए (नाम foo से fox) को स्पर्श किया जा सकता है और बी (bar से baz का नाम बदलें) को स्पर्श किया जा सकता है।

यदि आपको स्क्रिप्ट उपयोगी लगता है, तो कृपया इसे बेहतर बनाने और इसे पुन: सक्रिय करने के लिए स्वतंत्र महसूस करें और शायद एक दिन हमें git में ऐसी सुविधा मिल जाएगी। मुझे एक ऐसा टूल देखना अच्छा लगेगा जो समझ सकता है कि एक इंटरेक्टिव रीबेस द्वारा पेश किए जाने पर विलय संघर्ष को कैसे हल किया जाना चाहिए।

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