version control - Mercurial: एकाधिक रिपोजिटरी बनाम शाखाओं नामित




version-control branch (4)

हम वर्तमान में अपेक्षाकृत बड़े कोडबेस पर उपversण का उपयोग कर रहे हैं। प्रत्येक रिलीज को अपनी शाखा मिलती है, और ट्रंक के खिलाफ फिक्स का प्रदर्शन किया जाता है और svnmerge.py का उपयोग करके रिलीज शाखाओं में माइग्रेट किया जाता है

मेरा मानना ​​है कि समय बेहतर स्रोत नियंत्रण में आगे बढ़ने आया है, और मैं थोड़ी देर के लिए Mercurial के साथ टकरा रहा हूँ।

हालांकि Mercurial का उपयोग कर ऐसी रिलीज संरचना के प्रबंधन के दो स्कूल होने लगते हैं। या तो प्रत्येक रिलीज को अपना खुद का रेपो मिल जाता है, और रिलीज शाखा के खिलाफ फिक्स किए जाते हैं और मुख्य शाखा (और किसी अन्य नई रिलीज शाखाओं) में धकेल जाते हैं। या एक ही भंडार (या एकाधिक मिलान प्रतियों) में नामित शाखाओं का उपयोग करते हैं।

किसी भी मामले में ऐसा लगता है कि मैं रिलीज शाखाओं में शामिल करने के लिए चेरीपिक परिवर्तनों में प्रत्यारोपण जैसे कुछ का उपयोग कर रहा हूं।

मैं आपसे पूछता हूं; प्रत्येक दृष्टिकोण की सापेक्ष योग्यता क्या हैं?


आपको दोनों करना चाहिए।

@ नॉर्मन से स्वीकृत उत्तर के साथ शुरू करें: प्रति रिलीज एक नामित शाखा के साथ एक भंडार का उपयोग करें।

फिर, इमारत और परीक्षण के लिए प्रति रिलीज शाखा में एक क्लोन है।

एक महत्वपूर्ण नोट यह है कि यदि आप एकाधिक भंडारों का उपयोग करते हैं, तो आपको उनके बीच परिवर्तनों को स्थानांतरित करने के लिए transplant का उपयोग करना चाहिए क्योंकि 1) यह हैश बदलता है, और 2) यह उन बग्स को पेश कर सकता है जो परिवर्तन के बीच विरोधाभासी परिवर्तन करते समय पता लगाना बहुत मुश्किल हैं आप प्रत्यारोपण और लक्ष्य शाखा। आप इसके बजाए सामान्य विलय करना चाहते हैं (और बिना किसी झगड़े के: हमेशा विलय का निरीक्षण करें), जिसके परिणामस्वरूप @mg ने अपने उत्तर के अंत में क्या कहा होगा:

ग्राफ अलग दिख सकता है, लेकिन इसकी एक ही संरचना है और अंतिम परिणाम वही है।

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

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

लेकिन फिर भी आपको एक क्लोन प्रति शाखा / रिलीज को बनाए रखने की आवश्यकता है जिसे आपको बनाने और परीक्षण करने की आवश्यकता है। यह छोटा है क्योंकि आप hg clone <main repo>#<branch> <branch repo> , और उसके बाद शाखा रेपो में खींचें केवल उस शाखा पर नए बदलावों को खींचेंगे (साथ ही पूर्व शाखाओं पर पूर्वजों के परिवर्तन जो विलय किए गए थे)।

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

इस सेटअप के लिए यहां @ एमजी का उदाहरण सुनाया गया है। प्रस्थान बिंदू:

[a] - [b]

रिलीज संस्करण के लिए नामित शाखा बनाएं, "1.0" कहें, जब आप अल्फा रिलीज प्राप्त करते हैं। Commit बग फिक्स इस पर:

[a] - [b] ------------------ [m1]
         \                 /
          (1.0) - [x] - [y]

(1.0) वास्तविक परिवर्तन नहीं है क्योंकि नामित शाखा तब तक मौजूद नहीं है जब तक आप प्रतिबद्ध नहीं होते। (आप एक छोटी सी प्रतिबद्धता कर सकते हैं, जैसे एक टैग जोड़ने, यह सुनिश्चित करने के लिए कि नामित शाखाएं ठीक तरह से बनाई गई हैं।)

मर्ज [m1] इस सेटअप की कुंजी है। एक डेवलपर रिपोजिटरी के विपरीत जहां असीमित संख्या में सिर हो सकते हैं, आप अपने मुख्य रेपो में कई सिर नहीं लेना चाहते हैं (पुरानी, ​​मृत रिलीज शाखा को छोड़कर जैसा कि पहले उल्लेख किया गया है)। इसलिए जब भी आपके पास रिलीज शाखाओं पर नए बदलाव होते हैं, तो आपको उन्हें तुरंत डिफ़ॉल्ट शाखा (या बाद में रिलीज शाखा) में विलय करना होगा। यह गारंटी देता है कि एक रिलीज में किसी भी बग फिक्स को बाद में रिलीज़ में भी शामिल किया गया है।

इस बीच अगली रिलीज की ओर डिफ़ॉल्ट शाखा पर विकास जारी है:

          ------- [c] - [d]
         /
[a] - [b] ------------------ [m1]
         \                 /
          (1.0) - [x] - [y]

और सामान्य रूप से, आपको डिफ़ॉल्ट शाखा पर दो सिर मर्ज करने की आवश्यकता होती है:

          ------- [c] - [d] -------
         /                         \
[a] - [b] ------------------ [m1] - [m2]
         \                 /
          (1.0) - [x] - [y]

और यह 1.0 शाखा क्लोन है:

[a] - [b] - (1.0) - [x] - [y]

अब यह अगली रिलीज शाखा जोड़ने का एक अभ्यास है। यदि यह 2.0 है तो यह निश्चित रूप से डिफ़ॉल्ट रूप से शाखा बंद कर देगा। यदि यह 1.1 है तो आप 1.0 या डिफ़ॉल्ट को बंद करना चुन सकते हैं। भले ही, 1.0 पर कोई भी नया परिवर्तन पहली शाखा में विलय किया जाना चाहिए, फिर डिफ़ॉल्ट रूप से। यदि कोई संघर्ष नहीं होता है, तो यह स्वचालित रूप से किया जा सकता है, जिसके परिणामस्वरूप केवल खाली विलय होता है।

मुझे उम्मीद है कि उदाहरण मेरे पिछले अंक स्पष्ट करता है। संक्षेप में, इस दृष्टिकोण के फायदे हैं:

  1. एकल आधिकारिक भंडार जिसमें पूर्ण परिवर्तन और संस्करण इतिहास शामिल है।
  2. स्पष्ट और सरलीकृत रिलीज प्रबंधन।
  3. डेवलपर्स और इंटीग्रेटर के लिए वर्कफ़्लो साफ़ करें और सरलीकृत करें।
  4. वर्कफ़्लो पुनरावृत्तियों (कोड समीक्षा) और स्वचालन (स्वचालित खाली विलय) की सुविधा प्रदान करें।

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


जहां तक ​​मुझे पता है, बड़ा अंतर, कुछ ऐसा है जो आपने पहले ही कहा है: नाम ब्रांचेड एक ही भंडार में हैं। नामित शाखाओं में सब कुछ एक ही स्थान पर आसान है। अलग-अलग रिपोज़ छोटे और चारों ओर स्थानांतरित करने में आसान होते हैं। इस पर विचार के दो स्कूल इस कारण हैं कि कोई स्पष्ट विजेता नहीं है। जो भी पक्ष के तर्क आपको सबसे ज्यादा समझते हैं वह शायद वह है जिसके साथ आपको जाना चाहिए, क्योंकि ऐसा लगता है कि उनका पर्यावरण आपके जैसा ही है।


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


मैं वास्तव में संस्करणों के लिए नामित शाखाओं का उपयोग करने के खिलाफ सलाह देंगे। यह वास्तव में टैग के लिए क्या हैं। नामित शाखाएं एक stable शाखा की तरह लंबे समय तक चलने वाले मोड़ों के लिए हैं।

तो टैग का उपयोग क्यों न करें? एक मूल उदाहरण:

  • विकास एक शाखा पर होता है
  • जब भी एक रिलीज बनाया जाता है, तो आप इसे तदनुसार टैग करते हैं
  • विकास वहां से जारी है
  • यदि आपके पास किसी निश्चित रिलीज में ठीक करने के लिए कुछ बग हैं (या जो कुछ भी), तो आप बस इसके टैग पर अपडेट करें, अपने बदलाव करें और प्रतिबद्ध करें

इससे default शाखा, उर्फ ​​पर एक नया, अनाम नाम बनाया जाएगा। एक अज्ञात शाखा, जो एचजी में पूरी तरह ठीक है। फिर आप किसी भी बिंदु पर विलय कर सकते हैं बगफिक्स मुख्य विकास ट्रैक में वापस आ जाता है। नामित शाखाओं की कोई ज़रूरत नहीं है।







dvcs