मैं दो गैर-लगातार आवागमन कैसे कर सकता हूं?


182

मैं गिट के भीतर पूरे रिबासिंग फीचर के लिए थोड़ा नया हूं। मान लीजिए कि मैंने निम्नलिखित काम किए हैं:

A -> B -> C -> D

बाद में, मुझे एहसास हुआ कि Dइसमें एक फिक्स है जो Aकि जोड़े गए कुछ नए कोड पर निर्भर करता है और ये कमिट एक साथ हैं। मैं कैसे छुटकारा पाने करते Aऔर Dएक साथ और छुट्टी Bऔर Cअकेले?

जवाबों:


257

आप git rebase --interactiveB से पहले D को चला सकते हैं और D को A में स्क्वैश कर सकते हैं।

Git एक संपादक को खोलेगा, और आप इस तरह एक फ़ाइल देखेंगे, उदा: git rebase --interactive HEAD~4

pick aaaaaaa Commit A
pick bbbbbbb Commit B
pick ccccccc Commit C
pick ddddddd Commit D

# Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s))
#
# 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
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

अब आप इस तरह दिखने वाली फ़ाइल को बदलते हैं:

pick aaaaaaa Commit A
squash ddddddd Commit D
pick bbbbbbb Commit B
pick ccccccc Commit C

और git अब A और D के बदलाव को एक साथ एक कमिट में पिघला देगा, और बाद में B और C को डाल देगा। जब आप D के प्रतिबद्ध संदेश को रखना नहीं चाहते हैं, तो इसके बजाय squash, आप fixupकीवर्ड का उपयोग करेंगे । अधिक जानकारी के लिए fixup, आप git rebaseडॉक्स से परामर्श कर सकते हैं , या इस प्रश्न को देख सकते हैं , जिसके कुछ अच्छे उत्तर हैं।


5
प्रारंभ में, मैंने इसे "रिबेस डी पर ए, स्क्वैश डी में ए, फिर बी पर डीए पर रीबेस डी" के रूप में पढ़ा। यह उत्तर से स्पष्ट नहीं है कि यह एक पाठ संपादक में लाइनों को फिर से व्यवस्थित करके किया जा सकता है।
विक्टर सर्जेनको

3
यदि आपकी शाखा स्थानीय है, तो आपको There is no tracking information for the current branchरिबास करते समय त्रुटि मिलेगी । इस मामले में आप प्रतिबद्ध आप इस तरह, के साथ काम करना चाहता हूँ की संख्या निर्दिष्ट करने की जरूरत है: git rebase -i HEAD~4इस जवाब को देखें ।
जॉन्डोडो

1
मैं वर्षों के लिए इंटरेक्टिव मोड (git rebase -i) का उपयोग करता हूं, मुझे बस एहसास हुआ कि इसे फिर से व्यवस्थित किया जा सकता है । धन्यवाद Thanks
केल्विनचेक

43

नोट: आपको किसी भी तरह से किसी अन्य रेपो के लिए धक्का नहीं दिया जाना चाहिए, जब तक आपको परिणाम पता न हो

git log --oneline -4

D commit_message_for_D
C commit_message_for_C
B commit_message_for_B
A commit_message_for_A

git rebase --interactive

pick D commit_message_for_D
pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A

टाइप करें i(डालें मोड में वीआईएम डालें)

इस तरह दिखने के लिए सूची को बदलें (आपको कमिट को हटाने या शामिल करने की आवश्यकता नहीं है)। याद मत करो squash! :

pick C commit_message_for_C
pick B commit_message_for_B
pick A commit_message_for_A
squash D

Escइसके बाद टाइप ZZकरें (VIM सहेजें और बाहर निकलें)

# This is a combination of 2 commits.
# The first commit's message is:

commit_message_for_D

# This is the 2nd commit message:

commit_message_for_A

प्रकार i

पाठ को बदलें जो आप चाहते हैं कि नया प्रतिबद्ध संदेश कैसा दिखे। मेरा सुझाव है कि यह प्रतिबद्धताओं में बदलाव का विवरण है Aऔर D:

new_commit_message_for_A_and_D

Escफिर टाइप करेंZZ

git log --oneline -4

E new_commit_message_for_A_and_D
C commit_message_for_C
B commit_message_for_B

git show E

(You should see a diff showing a combination of changes from A and D)

आपने अब एक नई प्रतिबद्धता बनाई है E। कमिट करता है Aऔर Dअब आपके इतिहास में नहीं है, लेकिन गया नहीं है। आप इस बिंदु पर और थोड़ी देर के लिए उन्हें पुनर्प्राप्त कर सकते हैं git rebase --hard D( git rebase --hardकिसी भी स्थानीय परिवर्तन को नष्ट कर देगा! )।


3

SourceTree का उपयोग करने वालों के लिए :

सुनिश्चित करें कि आपने पहले ही कमिट को धक्का नहीं दिया है।

  1. रिपोजिटरी> इंटरएक्टिव रिबेस ...
  2. D (नई कमेटी) को सीधे A (पुरानी प्रतिबद्ध) से ऊपर खींचें
  3. सुनिश्चित करें कि डी को हाइलाइट किया गया है
  4. क्लिक करें Squash with previous

1

इंटरएक्टिव रिबेस तब तक अच्छी तरह से काम करता है जब तक कि आपके पास 20-30 कमिट्स और / या मास्टर या मर्ज के जोड़े के साथ बड़ी सुविधा शाखा है और जब आप अपनी ब्रांच में आ रहे थे तो टकराव ठीक कर रहे हैं। यहां तक ​​कि इतिहास के माध्यम से मेरे कमिटमेंट खोजने और यहां काम करने की जगह के pickसाथ squashभी। इसलिए मैं दूसरे तरीके की तलाश कर रहा था और इस लेख को पाया । मैंने अलग शाखा में इस पर काम करने के लिए अपने बदलाव किए:

git checkout master
git fetch
git pull
git merge branch-name
git reset origin/master
git branch -D branch-name
git checkout -b branch-name
git add --all
#Do some commit
git push -f --set-upstream origin branch-name

इससे पहले मुझे मास्टर + फिक्सिंग संघर्षों के 2-3 मर्जों के साथ ~ 30 कमिट्स के साथ मेरा पुल अनुरोध मिला। और इसके बाद मुझे एक पीआर के साथ स्पष्ट पीआर मिला।

PS यहां ऑटोमोडे में इस स्टेप्स को करने के लिए बैश स्क्रिप्ट है।


उस लेख में पहला समाधान वास्तव में अच्छा है, इस लिंक के लिए धन्यवाद
हूडी

-1

$ गिट चेकआउट मास्टर

$ गिट लॉग - ऑनलाइन

D
C
B
A

$ गिट रिबास - सैंटो हेड ^ ^ ^ ^ ^ ^ ^

$ गिट लॉग - ऑनलाइन

D
A

मुझे लगता है कि आपका मतलब है --oneline? और ऐसा लगता है कि आपने गिरा दिया है Cऔर Bवह नहीं है, जो ओपी का इरादा था।
bstpierre

मेरे लिए काम नहीं किया। इसने मेरे हेड और मास्टर दोनों को ए में स्थानांतरित कर दिया, लेकिन डी को ए ( git show A) में विलय नहीं किया और डी, सी और बी मेरे रिफ-लॉग में खो गए। git rebase Dवापस लाना था ।
नैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.