Git: किसी विशिष्ट कमिट को कैसे रिबेस करें?


154

मैं एक विशिष्ट कमिट के लिए रिजेक्ट करना चाहूंगा, दूसरी ब्रांच के एक हेड के लिए नहीं:

A --- B --- C          master
 \
  \-- D                topic

सेवा

A --- B --- C          master
       \
        \-- D          topic

के बजाय

A --- B --- C          master
             \
              \-- D    topic

मैं उसे कैसे प्राप्त कर सकता हूं?


4
क्या आपने git checkout Bदौड़ने से पहले करने की कोशिश की है git rebase?
पीटर-पॉल वैन जेमरडेन

नहीं, कि मदद करनी चाहिए? मुझे लगता है कि केवल rebaseकमांड के संदर्भ क्या मायने रखते हैं।
ओन्ड्रा उइस्का

जवाबों:


98

आप अपनी पसंद के आधार पर एक अस्थायी शाखा बनाकर - theonto पैरामीटर का उपयोग करने से बच सकते हैं और फिर इसके सरल रूप में रिबास का उपयोग कर सकते हैं:

git branch temp master^
git checkout topic
git rebase temp
git branch -d temp

5
मुझे यह आरआईएससी-जैसा दृष्टिकोण अधिक पसंद है :) कोशिश करेंगे। धन्यवाद।
ओन्ड्रा उइस्का

10
मुझे आश्चर्य है कि यह मेरे लिए काम नहीं करता है, थोड़ा अलग परिदृश्य में । मैं चाहता हूं कि समूह pep8 को छोड़ दे और मास्टर पर आधारित हो । git rebase temp(जब समूह पर ) "वर्तमान शाखा समूह अद्यतित होते हैं"।
Alois Mahdal

4
यह समाधान उस परिदृश्य के लिए काम नहीं करेगा जहां विषय पहले से ही मास्टर पर रीबेड किया गया है, लेकिन आप इसे मास्टर करने के लिए पूर्वज पर रिबेस करना चाहते हैं। उस स्थिति में आपको इसका उपयोग करना चाहिए git rebase --onto <target> <from> <to>ताकि आप <से> प्रतिबद्ध कर सकें।
मिर्ज़मास्टर

यह अब तक का सबसे आसान विकल्प है यदि आप उसी आधार पर रिबास करना चाहते हैं जिस पर शाखा आधारित है।
ऐश

1
मैं काम करने लगता हूं, लेकिन गिटलैब कुछ और कहता है। अगर मेरे पीछे 10 कमिट्स थे, तो 5 कमिट्स आगे थे, मेरी उम्मीद 8 कमिट्स पीछे रहने की थी, 5 कमिट्स आगे आने के बाद 5 कमिट्स की। लेकिन इसके बजाय यह उन लोगों के लिए अधिक जोड़ता है 5.
ROMANIA_engineer

67

तुम भी एक सीधा दृष्टिकोण ले जा सकते हैं:

git checkout topic
git rebase <commitB>

6
मेरे लिए, यह वास्तव में वह नहीं है जो इरादा है। जहाँ तक मेरा बता सकते हैं, इसके बारे में "अंतिम सामान्य पूर्वज" पर rebase की कोशिश करता है topicऔर commitB
डैन लेन्स्की

2
@DanLenski, यह नहीं है कि कैसे रिबास काम करता है। डॉक्स के बावजूद , It works by going to the common ancestor of the two branches (the one you’re on and the one you’re rebasing onto), getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn. मैंने इसे फिर से आजमाया और बस ठीक काम करने लगा।
rhhitsharma

1
सुपर आसान और काम करता है! अब मेरे पास है: कमिट__ब्रोम_मास्टर-> topicCommit1-> topicCommit2।
मार्टिन कोनिसक

यह मेरे लिए काम नहीं किया। इससे पहले, GitLab ने कहा कि "n कमिट्स आगे"। और अब, यह कहते हैं, "मी आगे बढ़ता है" जहां m > n
ROMANIA_engineer

48

"चालू" विकल्प का उपयोग करें:

git rebase --onto master^ D^ D

2
Dऔर D^"विषय" के अंतिम और अगले-से-अंतिम वचन का हैश होगा?
ओन्ड्रा उइस्का

39
वाक्य-विन्यास जैसा है git rebase --onto <new-parent> <old-parent>एक अलग माता-पिता को git पैरेंट पॉइंटर सेट करना देखें । आपके मामले में, <new-parent> B है, और <old-parent> है A.
jsz

7
मैं हमेशा 3 तर्कों का उपयोग करता हूं: छूट के लिए प्रारंभ, समाप्ति और अंत।
एडम डिमिट्रुक

14
इसने मेरे लिए काम किया:git rebase --onto <commit-ID> master

4
@ jsz की टिप्पणी सही है, साइमन साउथ की टिप्पणी के विपरीत, यह दूसरी तरह के आसपास है: git rebase --onto master <commit-ID-of-old-parent>और ओपी के लिए git rebase --onto B A
भूतपूर्व

19

ऊपर jsz द्वारा की गई टिप्पणी ने मुझे बहुत सारे दर्द से बचाया, इसलिए यहाँ एक स्टेप-बाय-स्टेप रिसीवी है, जो इस पर आधारित है कि मैं किसी अन्य कमिट के शीर्ष पर किसी भी कमिट को रिबेट / मूव करने के लिए उपयोग कर रहा हूं:

  1. शाखा के एक पिछले ब्रांचिंग बिंदु को खोजा जा सकता है (स्थानांतरित) - इसे पुराने माता-पिता कहें। ऊपर के उदाहरण में वह A है
  2. शीर्ष पर खोजें, जिसमें आप शाखा को स्थानांतरित करना चाहते हैं - इसे नया अभिभावक कहें। एग्जाम में वो बी
  3. आपको अपनी शाखा पर रहने की जरूरत है (आप जिसे स्थानांतरित करते हैं):
  4. अपना रिबास लागू करें: git rebase --onto <new parent> <old parent>

ऊपर के उदाहरण में यह उतना ही सरल है:

   git checkout topic
   git rebase --onto B A

6
यह सही उत्तर होना चाहिए। सिवाय इसके कि मैं उपयोग करता हूं git rebase --onto B master, अधिक गहन स्पष्टीकरण के लिए मेरा उत्तर देखें ।
जैक मॉरिस

यह मेरे लिए ठीक काम नहीं किया। मैंने 2 लगातार कमिट्स चुने (मास्टर से अंतिम एक जो वर्तमान शाखा में था और पहला मास्टर से जो वर्तमान शाखा में नहीं था)। मैंने १०० पीछे से शुरू किया - १० आगे और १ ९९ पीछे करने के बजाय - १० आगे, अब मेरे पीछे १०५ है - १३ आगे।
ROMANIA_engineer

यह सुनने के लिए खेद है कि यह काम नहीं किया। आपकी शाखाओं की तरह लगता है कि यह बहुत कम है - मैं पहले कई मतभेदों के साथ शाखाओं को फिर से भरने की कोशिश करने से पहले स्क्वाश करने का सुझाव दूंगा।
नेस्टर मिलियाव

11

विषय समाधान

पोस्ट किए गए प्रश्न का उत्तर देने के लिए सही आदेश निम्नलिखित में से कोई भी हो सकता है (मान लें कि शाखा topicपहले से ही चेक आउट है):

git rebase --onto B master
git rebase --onto master~1 master
git rebase --onto B A
git rebase --onto B C
git rebase --onto B

यदि topicजाँच नहीं की जाती है, तो आप बस topicकमांड को जोड़ते हैं (अंतिम को छोड़कर) जैसे:

git rebase --onto B master topic

वैकल्पिक रूप से, पहले शाखा देखें:

git checkout topic

टारगेट कमिट करने के लिए कमिट्स के किसी भी स्ट्रिंग को रिबास करें

कमांड के मूल रूप की हमें आवश्यकता होती है, जिसे दस्तावेज़ीकरण से हटा दिया गया है:

git rebase --onto <Target> [<Upstream> [<Branch>]]

<Branch>वैकल्पिक है और यह सब करता है बाकी कमांड को निष्पादित करने से पहले निर्दिष्ट शाखा की जांच करता है। यदि आप पहले से ही उस शाखा को देख चुके हैं जिसे आप रिबेट करना चाहते हैं, तो आपको इसकी आवश्यकता नहीं है। ध्यान दें कि आपके पास निर्दिष्ट होना चाहिए<Upstream> करने के लिए<Branch> या गिट आपको लगता है कि आप निर्दिष्ट कर रहे हैं <Upstream>

<Target>हम प्रतिबद्ध है कि हम के लिए हमारी स्ट्रिंग संलग्न करेंगे। शाखा नाम प्रदान करते समय, आप बस उस शाखा के प्रमुख वचन को निर्दिष्ट कर रहे हैं।<Target>किसी भी प्रतिबद्ध किया जा सकता है कि ले जाया जा रहा है की स्ट्रिंग में निहित नहीं होगा। उदाहरण के लिए:

A --- B --- C --- D         master
      \
       \-- X --- Y --- Z    feature

पूरे सुविधा शाखा को स्थानांतरित करने के लिए, आप चयन नहीं कर सकते X, Y, Z, याfeature के रूप में <Target>उन के बाद से सभी समूह के अंदर प्रतिबद्ध ले जाया जा रहा है।

<Upstream>खास है क्योंकि इसका मतलब दो अलग-अलग चीजों से हो सकता है। यदि यह एक प्रतिबद्ध है जो चेक आउट शाखा का पूर्वज है, तो यह कट बिंदु के रूप में कार्य करता है। मेरे द्वारा दिए गए उदाहरण में, यह कुछ भी होगा जो नहीं है C,D या master<Upstream>चेक आउट ब्रांच के प्रमुख के आने के बाद सभी कमिट होते हैं जिन्हें स्थानांतरित कर दिया जाएगा।

हालांकि, यदि <Upstream>पूर्वज नहीं है, तो चेक को निर्दिष्ट प्रतिबद्ध से श्रृंखला का बैक अप लें जब तक कि चेक आउट शाखा के साथ एक सामान्य पूर्वज नहीं मिल जाता है (और यदि यह एक नहीं मिल सकता है तो गर्भपात करता है)। हमारे मामले में, एक में <Upstream>की B, C, D, या masterमें सभी परिणाम के लिए प्रतिबद्ध होगाB कटौती बिंदु के रूप में सेवारत। <Upstream>अपने आप में एक वैकल्पिक कमांड है और यदि यह निर्दिष्ट नहीं है, तो git चेक आउट ब्रांच के माता-पिता को देखता है जो प्रवेश के बराबर है master

अब उस git ने कट्स का चयन किया है जो कटेगा और आगे बढ़ेगा, यह उन्हें लागू होता है <Target> , जो पहले से ही लक्ष्य पर लागू होते हैं।

दिलचस्प उदाहरण और परिणाम

इस शुरुआती बिंदु का उपयोग करना:

A --- B --- C --- D --- E         master
            \
             \-- X --- Y --- Z    feature
  • git rebase --onto D A feature
    प्रतिबद्ध लागू होगी B, C, X, Y, Zप्रतिबद्ध करने के लिए Dऔर लंघन अंत Bऔर Cक्योंकि वे पहले से लागू किया गया है।

  • git rebase --onto C X feature
    प्रभावी ढंग से कमिट करने के लिए , कमिट Yऔर प्रतिबद्ध लागू करेंगेZCX


4

एक सरल उपाय है git rebase <SHA1 of B> topic। यह आपकी परवाह किए बिना काम करता HEADहै।

हम git rebase doc से इस व्यवहार की पुष्टि कर सकते हैं

<upstream>के खिलाफ तुलना करने के लिए अपस्ट्रीम शाखा। केवल एक मौजूदा शाखा का नाम नहीं, कोई भी मान्य प्रतिबद्धता हो सकती है । वर्तमान शाखा के लिए अपस्ट्रीम को कॉन्फ़िगर करने में चूक।


आप सोच रहे होंगे कि क्या होगा अगर मैं topicउपरोक्त कमांड में भी SHA1 का उल्लेख करूं?

git rebase <SHA1 of B> <SHA1 of topic>

यह भी काम करेगा, लेकिन फिर से Topicबनाया नई शाखा को इंगित नहीं करेगा ताकि बनाई गई और HEADअलग स्थिति में हो। इसलिए यहां से आपको मैन्युअल रूप से पुराने को हटाना होगा Topicऔर रिबास द्वारा बनाई गई नई शाखा पर एक नया शाखा संदर्भ बनाना होगा।


3

मैंने ऊपर वर्णित समाधानों के मिश्रण का उपयोग किया है:

$ git branch temp <specific sha1>
$ git rebase --onto temp master topic
$ git branch -d temp

मुझे पढ़ना और समझना बहुत आसान लगा। स्वीकृत समाधान मुझे एक मर्ज संघर्ष की ओर ले जाता है (हाथ से ठीक करने के लिए बहुत आलसी):

$ git rebase temp
First, rewinding head to replay your work on top of it...
Applying: <git comment>
Using index info to reconstruct a base tree...
M       pom.xml
.git/rebase-apply/patch:10: trailing whitespace.
    <some code>
.git/rebase-apply/patch:17: trailing whitespace.
        <some other code>
warning: 2 lines add whitespace errors.
Falling back to patching base and 3-way merge...
Auto-merging pom.xml
CONFLICT (content): Merge conflict in pom.xml
error: Failed to merge in the changes.
Patch failed at 0001 <git comment>
The copy of the patch that failed is found in: .git/rebase-apply/patch

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".

1
यहाँ पर, कई फाइलों में तब टकराव हुआ जब मैंने 2 सबसे लोकप्रिय उत्तरों (यानी r0hitsharma and Dymitruk द्वारा) का इस्तेमाल किया
ओलिवर

3

चूंकि रिबासिंग इतना मौलिक है, इसलिए यहां नेस्टर मिलियाव के जवाब का विस्तार है । संयोजन jsz की और साइमन दक्षिण से टिप्पणी एडम Dymitruk का जवाब इस आदेश है जिस पर काम करता है पैदावार topicकी यह से शाखाओं कि क्या परवाह किए बिना शाखा masterशाखा के लिए प्रतिबद्ध Aया C:

git checkout topic
git rebase --onto <commit-B> <pre-rebase-A-or-post-rebase-C-or-base-branch-name>

ध्यान दें कि अंतिम तर्क की आवश्यकता है (अन्यथा यह आपकी शाखा को प्रतिबद्ध करने के लिए याद दिलाता है B)।

उदाहरण:

# if topic branches from master commit A:
git checkout topic
git rebase --onto <commit-B> <commit-A>
# if topic branches from master commit C:
git checkout topic
git rebase --onto <commit-B> <commit-C>
# regardless of whether topic branches from master commit A or C:
git checkout topic
git rebase --onto <commit-B> master

तो अंतिम कमांड वह है जिसे मैं आमतौर पर उपयोग करता हूं।


-2

ऐसा करने का एक और तरीका है या यदि आप केवल एक कमिटमेंट में वापस जाने की इच्छा रखते हैं।

यहाँ एक उदाहरण है nकि कमिट की संख्या पर वापस जाएँ :

git branch topic master~n

इस प्रश्न के लिए, यह भी किया जा सकता है:

git branch topic master~1

कमांड पूरी तरह से काम करता है git version 2.7.4। किसी अन्य संस्करण पर इसका परीक्षण नहीं किया गया है।


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