अपने परिवर्तनों को रखते हुए Git रिपॉजिटरी से चयनित कमिट एंट्री प्रविष्टियों को कैसे निकालें?


241

मैं एक लीनियर कमिट ट्री से चुनिंदा कमिट लॉग एंट्रीज को हटाना चाहता हूं, ताकि एंट्रीज कमिट लॉग में न दिखें।

मेरा प्रतिबद्ध पेड़ कुछ इस तरह दिखता है:

R--A--B--C--D--E--HEAD

मैं बी और सी प्रविष्टियों को निकालना चाहूंगा ताकि वे कमिट लॉग में न दिखें, लेकिन ए से डी में परिवर्तन संरक्षित होना चाहिए। हो सकता है कि एक ही प्रतिबद्ध शुरू करके, ताकि बी और सी बीसी बन जाएं और पेड़ जैसा दिखता है।

R--A--BC--D--E--HEAD

या, आदर्श रूप से, ए के बाद डी सीधे आता है। D 'A से B, B से C और C से D तक के परिवर्तनों का प्रतिनिधित्व करता है।

R--A--D'--E--HEAD

क्या यह संभव है? यदि हाँ, तो कैसे?

यह एक काफी नई परियोजना है, जिसकी अब तक कोई शाखा नहीं है, इसलिए इसका कोई विलय भी नहीं है।


@ xk0der: "कमिट्स" यहां सही शब्द है। rebaseपुराने को हटा सकते हैं / नए कमिट बना सकते हैं। मुझे नहीं पता कि "प्रतिबद्ध लॉग प्रविष्टियाँ" का क्या मतलब है।
JFS

@JFSebastian मुझे "कमिट लॉग" के साथ कोई समस्या नहीं दिखती है - सभी कमिट्स का लॉग। और मैं वास्तविक परिवर्तन (कमिट्स) को ध्यान में रखते हुए लॉग से कुछ प्रविष्टियों को हटाना चाहता था।
xk0der

@ xk0der: git commits कंटेंट-एड्रेसेबल हैं , अगर आप कमिट में कुछ भी बदलते हैं जैसे, इसका लॉग संदेश; आप एक नई प्रतिबद्धता बनाते हैं। आप git की कमिट को बिना git के पढ़ सकते हैं और अपने लिए देख सकते हैं
JFS

@JFSebastian - लिंक के लिए धन्यवाद - मुझे पता है कि - लेकिन क्या तकनीकीता वास्तव में मेरे द्वारा सामना की जा रही समस्या को बदल देती है और मैं इसे कैसे सामने रखूं? मुझे नहीं लगता। अंत में: मैं "कमिट लॉग मैसेजेस" को हटाना चाहता था - "कमिट्स चेंजेस" को हटाए बिना - कृपया मेरे सवाल को फिर से पढ़ें - विशेष रूप से दूसरा पैराग्राफ। अधिक जोड़ने के git logलिए "कमिट लॉग" git-scm.com/docs/git-log दिखाता है । और मैं उस लॉग से दो प्रविष्टियों से छुटकारा पाना चाहता था - परिवर्तन नहीं।
xk0der

जवाबों:


273

git-rebase (1) ठीक यही करता है।

$ git rebase -i HEAD~5

git awsome-ness [git rebase --interactive] में एक उदाहरण है।

  1. git-rebaseसार्वजनिक (दूरस्थ) कमिट पर उपयोग न करें ।
  2. सुनिश्चित करें कि आपकी कार्यशील निर्देशिका साफ़ है ( commitया stashआपके वर्तमान परिवर्तन)।
  3. उपरोक्त आदेश चलाएँ। यह आपकी शुरूआत करता है $EDITOR
  4. बदलें pickसे पहले Cऔर Dसे squash। यह C और D को B में पिघला देगा। यदि आप किसी कमिट को हटाना चाहते हैं तो बस इसकी लाइन को हटा दें।

यदि आप खो गए हैं, तो टाइप करें:

$ git rebase --abort  

जल्दी जवाब देने का शुक्रिया। तो क्या मैं A को चेकआउट करता हूं और एक रिबेस करता हूं, जैसे कुछ git rebase -i D [A]?
xk0der


3
हम इसे रिमोट रिपॉजिट पर कैसे कर सकते हैं?
एरियन

6
@Eray: सिर्फ push -fअपने परिवर्तन। यदि आप अकेले काम नहीं कर रहे हैं तो ऐसा न करें।
jfs

2
@ ripper234: मैंने git-rebaseब्लॉग पोस्ट के लिए पॉइंट मैनुअल और वेकबैक मशीन के लिंक तय किए हैं ।
12

75
# detach head and move to D commit
git checkout <SHA1-for-D>

# move HEAD to A, but leave the index and working tree as for D
git reset --soft <SHA1-for-A>

# Redo the D commit re-using the commit message, but now on top of A
git commit -C <SHA1-for-D>

# Re-apply everything from the old D onwards onto this new place 
git rebase --onto HEAD <SHA1-for-D> master

यह भी काम करता है और मुझे यह समझने में मदद करता है कि नरम रीसेट क्या है। दी, "शीर्ष" उत्तर सही है और छोटा है, लेकिन इस उत्तर के लिए भी धन्यवाद।
cgp

41

यहाँ एक विशिष्ट प्रतिबद्ध आईडी को हटाने का एक तरीका है, केवल यह जानने के लिए कि आप किस आईडी को हटाना चाहते हैं।

git rebase --onto commit-id^ commit-id

ध्यान दें कि यह वास्तव में उस बदलाव को हटा देता है जिसे कमिट द्वारा पेश किया गया था।


7
इस आदेश में अतिरिक्त HEAD एक 'अलग किए गए HEAD' के साथ रिबेस को समाप्त करने का कारण बनेगा, जो अवांछनीय है। इसे ommitted होना चाहिए।
फ्रॉस्टी

3
यह मेरे कमिट-आईडी को पेश किए गए बदलावों को दर्शाता है, ओपी बदलावों को बनाए रखना चाहता है, बस कमिट्स को स्क्वैश करता है।
सीबी बेली

1
-1 क्योंकि यह वह नहीं करता है जो ओपी ने पूछा था (बल्कि यह कुछ नष्ट कर देता है जिसे वह स्पष्ट रूप से बनाए रखना चाहता था)।
एमिल स्टायरके

1
यद्यपि यह वह नहीं करता है जो ओपी ने पूछा था, यह वही था जो मुझे चाहिए था, इसलिए उपयोगी उत्तर के लिए +1।
एडविंस

20

जेएफ सेबेस्टियन के जवाब पर विस्तार करने के लिए:

आप अपने प्रतिबद्ध इतिहास में आसानी से सभी प्रकार के परिवर्तन करने के लिए git-rebase का उपयोग कर सकते हैं।

Git rebase चलाने के बाद - आपको अपने $ EDITOR में निम्नलिखित मिलेंगे:

pick 366eca1 This has a huge file
pick d975b30 delete foo
pick 121802a delete bar
# Rebase 57d0b28..121802a onto 57d0b28
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit

आप कमिट के क्रम को बदलने के लिए लाइनों को स्थानांतरित कर सकते हैं और उस कमिट को हटाने के लिए लाइनें हटा सकते हैं। या आप दो कमिट्स को एक ही कमिट में जोड़ सकते हैं (स्क्वैश) एक कमांड को जोड़ सकते हैं (पिछली कमिट ऊपर दी गई कमिट है), कमिट्स को एडिट करें (जो बदला गया था), या फिर कमिट मैसेज को फिर से करें।

मुझे लगता है कि पिक का मतलब है कि आप उस कमिटमेंट को अकेले छोड़ना चाहते हैं।

(उदाहरण यहाँ से है )


14

आप गैर-संवादात्मक रूप से B और C को अपने उदाहरण में निकाल सकते हैं :

git rebase --onto HEAD~5 HEAD~3 HEAD

या प्रतीकात्मक रूप से,

git rebase --onto A C HEAD

ध्यान दें कि B और C में परिवर्तन D में नहीं होगा ; वे चले जाएंगे ।


अधिक जानकारी के लिए यहां देखें: sethrobertson.github.io/GitFixUm/fixup.html#remove_deep
Max

3

एक और तरीका,

git rebase -i ad0389efc1a79b1f9c4dd6061dca6edc1d5bb78a (C's hash)
and
git push origin master  -f

उस हैश को चुनें जिसे आप आधार के रूप में उपयोग करना चाहते हैं, और उपरोक्त कमांड को इसे इंटरैक्टिव बनाना चाहिए ताकि आप सभी शीर्ष संदेशों को स्क्वैश कर सकें (आपको सबसे पुराना छोड़ने की आवश्यकता है)


2

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

git checkout <SHA1 of A>
git log #verify looks good
git checkout -b rework
git cherry-pick <SHA1 of D>
....
git log #verify looks good
git branch -D <oldbranch>
git branch -m rework <oldbranch>

यदि आप ऐसा करते हैं तो आप E को भी खो देंगे, है ना? जैसा कि मैंने समझा था, आप मास्टर को हटा देते हैं और मास्टर के रूप में नाम बदलते हैं (एबीसीडीई प्रवाह को देखते हुए मास्टर शाखा है)।
रेन बंदेइरा

1

बस सभी लोगों के उत्तर एकत्र किए गए: (git plz इसे केवल संदर्भ के लिए उपयोग करने के लिए नया)

किसी भी हिट को हटाने के लिए रीट रिसेट करें

गिट लॉग

-first check from which commit you want to rebase

git rebase -i HEAD ~ १

-Here i want to rebase on the second last commit- commit count starts from '1')
-this will open the command line editor (called vim editor i guess)

तब स्क्रीन कुछ इस तरह दिखाई देगी:

नई लाइन जोड़ा 0c2236d उठाओ।

2a1cd65 पर रीबेस 2a1cd65..0c2236d (1 कमांड)

#

आदेश:

पी, उठाओ = उपयोग कमिट

r, reword = use प्रतिबद्ध करें, लेकिन प्रतिबद्ध संदेश को संपादित करें

ई, संपादित करें = कमिट का उपयोग करें, लेकिन संशोधन के लिए रुकें

s, स्क्वैश = कमिट का उपयोग करें, लेकिन पिछले प्रतिबद्ध में पिघला

f, fixup = जैसे "स्क्वैश", लेकिन इस कमिट के लॉग संदेश को त्याग दें

x, निष्पादित = कमांड (लाइन के बाकी भाग) शेल का उपयोग करके

d, drop = remove प्रतिबद्ध

#

इन पंक्तियों को फिर से आदेश दिया जा सकता है; वे ऊपर से नीचे तक क्रियान्वित होते हैं।

#

यदि आप यहां से एक लाइन हटाते हैं, तो यह कम होगा।

#

हालांकि, यदि आप सब कुछ हटा देते हैं, तो रिबास निरस्त कर दिया जाएगा।

#

ध्यान दें कि खाली कॉमेंट में ~ ~ टिप्पणी की जाती है

~
~
~
~
~
~
~
~
~ ~

यहां अपनी आवश्यकता के अनुसार पहली पंक्ति को बदलें (प्रतिबद्ध को हटाने के लिए ऊपर दिए गए आदेशों का उपयोग करें।

और तब

जोर का धक्का

यदि इसकी समस्या दिख रही है तो आपको परिवर्तनों को दूरस्थ रूप से धकेलने की आवश्यकता है (ITS VERY CRITICAL: यदि आप टीम में काम कर रहे हैं तो बलपूर्वक धक्का न दें)

git पुश -f उत्पत्ति


-1

आप इसके लिए गिट चेरी-पिक का इस्तेमाल कर सकते हैं। 'चेरी-पिक' अब आपके ब्रांच पर एक कमिट लगाएगा।

फिर करो

git rebase --hard <SHA1 of A>

फिर डी और ई लागू करें।

git cherry-pick <SHA1 of D>
git cherry-pick <SHA1 of E>

यह B और C कमिट को छोड़ देगा। कहा जा रहा है कि डी के बिना डी को शाखा में लागू करना असंभव हो सकता है, इसलिए वाईएमएमवी।


2
ओपी बी, सी, डी को संयोजित करना चाहता है, न कि उनके परिवर्तनों को हटाना।
jfs

3
मुझे लगता है कि आपका मतलब है reset --hard, नहीं rebase --hard(जो मौजूद नहीं है)
मौरिसियो शेफ़र
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.