"Git कमिट" के बजाय "git कमिट --amend" को पूर्ववत कैसे करें


1294

मैंने गलती से अपनी पिछली प्रतिबद्धता में संशोधन कर दिया। किसी विशेष फ़ाइल में किए गए परिवर्तनों के इतिहास को रखने के लिए कमिटमेंट अलग होना चाहिए था।

क्या पूर्ववत करने का कोई तरीका है? अगर मैं ऐसा कुछ करता हूं git reset --hard HEAD^, तो पहला कमिट भी पूर्ववत है।

(मैंने अभी तक किसी भी दूरस्थ निर्देशिका में धकेल नहीं दिया है)

जवाबों:


2287

आपको जो करने की ज़रूरत है वह वर्तमान विवरण के समान विवरणों के साथ एक नई प्रतिबद्ध बनाने के HEADलिए है, लेकिन माता-पिता के पिछले संस्करण के रूप में HEADgit reset --softब्रांच पॉइंटर को आगे बढ़ाएगा ताकि अगली कमेटी एक अलग कमेटी के शीर्ष पर हो, जहां से वर्तमान ब्रांच हेड अब है।

# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before 
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}

# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}

33
बहुत अच्छा, १। मैंने इसे git reflogसही संख्या खोजने के लिए दूसरे अंतिम संशोधन दृश्य के साथ भी किया {2}
JJD

178
बस स्पष्ट होने के लिए, पहला आदेश एक सच्चा "पूर्ववत" है। यह HEAD, वर्किंग डायरेक्टरी (अपरिवर्तित), और इंडेक्स स्टेट को पहले बनाता है git commit --amend। दूसरा एक नया कमिट में "रीडो" है। ये किसी भी काम के लिए git commit, न कि सिर्फ --amend
cdunn2001 21

60
इसलिए यदि आपने एक नए प्रतिबद्ध संदेश के साथ संशोधन नहीं किया है जिसे आपको निस्तारण करने की आवश्यकता है, तो दूसरा भाग नियमित रूप से हो सकता है git commit
मैट मोंटाग

18
किसी कारण के लिए, मैं एक त्रुटि जब चल रही थी git reset --soft HEAD@{1}: fatal: ambiguous argument 'HEAD@1': unknown revision or path not in the working tree. Use '--' to separate paths from revisions। जब मैंने HEAD@{1}समतुल्य प्रतिबद्ध हैश में दिखाया git reflog(धन्यवाद JJD!), तो इस उत्तर ने आश्चर्यजनक रूप से काम किया!
टिम कैमर

20
@TimArnold आपके शेल के आधार पर, आपको सिंगल या डबल कोट्स लगाने की आवश्यकता हो सकती है HEAD@{1}। यदि मैं echo HEAD@{1}उदाहरण के लिए tcsh में चलता हूं , तो आउटपुट HEAD@1इसलिए है क्योंकि ब्रेस की व्याख्या tcsh द्वारा की गई थी। यदि मैं एकल उद्धरण का उपयोग करता हूं, तो ब्रेस संरक्षित हैं।
केल्विन

136

रेफ-लॉग का उपयोग करें :

git branch fixing-things HEAD@{1}
git reset fixing-things

आपको तब अपने सभी पूर्व संशोधित परिवर्तनों को केवल अपनी कार्य प्रतिलिपि में होना चाहिए और फिर से प्रतिबद्ध हो सकता है

पिछली सूचक प्रकारों की पूरी सूची देखने के लिए git reflog


7
यह सूचकांक को भी मिटा देता है - अभी भी उपयोगी है, लेकिन एक सरल "पूर्ववत" से परे है।
cdunn2001 21

3
वहाँ के बीच कोई अंतर है HEAD@{1}और HEAD~1?
नेउम्यूज़िक

15
@neaumusic: हाँ! HEAD~1के रूप में बिल्कुल वैसा ही है HEAD^और वर्तमान प्रतिबद्ध के माता-पिता की पहचान करता है । HEAD@{1}दूसरी ओर, उस प्रतिबद्धता को संदर्भित करता है, जिसे HEAD ने इस एक के समक्ष इंगित किया था, अर्थात जब आप एक अलग शाखा की जांच करते हैं या किसी संशोधन में संशोधन करते हैं, तो उनका अर्थ अलग होता है।
knittl

@knittl आह कोई आश्चर्य नहीं कि मुझे नहीं लगता कि यह पहले संभव था, धन्यवाद फिर से, अच्छी जानकारी
neaumusic

9
मुट्ठी कदम बेमानी है। सरल git reset HEAD@{1}पर्याप्त है।
dwelle

79

इसके द्वारा संशोधित संशोधन खोजें:

git log --reflog

नोट: आप --patchस्पष्टता के लिए कमिट्स के शरीर को देखने के लिए जोड़ सकते हैं । के रूप में ही git reflog

फिर अपने HEAD को उस बिंदु पर किसी भी पिछली कमेटी में रीसेट कर दें जो इसके द्वारा ठीक था:

git reset SHA1 --hard

नोट: SHA1 को अपने वास्तविक कमिट हैश से बदलें । यह भी ध्यान दें कि यह आदेश किसी भी परिवर्तन को खो देगा , इसलिए आप पहले उन्हें रोक सकते हैं। वैकल्पिक रूप से, नवीनतम परिवर्तनों को बनाए रखने के लिए उपयोग करें--soft और फिर उन्हें प्रतिबद्ध करें।

फिर चेरी को उस अन्य वस्तु के लिए चुनें, जिसकी आपको शीर्ष पर आवश्यकता है:

git cherry-pick SHA1

26
यदि आप करते हैं git reset SHA1 --soft, तो आप नवीनतम परिवर्तनों को बनाए रख सकते हैं और फिर उन्हें प्रतिबद्ध कर सकते हैं।
प्रवर

24

आप मैनुअल से हमेशा एक कमिट विभाजित कर सकते हैं

  • Git rebase -i प्रतिबद्ध ^ के साथ एक इंटरेक्टिव रिबास शुरू करें, जहां कमिट वह है जिसे आप विभाजित करना चाहते हैं। वास्तव में, कोई भी कमिट रेंज तब तक करेगी, जब तक उसमें वह कमिटमेंट शामिल है।
  • उस कमिट को चिह्नित करें जिसे आप "एडिट" क्रिया से विभाजित करना चाहते हैं।
  • जब यह उस प्रतिबद्धता को संपादित करने की बात आती है, तो जीआईटी रीसेट HEAD ^ निष्पादित करें। इसका प्रभाव यह है कि HEAD एक के बाद एक रिवाइंड होता है और इंडेक्स सूट करता है। हालांकि, काम करने वाला पेड़ वही रहता है।
  • अब उस इंडेक्स में बदलाव करें जिसे आप पहले कमिट में रखना चाहते हैं। आप ऐसा करने के लिए git ऐड (संभवतः अंतःक्रियात्मक रूप से) या git-gui (या दोनों) का उपयोग कर सकते हैं।
  • जो भी प्रतिबद्ध संदेश है, उसके साथ अब-वर्तमान सूचकांक को प्रतिबद्ध करें।
  • आखिरी दो चरणों को दोहराएं जब तक कि आपका काम करने वाला पेड़ साफ न हो।
  • गिट रिबेस - कॉन्टिन्यू के साथ रिबेस को जारी रखें।

26
रास्ता बहुत जटिल है। git reflogआप सभी की जरूरत है
knittl

2
बहुत सारे कदम हाँ, लेकिन प्रत्येक चरण सरल और आसान है। इसने मेरे लिए काम किया और मुझे वोट मिला।
ओजबंडिट

5
इसके अतिरिक्त, यह उत्तर आपको उन परिवर्तनों को चुनिंदा रूप से लेने की अनुमति देता है जिन्हें आपने गलती से 'संशोधित' कर दिया था, जो git रीसेट करने के लिए कुछ अतिरिक्त मूल्य प्रदान करता है --soft HEAD @ {1} दृष्टिकोण (जिसने मेरी समस्या BTW हल कर दी)
Wiebe Gijsma

2
आप चुनिंदा तरीके से भी रिफ्लोग विधि से बदलाव कर सकते हैं। git resetइसके बजाय बस करो git reset --soft, फिर करो git add --patch
geekofalltrades

1
यह अभी भी इतिहास को फिर से लिखता है और इसके लिए एक बल पुश की आवश्यकता होती है। आपकी स्थिति पर निर्भर करता है कि कोई समस्या हो सकती है या नहीं।
पजन

20

संभवतः ध्यान देने योग्य है कि यदि आप अभी भी प्रतिबद्ध संदेश के साथ अपने संपादक में हैं, तो आप प्रतिबद्ध संदेश को हटा सकते हैं और यह git commit --amendकमांड को रद्द कर देगा ।


यही तो है वो।
atilkan

मेरा बच गया लेकिन ^ ^
इंजीनियर

14

शायद git reflogसंशोधन से पहले और संशोधन के बाद दो प्रतिबद्ध प्राप्त करने के लिए उपयोग कर सकते हैं ।

फिर git diff before_commit_id after_commit_id > d.diffसंशोधन से पहले और संशोधन के बाद के बीच अंतर करने के लिए उपयोग करें।

अगला उपयोग git checkout before_commit_idकरने से पहले कमिट करने के लिए

और git apply d.diffआपके द्वारा किए गए वास्तविक परिवर्तन को लागू करने के लिए अंतिम उपयोग ।

यह मेरी समस्या का हल करता है।


11

यदि आपने कमिट को रिमोट पर धकेल दिया है और फिर उस कमिटमेंट में गलत तरीके से बदलाव किया गया है तो यह आपकी समस्या को ठीक कर देगा। git logप्रतिबद्ध से पहले SHA को खोजने के लिए जारी करें। (यह माना जाता है कि रिमोट का नाम उत्पत्ति है)। अब उस SHA का उपयोग करके ये कमांड जारी करें।

git reset --soft <SHA BEFORE THE AMMEND>
#you now see all the changes in the commit and the amend undone

#save ALL the changes to the stash
git stash

git pull origin <your-branch> --ff-only
#if you issue git log you can see that you have the commit you didn't want to amend

git stash pop
#git status reveals only the changes you incorrectly amended

#now you can create your new unamended commit

3
यह अधिक सामान्य प्रश्न का एक विशेष मामला है, लेकिन इसने मेरी तत्काल आवश्यकता को ठीक से कवर किया है।
dmckee --- पूर्व-संचालक

8

आप अपने को पूर्ववत करने के लिए नीचे कर सकते हैं git commit —amend

  1. git reset --soft HEAD^
  2. git checkout files_from_old_commit_on_branch
  3. git pull origin your_branch_name

====================================

अब आपके परिवर्तन पूर्व की तरह हैं। तो आप के लिए पूर्ववत के साथ किया जाता हैgit commit —amend

अब आप कर सकते हैं git push origin <your_branch_name>, शाखा को धक्का देने के लिए।


3

इसके लगभग 9 साल देर से लेकिन इस भिन्नता को एक ही चीज़ को पूरा करते हुए नहीं देखा गया (यह इनमें से कुछ का संयोजन है, शीर्ष उत्तर के समान है ( https://stackoverflow.com/a/1459264/4642530 ) ।

शाखा पर सभी अलग किए गए सिर खोजें

git reflog show origin/BRANCH_NAME --date=relative

फिर SHA1 हैश का पता लगाएं

पुराने SHA1 पर रीसेट करें

git reset --hard SHA1

फिर उसे पीछे की ओर धकेलें।

git push origin BRANCH_NAME

किया हुआ।

यह आपको पूरी तरह से पुरानी प्रतिबद्धता पर वापस लौटा देगा।

(पूर्व अधिलेखित कमिटेड हेड की तारीख सहित)


हां, लेकिन मैं आमतौर पर --softअपने परिवर्तनों को बनाए रखने के लिए रीसेट करना चाहता हूं। मैं बस इसे अलग से प्रतिबद्ध चाहता हूं
जुआन मेंडेस

2
  1. अंतिम प्रतिबद्ध के साथ अस्थायी शाखा के लिए चेकआउट

    git branch temp HEAD@{1}

  2. अंतिम प्रतिबद्ध रीसेट करें

    git reset temp

  3. अब, आपके पास अपनी पिछली कमिट के साथ-साथ सभी फाइलें होंगी। सभी फाइलों की स्थिति की जाँच करें।

    git status

  4. अपनी कमिट फ़ाइलों को git स्टेज से रीसेट करें।

    git reset myfile1.js (जल्द ही)

  5. इस कमिट को रिटेट करें

    git commit -C HEAD@{1}

  6. अपनी फ़ाइलों को नई कमिट में जोड़ें और कमिट करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.