कैसे एक से अधिक कॉमेरी लेने के लिए


873

मेरी दो शाखाएँ हैं। कमिट a, एक का सिर है अन्य है, जबकि b, c, d, eऔर fकी चोटी पर a। मैं ले जाना चाहते हैं c, d, eऔर fबिना प्रतिबद्ध पहली शाखा करने के लिए b। का उपयोग करते हुए चेरी यह लेने आसान है: चेकआउट पहली शाखा एक के बाद एक चेरी लेने cके लिए fऔर पहली पर दूसरी शाखा rebase। लेकिन क्या सभी को चेरी c- fएक कमांड में लेने का कोई तरीका है ?

यहाँ परिदृश्य का एक दृश्य विवरण है (धन्यवाद JJD ):

यहां छवि विवरण दर्ज करें


3
आपके द्वारा उल्लेख किया गया रिबेज़ वास्तव में प्रासंगिक नहीं है? (मुझे लगता है कि आप बाद में पर bआधारित होना चाह सकते हैं f, लेकिन इसका चेरी-पिकिंग से कोई लेना-देना नहीं है।)
सुपरऑल

जवाबों:


1280

Git 1.7.2 ने चेरी की एक श्रृंखला को शुरू करने की क्षमता का परिचय दिया। से रिलीज नोट्स :

git cherry-pickकई प्रकार के कमिट (जैसे cherry-pick A..Bऔर cherry-pick --stdin) लेने के लिए सीखा , ऐसा किया git revert; rebase [-i]हालांकि, नेक्सस अनुक्रमण नियंत्रण का समर्थन नहीं करता है ।

चेरी Aको कमिट -पिक करने के लिए कमिट से कमिट B(जहां Aउम्र अधिक है B), चलाएं:

git cherry-pick A^..B

यदि आप स्वयं को अनदेखा करना चाहते हैं , तो दौड़ें:

git cherry-pick A..B

(टिप्पणी में क्रेडिट डेमियन, जेबी रेन्सबर्गर और sschaef को जाता है)


249
"चेरी-पिक ए..बी" फॉर्म में, ए को बी से पुराना होना चाहिए। यदि वे गलत क्रम हैं तो कमांड चुपचाप विफल हो जाएगी।
दामियन

294
इसके अलावा, यह चेरी-पिक ए नहीं होगा, बल्कि ए के बाद ए और बी सहित सभी कुछ
जेबी रेन्सबर्गर

454
A प्रकार को शामिल करने के लिएgit cherry-pick A^..B
kiritsuku

17
आप Git 1.7.1 या उससे पहले और नहीं कर सकते हैं अद्यतन है, तो आप बहुत जल्दी से उन्हें क्रम में चलाकर चेरी ले सकते हैं git cherry-pick f~3तो git cherry-pick f~2आदि अप करने के लिए git cherry-pick f(ऊपर तीर दबाने हो जाता है पिछला आदेश तो मैं जल्दी से संख्या और चलाने को बदल सकते हैं यह, अधिकांश कंसोल में समान होना चाहिए)।
डेविड मेसन

19
यह जानना अच्छा हो सकता है कि यह सिंटैक्स शाखा नामों के साथ भी काम करता है। git cherry-pick master..somebranchमास्टर (क्योंकि पहले से ही मास्टर पर छूट है), और उन्हें अपनी वर्तमान शाखा में लागू करने के बाद से किसी न किसी तरह सभी कमानों को चुन लेंगे।
Tor Klingberg

102

ऐसा करने का सबसे सरल तरीका ontoविकल्प के साथ है rebase। मान लीजिए कि पर शाखा है जो वर्तमान खत्म amybranch कहा जाता है और इस शाखा है कि आप ले जाना चाहते है c- fपर।

# checkout mybranch
git checkout mybranch

# reset it to f (currently includes a)
git reset --hard f

# rebase every commit after b and transplant it onto a
git rebase --onto a b

1
धन्यवाद! क्या आप git checkout secondbranch && git rebase mybranchपूर्ण उत्तर के लिए भी जोड़ सकते हैं
tig

1
इस उत्तर ने मुझे अपना सिर पाने में बहुत मदद की, जो इस परिदृश्य में है। और: आप rebaseभी इंटरैक्टिव मोड का उपयोग कर सकते हैं । धन्यवाद, @Charles!
ओलिवर

1
इस दृष्टिकोण की सुंदरता यह है कि आप --interactiveअनुक्रम से कुछ कमिट्स को हटाने के लिए उपयोग कर सकते हैं या "चेरी पिक" से पहले उन्हें फिर से व्यवस्थित कर सकते हैं । +1
माइकल मर्केल

यह एक सामान्य आदेश है, अपने सिर को चारों ओर लपेटने के लिए थोड़ा मुश्किल है, लेकिन यह अद्भुत काम करता है।
वेलेरियो

वाइल्ड जिसे आपको कमिटमेंट देना है कि आप डिबेट में से एक के रूप में रिबास नहीं करना चाहते हैं ( bइस उदाहरण में) लेकिन हां इसने मेरे लिए काम किया है।
asontu

85

या अनुरोधित वन-लाइनर:

git rebase --onto a b f

5
यदि केवल इसकी संक्षिप्तता के लिए, यह सबसे अच्छा जवाब है।
नैट चांडलर

9
अपवोट किया गया है, लेकिन अगर आप एक प्रतिबद्ध (एक शाखा के विपरीत) है - तो आप को अलग राज्य में छोड़ देंगे - आपको यह जोड़ने के लिए संपादित करना चाहिए कि किसी शाखा को नीचे दिए गए उत्तर के
जांचना

68

आप की एक सीरियल संयोजन का उपयोग कर सकते हैं git rebaseऔर git branchकिसी अन्य शाखा पर प्रतिबद्ध के एक समूह लागू करने के लिए। जैसा कि पहले ही wolfc द्वारा पोस्ट किया गया पहला कमांड वास्तव में कमिट को कॉपी करता है। हालाँकि, परिवर्तन तब तक दिखाई नहीं देता है जब तक कि आप समूह के सबसे शीर्ष पर एक शाखा का नाम नहीं जोड़ते हैं।

कृपया चित्र को एक नए टैब में खोलें ...

कार्यप्रवाह

पाठ रूप में आदेशों को संक्षेप में प्रस्तुत करने के लिए:

  1. कमांड का उपयोग करके एक स्वतंत्र प्रक्रिया के रूप में गिटक खोलें gitk --all &:।
  2. भागो git rebase --onto a b f
  3. GitkF5 में दबाएं । कुछ नहीं बदलता है। लेकिन कोई निशान नहीं है।HEAD
  4. Daud git branch selection
  5. GitkF5 में दबाएं । इसके कमिट के साथ नई शाखा दिखाई देती है।

यह चीजों को स्पष्ट करना चाहिए:

  • कमेटी aग्रुप का नया रूट डेस्टिनेशन है।
  • कमेटी bग्रुप की पहली कमेटी (अनन्य) से पहले की प्रतिबद्धता है।
  • कमेटी fग्रुप का अंतिम कमिट (समावेशी) है।

बाद में, आप इस्तेमाल कर सकते हैं git checkout feature && git reset --hard bप्रतिबद्ध नष्ट करने के लिए cजब तक fसे featureशाखा।

इस उत्तर के अलावा, मैंने एक ब्लॉग पोस्ट लिखी जिसमें कमांड्स का वर्णन एक अन्य परिदृश्य में किया गया है जो आम तौर पर इसका उपयोग करने में मदद करनी चाहिए।


2
अगर mybranch (a..f commits) की जरूरत नहीं है, तो इसे सरल बनाया जा सकता है: git rebase --onto a b mybranchऔर btw - कौन सा प्रोग्राम उन निफ्टी git चित्रों को करता है?
Mr_and_Mrs_D

2
@Mr_and_Mrs_D आपकी टिप्पणी के लिए धन्यवाद। मुझे लगता है कि मैंने चित्रों को खींचने के लिए cacoo.com का उपयोग किया ।
JJD

48

विशेष रूप से इस सवाल का जवाब देने के लिए जेबी रैंसबर्गर और sschaef की टिप्पणियों को लागू करने के लिए ... इस उदाहरण के लिए चेरी-पिक रेंज का उपयोग करें:

git checkout a
git cherry-pick b..f

या

git checkout a
git cherry-pick c^..f

3
मैंने उपयोग किया git 2.7.0.windows.1और देखा कि जब मैं चेरी की रेंज लेने की कोशिश करता है तो सब कुछ ठीक है, लेकिन गिट आपको कहीं भी यह नहीं बताता है git cherry-pick --continue | --abort | --quitकि आपको फिर से प्रतिबद्ध / चेरी-पिक करने की कोशिश करने से पहले करना होगा। तो अगर आप git cherry-pick --continueदिए गए रेंज से कमिट -पिक रेंज कमिट करते हैं तो आपको हर बार तैयार होने की जरूरत है (संघर्ष या ऐसे हल करने के लिए)।
कुस्कमेन

मैंने ठीक वैसा ही किया, लेकिन घातक था:
अमित कार्णिक

मुझे नहीं पता कि मैं कहां गलत हूं, लेकिन जब मैं अपनी तरफ से 'git cherry-pick c ^ .. f' करता हूं, तो इसमें कमिट f शामिल है लेकिन कमिट c नहीं। लेकिन जैसा कि मैंने हर जगह पढ़ा है, यह समावेशी के रूप में c और f को परिभाषित करने वाला है। या मैं गलत हूँ?
शमूएल

@ शमूएल हां, यह सही है। ^के बाद ग वास्तव में इसका मतलब है जो इस मामले में ख है "ग से पहले प्रतिबद्ध"। इसी c^..fका पर्याय है b..f। करने की कोशिश करें git log c^..fऔर आपको f के माध्यम से कमिट्स सी दिखना चाहिए, ठीक उसी तरह जैसे आपने किया थाgit log b..f
एंडी

40

यदि आपके पास विलय करने के लिए चयनात्मक संशोधन हैं, तो ए, बी, सी, डी, ई, एफ, जी, एच, आई, जे से कम ए, सी, एफ, जे कहते हैं, बस कमांड के नीचे का उपयोग करें:

git चेरी-पिक ACFJ


1
अच्छा और सरल
पालक

21
git rev-list --reverse b..f | xargs -n 1 git cherry-pick

2
अगर कोई संघर्ष नहीं है, तो सही काम करता है, अन्यथा "पर छूट" आसान हो सकता है क्योंकि आपको यह पता लगाने की ज़रूरत नहीं होगी कि यह कहाँ रुक गया है और बाकी पैच को फिर से लागू करना है।
रुसलान कबालिन

6
कृपया टिप्पणी करते हुए बताएं कि यह क्या कर रहा है
Mr_and_Mrs_D

7
चूँकि किसी ने समझाया नहीं ... git Rev-list ब्रांच b से f (उलट) के सभी संशोधनों को प्रिंट करता है, ताकि जब प्रत्येक लाइन (कमिट हैश) क्रम में पारित हो जाए, तो यह प्रत्येक को वर्तमान git HEAD पर चुन लेगी। अर्थातgit cherry-pick {hash of c}; git cherry-pick {hash of d}; ...
कोडरचेत

8

ब्रांच की टिप तक एक कमिट आईडी से चेरी लेने के लिए, आप इसका उपयोग कर सकते हैं:

git cherry-pick commit_id^..branch_name


यह पहले से ही उत्तर stackoverflow.com/a/31640427/96823
tig

1
यह उत्तर वास्तव में अलग है और मेरे लिए मददगार था। यह शाखा का नाम निर्दिष्ट करता है, अंतिम प्रतिबद्ध SHA नहीं।
सबट्री

7

एक और उल्लेख योग्य बात यह है कि यदि आप चाहते हैं कि अंतिम nएक शाखा से आए, तो ~वाक्यविन्यास उपयोगी हो सकता है:

git cherry-pick some-branch~4..some-branch

इस मामले में, उपरोक्त कमांड अंतिम 4 कमिट्स को एक शाखा से लेगी, जिसे some-branch(हालांकि आप एक शाखा के नाम के स्थान पर एक प्रतिबद्ध हैश का उपयोग भी कर सकते हैं)


1
बहुत उपयोगी जवाब, धन्यवाद! :)
जसक डेज़र्डज़िकोस्की

3

वास्तव में, इसे करने का सबसे सरल तरीका यह हो सकता है:

  1. दो शाखाओं के बीच मर्ज-बेस रिकॉर्ड करें: MERGE_BASE=$(git merge-base branch-a branch-b)
  2. तेजी से आगे या नई शाखा पर पुरानी शाखा को फिर से शुरू करें
  3. चरण 1 से मर्ज बेस पर शुरू होने पर, स्वयं पर परिणामी शाखा को रिबास करें, और वांछित नहीं होने वाले मैन्युअल रूप से हटा दें:

    git rebase ${SAVED_MERGE_BASE} -i
    

    वैकल्पिक रूप से, यदि केवल कुछ नए कमिट हैं, तो चरण 1 को छोड़ दें, और बस उपयोग करें

    git rebase HEAD^^^^^^^ -i
    

    पहले चरण में, ^मर्ज-बेस को स्थानांतरित करने के लिए पर्याप्त उपयोग करना।

आपको इंटरेक्टिव रिबेस में कुछ इस तरह दिखाई देगा:

pick 3139276 commit a
pick c1b421d commit b
pick 7204ee5 commit c
pick 6ae9419 commit d
pick 0152077 commit e
pick 2656623 commit f

फिर लाइनों को हटा दें b (और कोई अन्य जिसे आप चाहते हैं)



0

यहाँ एक स्क्रिप्ट है जो आपको एक पंक्ति में कई कॉमेरी को चेरी-पिक करने की अनुमति देगी, केवल स्क्रिप्ट को बताकर कि चेरी पिक्स के लिए कौन सा स्रोत और टार्गेट शाखाएँ और कमिट्स की संख्या:

https://gist.github.com/nickboldt/99ac1dc4eb4c9ff003a1effef2eb2d81

मास्टर करने के लिए अपनी शाखा से चेरी लेने के लिए (स्रोत के रूप में वर्तमान शाखा का उपयोग करता है):

./gcpl.sh -m

अपनी 6.19.x शाखा से मास्टर करने के लिए नवीनतम 5 को चुनता है:

./gcpl.sh -c 5 -s 6.19.x -t master

जब आप सीधे Git के साथ ऐसा कर सकते हैं तो इस स्क्रिप्ट की आवश्यकता क्यों होगी? ...
code_dredd

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