रिबेस के बाद ब्रांच को पुश नहीं कर सकते


131

हम गिट का उपयोग करते हैं और एक मास्टर शाखा और डेवलपर शाखाएं हैं। मुझे एक नई सुविधा जोड़ने की आवश्यकता है और फिर कमिट को मास्टर करने के लिए रिबेट करें, फिर मास्टर को CI सर्वर पर धकेलें।

समस्या यह है कि अगर मेरे पास रिबास के दौरान संघर्ष होता है, तो मैं रिबास पूरा होने के बाद अपनी दूरस्थ डेवलपर शाखा (जीथब पर) को धक्का नहीं दे सकता, जब तक कि मैं अपनी दूरस्थ शाखा नहीं खींचता। इससे डुप्लिकेट कमिट होता है। जब कोई टकराव नहीं होता है, तो उम्मीद के मुताबिक काम करता है।

प्रश्न: रिबेस और संघर्ष रिज़ॉल्यूशन के बाद, मैं डुप्लिकेट कमिट्स बनाए बिना अपनी स्थानीय और दूरस्थ डेवलपर शाखाओं को कैसे सिंक करूं

सेट अप:

// master branch is the main branch
git checkout master
git checkout -b myNewFeature

// I will work on this at work and at home
git push origin myNewFeature

// work work work on myNewFeature
// master branch has been updated and will conflict with myNewFeature
git pull --rebase origin master

// we have conflicts
// solve conflict
git rebase --continue

//repeat until rebase is complete
git push origin myNewFeature

//ERROR
error: failed to push some refs to 'git@github.com:ariklevy/dropLocker.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

// do what git says and pull
git pull origin myNewFeature

git push origin myNewFeature

// Now I have duplicate commits on the remote branch myNewFeature

संपादित करें

तो ऐसा लगता है कि यह वर्कफ़्लो को तोड़ देगा:

developer1 myNewFeature पर काम कर रहा है developer2 अपने निवेचर पर काम कर रहा है, दोनों मुख्य शाखा के रूप में मास्टर का उपयोग करते हैं

डेवलपर 2 ने myNewFeature को अपनेNewFeature में विलय कर दिया है

डेवलपर 1 विद्रोह, संघर्षों को हल करता है, फिर myNewFeature के लिए दूरस्थ शाखा को बल देता है

कुछ दिनों बाद, डेवलपर 2, myNewFeature को फिर से अपनेNewFeature में मिला लेता है

क्या इससे अन्य डेवलपर डेवलपर 1 से नफरत करेंगे?


समाधान नहीं बल्कि सिर्फ एक विचार। कौन है we? क्या आप सिर्फ आप से ज्यादा की टीम में हैं? theyकहते हैं (जो लोग मुझसे अधिक जानते हैं) कि यदि आप अपना कोड साझा करते हैं तो आप का उपयोग नहीं करना चाहिए rebase। आप क्यों नहीं बस कर नहीं कर रहे हैं git pullऔर git merge?
एडम

क्षमा करें, हम = विकास दल
मैट

1
हां, जब आप कोड साझा कर रहे हों तो शायद रिबास न हो। इससे आपको उन चीज़ों को करना पड़ सकता है जैसे नीचे सूचीबद्ध ( forceधक्का)
एडमटी

ओह क्षमा करें, जब वे कहते हैं rewriting history, कि एकrebase
एडमट

जैसा कि उन्होंने कहा कि अपनी खुद की एक विकास शाखा है ताकि कोई समस्या न हो जब तक कि किसी को उस में विलय करने की उम्मीद न हो।
Learath2

जवाबों:


93

सबसे पहले, आप और आप जिनके साथ काम कर रहे हैं, वे इस बात पर सहमत होने की जरूरत है कि साझा विकास के लिए एक विषय / देवल शाखा है या सिर्फ अपना। अन्य डेवलपर्स को पता है कि मेरी विकास शाखाओं में विलय नहीं होगा क्योंकि वे किसी भी समय बगावत करेंगे। आमतौर पर वर्कफ़्लो इस प्रकार है:

o-----o-----o-----o-----o-----o       master
 \
   o-----o-----o                      devel0
                \
                  o-----o-----o       devel1

फिर रिमोट के साथ अद्यतित रहने के लिए मैं निम्नलिखित कार्य करूंगा:

 git fetch origin
 git checkout master
 git merge --ff origin/master

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

फिर जब रिमोट में परिवर्तन होता है और मैं तेजी से नवीनतम री-अप करने के लिए अग्रसर होता हूं:

git checkout devel0
git rebase master
git push -f origin devel0

इसके बाद अन्य डेवलपर्स को पता है कि उन्हें अपनी नवीनतम से हटकर अपनी देवल शाखाओं को फिर से बनाने की आवश्यकता होगी:

git fetch <remote>
git checkout devel1
git rebase <remote>/devel0

जो बहुत क्लीनर इतिहास में परिणाम:

o-----o                                 master
       \
         o-----o-----o                  devel0
                      \
                        o-----o-----o   devel1

आगे और पीछे अपने मर्ज में नहीं मिलाएँ। न केवल यह डुप्लिकेट कमिट बनाता है और इतिहास का पालन करना असंभव बनाता है, एक विशिष्ट परिवर्तन से प्रतिगमन खोजना असंभव हो जाता है (यही कारण है कि आप पहली बार में संस्करण नियंत्रण का उपयोग कर रहे हैं, ठीक है?)। आपके द्वारा की जा रही समस्या सिर्फ ऐसा करने का परिणाम है।

यह भी लगता है कि अन्य डेवलपर्स आपकी डेवेल शाखाओं के लिए कमिट कर रहे हैं। क्या आप इसकी पुष्टि कर सकते हैं?

विलय करने का एकमात्र समय तब होता है जब आपकी विषय शाखा को स्वीकार करने के लिए तैयार हो master

एक और बात। यदि कई डेवलपर्स एक ही रिपॉजिटरी के लिए प्रतिबद्ध हैं, तो आप सभी को डेवलपर्स डेवेल शाखाओं के बीच अंतर करने के लिए नामित शाखाओं पर विचार करना चाहिए। उदाहरण के लिए:

git branch 'my-name/devel-branch'

इसलिए सभी डेवलपर्स विषय शाखाएं अपने स्वयं के नेस्टेड सेट के भीतर रहती हैं।


1
"इसके अलावा, ऐसा लगता है कि अन्य डेवलपर्स आपकी डेवेल शाखाओं पर कमिट कर रहे हैं। क्या आप इसकी पुष्टि कर सकते हैं?" हाँ, वे हैं ...
मैट

आपने एक और मुद्दा मेरे ध्यान में भी लाया है। ऑफिस और घर के बीच काम करना। मैं दोनों स्थानों पर विलय करता हूं और दिन के अंत में मैं धक्का देता हूं ताकि मैं जहां से छोड़ा था वहां से उठा सकूं। फिर जब यह रिबेट करने का समय होता है, तो वे सभी हंगामा भ्रम पैदा करते हैं। मुझे अपनी शाखाओं को एक शाखा के रूप में मानने और पुनर्व्यवस्थित करने की आवश्यकता है
मैट

@ मैट हाँ, उन दो समस्याओं वास्तव में अपने कार्यप्रवाह पेंच होगा। पहले के लिए, मैं अन्य डेवलपर्स से संवाद करूँगा कि केवल स्वामी एक नामित ब्रांचेड (जैसे 'मैट / डेवेल') के लिए प्रतिबद्ध हो सकते हैं। IMHO, कोई भी दो डेवलपर्स एक ही शाखा के लिए प्रतिबद्ध नहीं होना चाहिए। बस भ्रम पैदा करता है। बाद के लिए, रिबासिंग और फोर्स पुशिंग को दो स्थानों को अप-टू-डेट रखना चाहिए।
ट्रेवर नॉरिस

बहुत बढ़िया जवाब। मेरा एक प्रश्न है, --forceजब आप झंडा का इस्तेमाल करते हैं तो आप क्यों करते हैं git push -f origin devel0?
नोबिता

2
@ नोबिता जब git pushकोई तेज़-फॉरवर्ड नहीं कर सकता (यानी शा इतिहास ऊपर से मेल नहीं खाता) तो आपको नए इतिहास से उत्पन्न नए इतिहास के साथ पिछले इतिहास को अधिलेखित करने के लिए जोर लगाना चाहिए git rebase
ट्रेवर नॉरिस

50

आपको पुश को मजबूर करने की आवश्यकता है क्योंकि आपने कमिट्स को आगे बढ़ाया है, लाइन गिट आपको शाखा की नोक पर कॉमेट्स जोड़ने की उम्मीद कर रहा है। git push -f origin myNewFeatureआपकी समस्या को ठीक करेगा।

युक्ति: ऊपर बल धक्का का एक वैध उपयोग है। कभी भी सार्वजनिक रूप से सुलभ रिपॉजिटरी पर इतिहास को दोबारा न लिखें या बहुत सारे लोग आपसे नफरत करेंगे।


1
वर्कफ़्लो को बनाए रखने के लिए मुझे यह सबसे इष्टतम तरीका लगता है।
सैयद प्रॉम

1
धन्यवाद दोस्त। मैंने इस आदेश का उपयोग अपनी विद्रोही स्थानीय शाखा को उसी दूरस्थ शाखा के लिए बाध्य करने के लिए किया।
वीई

11
उपयोग करने git push --force-with-leaseकी तुलना में उपयोग करना अधिक सुरक्षित हैgit push --force

git push --force-with-lease origin HEAD- यह मानते हुए कि आपकी लक्ष्य शाखा पहले ही चेकआउट हो चुकी है
लुकासी सेर्गी जू

31

यहां ध्यान रखने वाली मुख्य बात यह है कि पर्दे के पीछे क्या पुल और रिबास हो रहा है।

एक पुल मूल रूप से दो काम करेगा: भ्रूण और मर्ज। जब आप शामिल करते हैं - क्रेबेज यह मर्ज के बजाय एक रिबास करेगा।

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

(यह बताता है कि रिबेज़ करते समय आपको एक से अधिक विरोध प्रस्ताव प्राप्त हो सकते हैं। एक संघर्ष रिज़ॉल्यूशन बनाम आप एक मर्ज के साथ प्राप्त कर सकते हैं। आपके पास EACH प्रतिबद्ध पर एक संघर्ष को हल करने का अवसर है जो अन्यथा आपके कमिट्स को संरक्षित करने के लिए छूट दी जा रही है। )

आप दूरस्थ शाखाओं में बगावत के बदलावों को आगे नहीं बढ़ाना चाहते क्योंकि यह इतिहास को फिर से लिखना है। Ofcoarse, कभी थोड़ा मजबूत नहीं होता क्योंकि लगभग हमेशा अपवाद होते हैं। उदाहरण के लिए विशिष्ट वातावरण पर काम करने के लिए आपके स्थानीय रिपॉजिटरी के दूरस्थ संस्करण को बनाए रखने की आवश्यकता है।

इसके लिए आपको बल का उपयोग करते हुए कई बार विद्रोही परिवर्तनों को धकेलना होगा:

git push -f origin newfeature

या कुछ मामलों में आपके व्यवस्थापक ने बल देने की क्षमता को हटा दिया हो सकता है इसलिए आपको हटाना और पुन: निर्माण करना होगा:

git push origin :newfeature
git push origin newfeature

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

याद रखें कि आप git की GC पर लगभग हमेशा लाभ उठा सकते हैं:

git reflog

यह एक बड़ा जीवन रक्षक है क्योंकि आप अपने सभी रिबास / संघर्ष प्रबंधन में खो जाने पर अधिक स्थिर स्थिति में वापस आ सकते हैं।


ऊपर डिलीट और रीक्रिएट विकल्प ने मेरे लिए अच्छा काम किया। मेरे रेपो पर कोई जबरन अनुमति नहीं!
साइमन होम्स

2

आपको एक मजबूर धक्का यानी प्रदर्शन करने की जरूरत है git push -f origin myNewFeature

ओह, और आप बेहतर यह सुनिश्चित करते हैं कि लोग आपकी देव शाखा पर कुछ भी आधार नहीं बनाते हैं - आमतौर पर आप उन शाखाओं को प्रकाशित करने के लिए नहीं होते हैं जहाँ आप इतिहास को फिर से लिख रहे हैं (या एक बार प्रकाशित होने के बाद इतिहास को फिर से लिखना नहीं चाहते हैं)। एक तरह से शाखा नाम का उपयोग किया जाएगा wip/myNewFeatureऔर फिर यह उल्लेख wipकिया जाएगा कि शाखाओं को समय-समय पर मास्टर करने के लिए छूट दी जाएगी।


उपयोग करने git push --force-with-leaseकी तुलना में उपयोग करना अधिक सुरक्षित हैgit push --force

@MrCholo लोग इसे तब तक इस्तेमाल करना शुरू नहीं करेंगे जब तक git इसके लिए एक छोटा विकल्प नहीं जोड़ता, जैसे -fकि एक सामान्य मजबूर धक्का के लिए :)
ThiefMaster

हा हाँ, मैंने इसे एक स्वचालित स्क्रिप्ट में प्रयोग किया था

2

सामान्य उत्तर जो पहले ही दिया जा चुका है - उपयोग करने के लिए git push -f origin myNewFeature विद्रोही परिवर्तनों को धकेलने के - एक अच्छी शुरुआत है। मैं इस जवाब को संपादित करने के बारे में लिख रहा हूं कि क्या यह आपके वर्कफ़्लो को तोड़ देगा।

यदि हम मानते हैं कि आप git pull --rebase ...रिमोट शाखा पर एक बल-पुश द्वारा उपयोग (या उस पर कुछ भिन्नता) करने जा रहे हैं , तो आपके उदाहरण में वर्कफ़्लो को तोड़ने वाली चीज़ डेवलपर 2 में विलय myNewFeatureहो रही है hisNewFeature। यह समझ में आता है कि जब तक कोई अन्य उस शाखा पर काम नहीं कर रहा है, तब तक अपनी स्वयं की सुविधा शाखा को पुन: प्राप्त करने में सक्षम होने के लिए, इसलिए आपको शाखा क्षेत्र का सीमांकन करने के लिए नियमों की आवश्यकता है।

आप इसके चारों ओर एक) एक नियम की स्थापना करके प्राप्त कर सकते हैं जिसे आप केवल masterएक developशाखा बनाते हैं, या ख) एक सामूहिक शाखा बनाते हैं , जिस पर आप अपनी myNewFeatureशाखा को आधार बनाते हैं , और एक नियम स्थापित करते हैं जिसे आप केवल कभी भी विलय करते हैं developmasterतब केवल मील के पत्थर या रिलीज के लिए आरक्षित किया जाएगा (या हालांकि आप इसे स्थापित करना चाहते हैं), और developवह होगा जहां आप प्रत्येक सुविधा को धक्का देते हैं जब यह अन्य फीचर शाखाओं में एकीकृत होने के लिए तैयार होता है।

मेरा मानना ​​है कि इसे Gitflow वर्कफ़्लो का सरलीकृत संस्करण माना जा सकता है।


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