2012-04-16 15 views
13

धक्का दिया गया है ठीक है, मैंने थोड़ा गड़बड़ कर दी है। जाहिर है, घर पर मेरी मशीन पर, विकास शाखा अद्यतन नहीं की गई थी। मैंने एक प्रतिबद्धता और धक्का दिया। नतीजा यह था कि वास्तविक मूल/विकास शाखा को मेरी स्थानीय विकास शाखा में विलय कर दिया गया है - जिसे किसी कारण से अलग शाखाओं के रूप में माना जाता था!एक मर्ज को पूर्ववत करें जिसे

एक बात के लिए, मैं वास्तव में नहीं समझता कि यह कैसे हुआ और दूसरा, क्या मैं इसे पूर्ववत कर सकता हूं?

यह समझाने के लिए, नेटवर्क अब इस तरह दिखता है:

local-develop ---------------------------------- C*--- M - 
origin/develop --- C --- C --- C --- C --- C ---------/

क्या मैं सच में चाहते थे कि सी * मूल करने के लिए प्रतिबद्ध किया जाएगा/बजाय शाखाओं विलय की विकास।

जैसा कि मैंने कहा, यह पहले से ही धक्का दिया गया है। क्या परिवर्तनों को हटाने और जिस तरह से मैं चाहता हूं उसे प्रतिबद्ध करने का कोई तरीका है?

उदाहरण के लिए मुझे क्या करना:

git reset --hard HEAD~1 

मुझे यकीन है कि अगर यह मर्ज नाश कर देती है नहीं हूँ और मैं दो अलग अलग विकसित करता है, और फिर मर्ज नष्ट कर दिया आदि ...?

उत्तर

26

विलय धक्का पर नहीं होता है, वे git merge (अच्छी तरह से, और pull पर होते हैं लेकिन यह वास्तव में केवल विलय + विलय होता है, इसलिए विलय पर हो रहा है)। ,

<get copy from origin/develop> 
<wait around for remote's origin/develop to acquire new commits> 
git checkout develop  # get onto (local) develop branch 
<edit> 
git commit -m message  # create some new commit(s) 
git push origin develop # attempt to push -- but this fails! 
git pull 

ऐसा नहीं है कि अंतिम चरण बनाता है कि मर्ज प्रतिबद्ध (M ऊपर) है, क्योंकि pull मतलब है fetch (उन सभी नए प्रतिबद्ध है कि अब कर रहे हैं मिलता है:

यह अधिक संभावना है कि आप कुछ इस तरह किया था लगता है origin/develop), फिर merge (अपना स्थानीय develop लें और अपने प्रतिबद्धता को उन नए लोगों के साथ विलय करें)।

आप नहीं git push एड इस नई परिणाम है, तो दूरस्थ रेपो या तो अपने स्थानीय प्रतिबद्ध की, जिन्हें आप लेबल लगाया था C* और M जरूरत नहीं है। इस मामले में, आप अच्छे आकार में हैं! (आप git fetch चलाकर जांच कर सकते हैं फिर से सुनिश्चित करें कि आपके स्थानीय रेपो के origin/develop मैचों दूरदराज में एक है, तो git log origin/develop कर उस में क्या देखने के लिए बनाने के लिए।)

यह दो पूरी तरह अलग Git रेपोस यहाँ हैं कि याद करने के लिए मदद मिल सकती है : तुम्हारा सामान, तुम्हारा सामान; और जिसे आप origin पर कॉल कर रहे हैं। (चलो उस मशीन को X पर कॉल करें।) यदि आप X पर लॉग ऑन करना चाहते हैं, तो इसका अपना अलग प्रतिबद्ध इतिहास और शाखा नाम और इसी तरह से है। वहां पर, आप निर्देशिका को रेपो में बदल देंगे, git log -1 develop चलाएं, और देखें कि उस शाखा की नोक पर क्या है।

अब अगर आप X से लॉग आउट करते हैं और अपनी मशीन पर वापस आते हैं, तो आप git log -1 origin/develop चला सकते हैं। यदि X पर आपने जो देखा है, वही है, तो get fetch में अपडेट करने के लिए कुछ भी नहीं है, क्योंकि git fetch प्रभाव में (लेकिन अधिक कुशलता से) है, X पर लॉग ऑन करें और develop में क्या देखें। X में कुछ भी है जो आपके पास origin/develop में नहीं है, fetch लाता है और origin/develop पर जोड़ता है।अब आप X के साथ समन्वयित हैं। X में आपकी सामग्री नहीं है, लेकिन आपके पास उनका है।

आप तो एक merge (pull से गर्भित एक सहित), Git कर रही है, किसी मर्ज के लिए प्रतिबद्ध है, तो यह करने के लिए, बनाने है होगा ... के अतिरिक्त कदम उठाने लेकिन यह सब में अपने रेपो है, पर अगर इस मामले में शाखा की नोक (अभी भी develop)। जब तक आप धक्का इस मर्ज के लिए प्रतिबद्ध X (या X पर किसी को आपसे आपके प्रतिबद्ध खींचती है लेकिन अब :-) के लिए कि उपेक्षा करते हैं) के लिए, X यह नहीं होगा।

वैसे भी, जब तक कि दूरदराज के (X यहाँ) अपने मर्ज के लिए प्रतिबद्ध नहीं है, आप के लिए सुनहरा कर रहे हैं। चूंकि वे नहीं हैं, कोई और भी नहीं करता है। आप अपने लिए प्रतिबद्ध (C*) origin/develop के शीर्ष पर डाल करने के लिए अपने develop शाखा के एक rebase कर सकते हैं। यह विलय प्रतिबद्धता से छुटकारा पायेगा (M), और फिर आप origin/develop पर एक सरल फास्ट-फॉरवर्ड को दबा सकते हैं।

तो Xकरता है अपने मर्ज प्रतिबद्ध-यानी, अगर आप pull एड आप के बाद धक्का दिया और मिल गया है कि मर्ज-तो आप (कुछ हद तक) क्योंकि शायद अन्य लोगों X के लिए उपयोग किया है और अब प्रयोग कर रहे हैं समस्या आ रही आपका विलय प्रतिबद्ध X पर रिपो को वापस रोल करना संभव है, जिस तरह से आप git reset और git rebase के साथ अपने स्वयं के रेपो में ऐसा कर सकते हैं और इसी तरह, लेकिन यह आमतौर पर एक बुरा विचार है।


अब, मान लीजिए आप वास्तव में है अन्य रेपो (मशीन X पर) करने के लिए धक्का दिया है, लेकिन आप पूरी तरह से सुनिश्चित और कोई नहीं अभी तक अपने बदलाव देखा गया है कर रहे हैं, और आप निश्चित रूप से उन्हें पुनर्स्थापित करने के लिए जा रहे हैं, बजाय वापस लाने में उन्हें ("fessing up" की मात्रा को वापस लेना और पीछे स्क्रू-रिकॉर्ड छोड़ना, जो हर किसी को आसानी से इसे पुनर्प्राप्त करने देता है, लेकिन उन्हें आपकी त्रुटि देखने देता है :-))।

यहाँ चाल है: आप पहली बार कहना है कि, जहां सी 7 पहले से आपके बहुत ही चित्र में है "शाखा devel की नोक सी 7 के लिए प्रतिबद्ध है" मशीन एक्स के रेपो प्राप्त करने की आवश्यकता है, सिर्फ इतना है कि फिर से गिने मैं प्रत्येक प्रतिबद्धता को अलग-अलग नाम दे सकते हैं:

--------------------------- C*--- M 
--- C4 --- C5 --- C6 --- C7 ----/

तो, आप यह कैसे कर सकते हैं? खैर, एक तरीका है X, cd रेपो में लॉग इन करना है (भले ही यह --bare है), और वहां git update-ref का उपयोग करें। आइए मान लें कि सी 7 के लिए SHA1 वास्तव में 50db850 है (जैसा कि "गिट लॉग" द्वारा दिखाया गया है)। तो फिर तुम ऐसा कर सकता है:

localhost$ ssh X 
X$ cd /path/to/repo.git 
X$ git update-ref refs/heads/develop 50db850 

लेकिन अगर आप X में प्रवेश नहीं कर सकते हैं, या यहां तक ​​कि बस नहीं है, तो आप git push -f साथ भी ऐसा ही कर सकते हैं। (यह अन्य लाभ हैं: विशेष रूप से, अपने Git रेपो पता चल जाएगा कि origin/develop, rewound किया गया है एक बार push -f सफलतापूर्वक पूरा करती है।) बस एक स्थानीय शाखा की नोक सही की ओर इशारा करते प्रतिबद्ध बनाने:

localhost$ git branch resetter 50db850 
localhost$ git log resetter   # make sure it looks right 
... 
localhost$ git push -f origin resetter:develop 
Total 0 (delta 0), reused 0 (delta 0) 
To ssh://[redacted] 
+ 21011c9...50db850 resetter -> develop (forced update) 
localhost$ git branch -d resetter # we don't need it anymore 

एक बार ऐसा करने के बाद, मशीन एक्स उस स्थिति में वापस आ गया है जिसे आप चाहते थे, और आप आगे बढ़ सकते हैं जैसे कि आपने कभी मर्ज को धक्का नहीं दिया है जिसे आप पसंद नहीं करते थे।

नोट है कि जब आप push -f करते हैं, अगर किसी और को M के शीर्ष पर नए प्रतिबद्ध बना दिया है, उन भी अदृश्य हो जाएगा (तकनीकी रूप से वे वहाँ में अब भी कर रहे हैं, अपने मर्ज के साथ प्रतिबद्ध है, लेकिन वे कर रहे हैं " lost+foundgit fsck --lost-found की भावना में खो गया ", और कुछ महीनों के बाद वे वास्तव में हमेशा के लिए चले जाएंगे)।

बार बहुत महत्वपूर्ण: "साझा रेपो के रोलबैक" इस तरह की है कि साझा रेपो के अन्य उपयोगकर्ताओं के लिए एक बड़ा दर्द है तो वास्तव में यकीन है कि यह ठीक है इससे पहले कि आप यह कर सकता है।


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

मुझे लगता है कि यहाँ सही दूर ले सबक है: नज़र (git log) इससे पहले कि आप धक्का यकीन है कि तुम किस बारे में पुश करने के लिए कर रहे हैं क्या आप को पुश करने का इरादा है कि बनाने के लिए।

या, आसान और सरल: git ls-remote। रिमोट के पास यह देखने के लिए यह fetch प्रोटोकॉल कोड का उपयोग करता है। लेकिन यह उस विषय को छुपाता है जो मैं यहां जा रहा हूं, जो है: रिमोट सिर्फ आपके जैसा ही रेपो है!

आगामी गिट संस्करण 2 रिलीज़ में नई "सुरक्षा विशेषताएं" हैं जो git push -f के साथ उपयोग योग्य होंगी। लेकिन वे अभी तक बाहर नहीं हैं, इसलिए यह आपकी मदद नहीं करता है। जब मैं उन्हें नोट करूँगा, तो मैं इसे बाद में फिर से संपादित कर दूंगा। तब तक, वास्तव में यहां सावधान रहें: इस बिंदु पर, आप साझा भंडार में नई सामग्री को धक्का देने की कोशिश कर रहे किसी और के खिलाफ दौड़ रहे हैं।

आप इसे कच्चे SHA-1 आईडी द्वारा भी कर सकते हैं। हालांकि शाखा नाम का नाम पंक्ति में कई बार सही टाइप करना आसान है।

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

+0

वाह, धन्यवाद इस व्यापक उत्तर के लिए एक बहुत। अनजाने में मैंने इसे एक्स पर धक्का दिया है। चूंकि मुझे यकीन है कि किसी और ने एक नया fetch नहीं बनाया है, मैं सोच रहा था कि क्या मैं इन परिवर्तनों को पूर्ववत कर सकता हूं। एक बात मैं वास्तव में इस बारे में स्पष्ट नहीं हूं: अगर मैं दो कदम पीछे रीसेट करता हूं, तो क्या मैं शाखाओं में से एक या दोनों के साथ छोड़ दिया गया हूं? – dmeu

+0

ठीक है, ठीक है, धक्का देने के बाद, यदि आप * वास्तव में सुनिश्चित हैं * :-) ... आप जो करना चाहते हैं वह एक्स को रिवाइंड करने के लिए शाखा 'डेवेल' की नोक का विचार प्राप्त करना है। मुझे जवाब संपादित करने दो ... – torek

+2

ओह, और: यदि आप "दो चरणों को वापस ले जाने" के लिए हेड ~ 2' रीसेट करते हैं, तो यह वास्तव में गिट को बताने के लिए है: "उस शाखा की नोक सेट करें जो मैं अभी कर रहा हूं" - संभवतः यह आपका ' हेड ~ 2 "देखकर आप जो प्रतिबद्धता आईडी प्राप्त करते हैं उसे विकसित करें। यदि आप देखना चाहते हैं कि क्या प्रतिबद्ध है, तो 'गिट शो हेड ~ 2' पहले। यदि आप उपर्युक्त अपने आरेख से 'एम' प्रतिबद्ध हैं, तो 'HEAD ~ 2'' एम ~ 2' है जो' एम' और 'सी *' दोनों पर बैक अप करता है। शायद आप जो चाहते हैं वह नहीं। – torek

संबंधित मुद्दे