आप गिट इतिहास में एक विशिष्ट संशोधन कैसे निकालते हैं?


213

मान लीजिए कि आपका गिट इतिहास ऐसा है:

1 2 3 4 5

1-5 अलग-अलग संशोधन हैं। आपको 1, 2, 4 और 5 रखते हुए 3 को हटाने की आवश्यकता है। यह कैसे किया जा सकता है?

क्या एक कुशल विधि है जब हटाए जाने के बाद सैकड़ों संशोधन होते हैं?


यह प्रश्न अ-परिभाषित है। यह स्पष्ट रूप से नहीं कहा गया है कि लेखक 1-2- (3 + 4) -5 या 1-2-4-5 चाहता है
RandyTek

14
खैर 8 साल बाद, मैं आपको यह नहीं बता सकता कि मैं किस समस्या को हल करने की कोशिश कर रहा था। लेकिन समझ में हमेशा कुछ करने के बहुत सारे तरीके होते हैं, और ऐसे बहुत से जवाब होते हैं जो विभिन्न लोगों को पसंद आए हैं, इसलिए मुझे लगता है कि अस्पष्टता बहुत सारे लोगों को बहुत मुश्किल नहीं कर रही है
1800 जानकारी

1
git rebase --onto 2 3 HEADबहुत ज्यादा मतलब है 2 पर छूट, 3 और HEAD के बीच कमिट (HEAD वैकल्पिक है, या इस मामले में 5)
neaumusic

जवाबों:


76

संशोधन 3 और 4 को एक ही संशोधन में संयोजित करने के लिए, आप गिट रीबेस का उपयोग कर सकते हैं। यदि आप संशोधन 3 में बदलावों को दूर करना चाहते हैं, तो आपको इंटरैक्टिव रिबेस मोड में एडिट कमांड का उपयोग करना होगा। यदि आप परिवर्तनों को एकल संशोधन में जोड़ना चाहते हैं, तो स्क्वैश का उपयोग करें।

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

से Git प्रलेखन :

इसे सबसे पुरानी प्रतिबद्धताओं के साथ शुरू करें जिसे आप बनाए रखना चाहते हैं:

git rebase -i <after-this-commit>

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

डेडबॉडी चुनें
fa1afe1 उठाओ अगले प्रतिबद्ध की ऑनलाइन
...

ऑनेलाइन विवरण शुद्ध रूप से आपकी खुशी के लिए हैं; git-rebase उन्हें नहीं बल्कि कमिटेड नामों ("डेडबी" और "fa1afe1" इस उदाहरण में) पर दिखेगा, इसलिए नामों को हटाएं या संपादित न करें।

कमांड "पिक" को कमांड "एडिट" के साथ बदलकर, आप git-rebase को उस कमिट को लागू करने के बाद बंद करने के लिए कह सकते हैं, ताकि आप फाइलों को संपादित कर सकें और / या कमिट मैसेज को एडिट कर सकें, कमिट में संशोधन कर सकें और रिबासिंग जारी रख सकें।

यदि आप दो या अधिक कमिट्स को एक में बदलना चाहते हैं, तो दूसरी और बाद की कमिट के लिए कमांड "पिक" को "स्क्वैश" से बदलें। यदि कमिट्स में अलग-अलग लेखक होते हैं, तो यह पहली प्रतिबद्ध लेखक के लिए स्क्वास्ड कमिट का गुण होगा।


42
-1 प्रश्न अच्छी तरह से परिभाषित है लेकिन यह उत्तर इतना स्पष्ट नहीं है। लेखक यह नहीं कहता कि इसका सटीक हल क्या है।
हांग्जो लेवचुक

1
यह एक गलत लीड है। SPLITTING COMMITS सेक्शन सही नहीं है। आप मैनुअल में बहुत अधिक पढ़ना चाहते हैं - @Rares Vernica का उत्तर देखें।
अलेक्सांद्र लेवचुक

1
@AleksandrLevchuk प्रश्न को अच्छी तरह से परिभाषित नहीं किया गया है: यह इस तरह से स्पष्ट नहीं है कि प्रश्न में कहा गया है कि 3 में बदलाव को रखा जाना है या छोड़ दिया गया है। मैं इस बात से सहमत हूँ कि यदि परिवर्तनों को छोड़ दिया जाना है, तो अन्य उत्तर एक आसान तरीका प्रदान करते हैं। यदि परिवर्तन रखे जाने हैं, तथापि, यह एक विशुद्ध रूप से कॉस्मेटिक ऑपरेशन होगा। दोनों इतिहास को उन तरीकों से फिर से लिखते हैं जो खतरनाक हैं यदि दूसरों में त्रुटिपूर्ण इतिहास के आधार पर काम हो सकता है; अगर ऐसा है, तो कॉस्मेटिक क्लीनअप नहीं किया जाना चाहिए, और परिवर्तन हटाने को गिट रिवर्ट के माध्यम से बेहतर किया जाएगा।
थियोडोर मर्डॉक

124

प्रति इस टिप्पणी (और मैं जाँच की है कि यह सच है), rado का जवाब बहुत करीब है लेकिन पत्ते एक अलग सिर राज्य में git। इसके बजाय, उस शाखा से HEADनिकालने के लिए इसे निकालें और उपयोग करें <commit-id>जिस पर आप हैं:

git rebase --onto <commit-id>^ <commit-id>

1
अगर आप मुझे बता सकते हैं कि सिर्फ कमिट-आईडी के इतिहास से उस कमिट-आईडी को कैसे हटाया जाए, तो आप मेरे हीरो होंगे।
kayleeFrye_onDeck

क्या आप कृपया उस स्पष्टीकरण को शामिल कर सकते हैं जो उत्तर में जादू कमांड करता है? यानी प्रत्येक पैरामीटर क्या दर्शाता है?
अलेक्जेंड्राइड

यह कमाल है, लेकिन क्या होगा अगर मैं इतिहास में पहली बार कमिटमेंट निकालना चाहता हूं? (यही कारण है कि मैं यहाँ आया था: पी)
स्टर्लिंग कैमडेन

2
किसी कारण से, जब मैं इसे चलाता हूं तो कुछ भी नहीं होता है। हालांकि, यह काम ^करने के लिए बदल रहा है ~1
एंटीमनी

रास्ता देर से, लेकिन मैं जोड़ने जा रहा हूँ कि यदि आप मर्ज संघर्ष में भागते हैं, तो रिबास को निरस्त करें और फिर --strategy-option theirsअंत में इसे फिर से चलाएँ ।
LastStar007

122

गैर-अंतःक्रियात्मक रूप से विशिष्ट को हटाने का एक तरीका यहां है <commit-id>, केवल यह जानना कि <commit-id>आप किसको हटाना चाहते हैं:

git rebase --onto <commit-id>^ <commit-id> HEAD

2
मेरे लिए भी काम किया। Btw, ^ ऑपरेटर क्या करता है? क्या इसका मतलब निर्दिष्ट एक के बाद अगली प्रतिबद्ध है?
होपिया

3
@ हापिया का अर्थ है (पहले) निर्दिष्ट वचन के जनक। "गिट मदद संशोधन" देखें
एमिल स्टायरके

12
उनके जवाब में @ करीम की सिफारिश को छोड़ दें HEADताकि एक अलग सिर से बच सकें।
mklement0

1
यह पता लगाने की तुलना में बहुत आसान है कि कितने खोज करने के लिए वापस आते हैं।
दाना वुडमैन

1
यह कमाल है, लेकिन क्या होगा अगर मैं इतिहास में पहली बार कमिटमेंट निकालना चाहता हूं? (यही वजह है कि मैं यहां आया: पी)
स्टर्लिंग कैमडेन

76

जैसा कि गिट-रिबेस (1) से पहले उल्लेख किया गया है, आपका मित्र है। यह मानते हुए कि शाखाएँ आपकी masterशाखा में हैं, आप ऐसा करेंगे:

git rebase --onto master~3 master~2 master

इससे पहले:

1---2---3---4---5  master

उपरांत:

1---2---4'---5' master

Git-rebase (1) से:

छूट के साथ कई प्रकार के आवागमन भी हटाए जा सकते हैं। यदि हमारे पास निम्न स्थिति है:

E---F---G---H---I---J  topicA

उसके बाद कमान

git rebase --onto topicA~5 topicA~3 topicA

एफ और जी को हटाने का परिणाम होगा:

E---H'---I'---J'  topicA

यह उपयोगी है अगर एफ और जी किसी तरह से त्रुटिपूर्ण थे, या विषय का हिस्सा नहीं होना चाहिए। ध्यान दें कि - तर्क और पैरामीटर का तर्क किसी भी मान्य प्रतिबद्ध-ईश हो सकता है।


3
क्या यह नहीं होना चाहिए --onto master~3 master~1?
मथियास

3
यदि आप बस अंतिम प्रतिबद्ध को हटाना चाहते हैं, तो यह है - सेंटो मास्टर ~ 1 मास्टर
माइकहॉल

मैं इस विला को ले जाना चाहूंगा। लेकिन मुझे MERGE CONFLICTत्रुटि मिलती है । मैंने stackoverflow.com/questions/2938301/remove-specific-commit में उल्लेखित परिदृश्य का उपयोग किया है और उस उदाहरण में 2 वें प्रतिबद्ध को हटाने में असमर्थ हूं।
मान 81१

22

यदि आप सभी संशोधन 3 में किए गए बदलावों को दूर करना चाहते हैं, तो आप गिट रिवर्ट का उपयोग करना चाह सकते हैं।

Git रिवर्ट बस उन परिवर्तनों के साथ एक नया संशोधन बनाता है, जो आपके द्वारा परिवर्तित किए जा रहे संशोधन के सभी परिवर्तनों को पूर्ववत करता है।

इसका मतलब यह है, कि आप दोनों अवांछित प्रतिबद्धताओं के बारे में जानकारी बनाए रखते हैं, और उन परिवर्तनों को दूर करने वाले प्रतिबद्ध हैं।

यह संभवत: बहुत अधिक अनुकूल है यदि यह संभव है कि किसी ने आपके भंडार से इस बीच खींच लिया है, क्योंकि मूल रूप से केवल एक मानक प्रतिबद्ध है।


4
दुर्भाग्य से मेरे लिए एक अच्छा समाधान नहीं है क्योंकि किसी ने गलती से रेपो को 100MB बकवास कर दिया, आकार को उड़ाने और वेब इंटरफ़ेस को सुस्त बना दिया।
स्टीफन स्मिथ

18

अब तक के सभी जवाबों के पीछे चिंता की बात नहीं है:

क्या एक कुशल विधि है जब हटाए जाने के बाद सैकड़ों संशोधन होते हैं?

चरणों का पालन करें, लेकिन संदर्भ के लिए, आइए निम्नलिखित इतिहास को मानें:

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

सी : हटाने के लिए प्रतिबद्ध होने के बाद ही प्रतिबद्ध (साफ)

R : हटाने के लिए प्रतिबद्ध है

बी : हटाने के लिए प्रतिबद्ध होने से पहले प्रतिबद्ध (आधार)

"सैकड़ों संशोधन" की कमी के कारण, मैं निम्नलिखित पूर्व शर्तें मान रहा हूं:

  1. वहाँ कुछ शर्मनाक है कि आप चाहते हैं कि कभी अस्तित्व में नहीं था
  2. ZERO बाद में आने वाले कमिट हैं जो वास्तव में उस शर्मनाक कमिट पर निर्भर करते हैं (रिवर्ट पर शून्य संघर्ष)
  3. आप इस बात की परवाह नहीं करते हैं कि आपको सैकड़ों हस्तक्षेप करने वाले कमिटों के 'कमेटी' के रूप में सूचीबद्ध किया जाएगा ('लेखक' संरक्षित रहेगा)
  4. आपने रिपॉजिटरी को कभी साझा नहीं किया है
    • या आप वास्तव में उन सभी लोगों पर पर्याप्त प्रभाव डालते हैं, जिन्होंने कभी अपने इतिहास को अपने नए इतिहास का उपयोग करने के लिए मनाने के लिए इसमें प्रतिबद्ध किया है
    • और आप परवाह नहीं है के बारे में इतिहास को फिर से लिखने

यह बाधाओं का एक सुंदर प्रतिबंधक सेट है, लेकिन एक दिलचस्प जवाब है जो वास्तव में इस कोने के मामले में काम करता है।

यहाँ कदम हैं:

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

अगर वास्तव में कोई टकराव नहीं हैं, तो इसे बिना किसी रुकावट के आगे बढ़ना चाहिए। यदि संघर्ष होते हैं, तो आप उन्हें हल कर सकते हैं rebase --continueया शर्मिंदगी के साथ जीने का फैसला कर सकते हैं और rebase --abort

अब आपको इस पर होना चाहिए masterकि अब इसमें कोई आर नहीं है। जिस saveस्थिति में आप सामंजस्य बनाना चाहते हैं, उसके लिए शाखा आपको बताती है।

आप अपने नए इतिहास में अन्य सभी के स्थानांतरण की व्यवस्था कैसे करना चाहते हैं, यह आप पर निर्भर है। आप से परिचित होने की आवश्यकता होगी stash, reset --hardऔर cherry-pick। और अगर आप नष्ट कर सकते हैं base, remove-meऔर saveशाखाओं


मैं इसे 150000 बार कैसे पसंद कर सकता हूं?
गेना मोरोज़

मेरे लिए काम किया है कि एक शाखा के इतिहास के मध्य से 3 कमिट्स को हटा दें जहां किसी ने 150mb फाइलों का एक गुच्छा बनाया हो।
मार्कोस

3

मैं भी ऐसी ही स्थिति में उतरा। नीचे दिए गए आदेश का उपयोग करते हुए इंटरैक्टिव रिबास का उपयोग करें और चयन करते समय, 3 जी कम करें।

git rebase -i remote/branch

2

तो यहां वह परिदृश्य है जिसका मैंने सामना किया, और मैंने इसे कैसे हल किया।

[branch-a]

[Hundreds of commits] -> [R] -> [I]

यहाँ Rवह कमिटमेंट है जिसे मुझे हटाने की जरूरत थी, और Iएक सिंगल कमिट है जो बाद में आती हैR

मैंने एक उलट दिया और उन्हें एक साथ कर दिया

git revert [commit id of R]
git rebase -i HEAD~3

इंटरएक्टिव रिबास स्क्वैश के दौरान अंतिम 2 का प्रदर्शन होता है।


0

राडो और करीम के जवाब मेरे लिए कुछ नहीं करते हैं (केवल संदेश "वर्तमान शाखा अद्यतित है।" प्रकट होता है)। संभवतः ऐसा इसलिए होता है क्योंकि '' 'प्रतीक विंडोज कंसोल में काम नहीं करता है। हालाँकि, इस टिप्पणी के अनुसार , '~' द्वारा '~' को बदलने से समस्या हल हो जाती है।

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