इस प्रोजेक्ट के बारे में

9vcs एक वर्जन कंट्रोल सिस्टम है जिसे लेखक की Go 9p लाइब्रेरी के माध्यम से Plan 9 प्रोटोकॉल, 9P पर बनाया गया है। इसका उद्देश्य एक छोटी विश्वसनीय टीम है जो बिना किसी होस्टिंग प्लेटफॉर्म के वास्तविक वर्जन कंट्रोल चाहती है। इतिहास को स्नैपशॉट के बजाय कंटेंट-एड्रेस्ड पैच के सेट के रूप में रखा जाता है; README डिजाइन तर्क के लिए PLAN.md की ओर संकेत करता है और स्वयं को व्यावहारिक उपयोग तक सीमित रखता है। इसकी शब्दावली जानबूझकर GitHub जैसी नहीं रखी गई है: इसमें clone, push, pull, fork या pull request नहीं है, और एक चीट शीट सामान्य शब्दों को 9vcs समकक्षों से मैप करती है। आवश्यकताएं और इंस्टॉलेशन एकमात्र आवश्यकता Go 1.26.5 या उसके बाद का संस्करण है। 9vcs और वह 9p लाइब्रेरी जिस पर यह आधारित है, दोनों शुद्ध Go हैं और केवल स्टैंडर्ड लाइब्रेरी का उपयोग करते हैं, जिसमें कोई डेमन, डेटाबेस या बाहरी सेवाएं नहीं हैं। प्रीबिल्ट बाइनरीज़ Releases पेज पर linux/amd64, linux/arm64, darwin/arm64 और darwin/amd64 के लिए tar.gz आर्काइव्स के रूप में प्रकाशित की गई हैं, जिनमें से प्रत्येक में सत्यापन के लिए एक .sha256 चेकसम है; आर्काइव में बाइनरी, LICENSE और README शामिल हैं। सोर्स से बिल्ड करना cmd/9vcs के विरुद्ध एक सिंगल go build कमांड है। वैकल्पिक रूप से, कुछ इंस्टॉलर उपलब्ध हैं। सोलो वर्कफ़्लो एक डायरेक्टरी में init चलाने के बाद, status बदले हुए प्रत्येक पाथ के लिए एक लाइन प्रिंट करता है, जिसमें नए के लिए A, संशोधित के लिए M, हटाए गए के लिए D और अनसुलझे संघर्ष (unresolved conflict) के लिए U का उपयोग किया जाता है; यह केवल वही रिपोर्ट करता है जो 'डर्टी' है, न कि diff। मूव्स को रीनेम के रूप में ट्रैक नहीं किया जाता है — एक मूव की गई फ़ाइल डिलीट और ऐड के रूप में दिखाई देती है, जो इस बात से मेल खाती है कि अंतर्निहित पैच इसे कैसे स्टोर करता है। diff वर्किंग ट्री में लाइन-लेवल परिवर्तन दिखाता है, किसी अन्य बिंदु के विरुद्ध diff कर सकता है, या वर्किंग ट्री को शामिल किए बिना सीधे दो बिंदुओं की तुलना कर सकता है। log रिकॉर्ड किए गए पैच को नवीनतम पहले, लेखक, फिंगरप्रिंट या सिग्नेचर स्टेटस और प्रभावित पाथ के साथ सूचीबद्ध करता है। record एक पैच बनाता है। इसमें कोई स्टेजिंग एरिया या इंडेक्स स्टेप नहीं है: वर्किंग ट्री स्वयं स्टेजिंग एरिया है, और record इसे वर्तमान head के विरुद्ध diff करता है। ब्रांच और मर्जिंग branch सूची बनाता है, HEAD से या किसी अन्य ब्रांच या हैश से बनाता है, और checkout स्विच करता है या -b फ्लैग के साथ बनाता और स्विच करता है। मर्जिंग वास्तविक पैच-ग्राफ संघर्ष पैदा करती है — लाइन-लेवल फोर्क्स, तुलना साइडकार फ़ाइल के साथ बाइनरी संघर्ष, और मॉडिफाई/डिलीट रेस — न कि एक उथला थ्री-वे टेक्स्ट diff। एक क्लीन मर्ज record के साथ पूरा होता है। एक संघर्षपूर्ण मर्ज प्रभावित टेक्स्ट फ़ाइलों में इनलाइन संघर्ष मार्कर छोड़ता है, जबकि बाइनरी संघर्षों को तुलना के लिए पाथ और एक छोटे हैश के नाम वाली साइडकार फ़ाइल मिलती है; उपयोगकर्ता इसे एडिट करता है और फिर रिकॉर्ड करता है। एक मर्ज को रद्द (abort) किया जा सकता है, जिससे वर्किंग ट्री ठीक उसकी प्री-मर्ज स्थिति में बहाल हो जाता है और मर्ज स्टेट क्लियर हो जाता है, चाहे मर्ज merge कमांड से आया हो या apply से। इग्नोर पैटर्न एक रेपो-रूट .9vcsignore फ़ाइल .gitignore की तरह काम करती है और इसे रिकॉर्ड और साझा करने के लिए बनाया गया है। प्रति लाइन एक पैटर्न; खाली लाइनों और हैश कमेंट्स को छोड़ दिया जाता है। बिना स्लैश वाले पैटर्न किसी भी गहराई पर मैच होते हैं, स्लैश वाले पैटर्न रेपो रूट से जुड़े होते हैं, और ट्रेलिंग स्लैश मैच को वास्तविक डायरेक्टरी तक सीमित करता है। विस्मयादिबोधक चिह्न (!) के साथ निगेशन और डबल-स्टार पैटर्न स्पष्ट रूप से समर्थित नहीं हैं। इग्नोर पैटर्न केवल नई फ़ाइलों को record और diff से बाहर रखते हैं, और बाद में पैटर्न जोड़ने से पहले से रिकॉर्ड की गई फ़ाइल डिलीट नहीं दिखाई देती। टीम उपयोग प्रत्येक इंस्टॉलेशन पहले उपयोग पर एक लॉन्ग-लिव्ड Ed25519 की-पेयर जेनरेट करता है, और identity show उस फिंगरप्रिंट को प्रिंट करता है जिसे टीम के साथी एक-दूसरे को अधिकृत करने के लिए आउट-ऑफ-बैंड एक्सचेंज करते हैं। जो कोई भी साझा इतिहास होस्ट करता है वह एक पोर्ट पर serve चलाता है; सर्वर वर्तमान रेपो में .9vcs/authorized-peers को पढ़ता है, जिसमें प्रति टीम सदस्य एक फिंगरप्रिंट-और-परमिशन लाइन होती है, जहाँ अनुमतियाँ read (केवल इतिहास पुल करना), propose (रीड प्लस ऑफर्स एरिया में एक हस्ताक्षरित बंडल पोस्ट करना), और write (ब्रांच रिफ को मूव करने सहित सब कुछ) होती हैं। कोई add-collaborator कमांड नहीं है — यह केवल उस फ़ाइल को एडिट करना है — और फ़ाइल स्टार्टअप पर एक बार पढ़ी जाती है, इसलिए परिवर्तनों के लिए रीस्टार्ट की आवश्यकता होती है, जो किसी संभावित रूप से कॉम्प्रोमाइज्ड की को रद्द करते समय महत्वपूर्ण होता है। serve बिना किसी बैकग्राउंड डेमन के फोरग्राउंड में चलता है। एक नेटवर्क पुश उस ब्रांच को मूव करने से मना करता है जो वर्तमान में सर्विंग मशीन पर चेक आउट है, इसलिए होस्ट को एक अलग ब्रांच चेक आउट रखनी चाहिए या सर्विंग के लिए आरक्षित डायरेक्टरी का उपयोग करना चाहिए। एक नया टीम सदस्य init और import के साथ शुरू करता है, जिसमें एक पीयर फिंगरप्रिंट और एक होस्ट और पोर्ट प्लस ब्रांच नाम पास किया जाता है; import केवल फास्ट-फॉरवर्ड है और ब्रांच और हर पैच और ब्लॉब को पुल करता है जिस पर यह ट्रांजिटिवली निर्भर करता है। reconcile निरंतर सिंक कमांड है: यह पुल करता है यदि पीयर आगे है, पुश करता है यदि लोकल साइड आगे है, और वास्तविक विचलन (divergence) पर जो गायब है उसे फेच करता है और उपयोगकर्ता से स्थानीय रूप से चेक आउट और मर्ज करने के लिए कहता है, न कि वायर पर रिज़ॉल्व करने के लिए। दोनों कमांड स्पष्ट रूप से एक पीयर फिंगरप्रिंट को पिन कर सकते हैं, अन्यथा वे एक लोकल trust-on-first-use स्टोर का उपयोग करते हैं जो नए पते के लिए एक बार प्रॉम्प्ट करता है, ज्ञात पतों की चुपचाप जांच करता है, और अचानक बदलने वाले फिंगरप्रिंट को ज़ोर से अस्वीकार करता है। ऑफलाइन एक्सचेंज और प्रस्ताव बंडल बिना किसी रनिंग सर्वर के परिवर्तनों को ले जाते हैं: export ईमेल, चैट या रिमूवेबल मीडिया के लिए एक फ़ाइल में हस्ताक्षरित बंडल लिखता है, और प्राप्तकर्ता bundle show (साइनर, मैसेज, पैच) के साथ इसका निरीक्षण करता है, सिग्नेचर को सत्यापित करने और किसी रिफ को छुए बिना इसे स्थानीय रूप से स्टोर करने के लिए import करता है, diff के साथ समीक्षा करता है, और फिर इसे apply और record करता है। Import अपने आप कभी रिफ को मूव नहीं करता है। केवल propose अनुमति वाले पीयर offer का उपयोग करके सीधे सबमिट कर सकते हैं, जो मेंटेनर के सर्वर पर एक हस्ताक्षरित बंडल पोस्ट करता है; मेंटेनर लंबित ऑफर्स को सूचीबद्ध करता है, फेच, सत्यापित और स्थानीय रूप से स्टोर करने के लिए एक को apply करता है, इसे apply के साथ एकीकृत करता है, और इसे कतार से हटा देता है। क्योंकि ऑफर्स केवल लाइव सर्वर नेमस्पेस के अंदर मौजूद होते हैं, मेंटेनर अपने स्वयं के serve इंस्टेंस से जुड़ता है और इसलिए उसे authorized-peers फ़ाइल में अपने स्वयं के फिंगरप्रिंट की भी आवश्यकता होती है। 9sh और नेमस्पेस हैंडलिंग सामान्य रूप से रेपो को वर्तमान डायरेक्टरी से ऊपर जाकर रिज़ॉल्व किया जाता है, जैसे git में। 9sh (एक Plan 9 स्टाइल शेल) के अंदर, कमांड नाम से पहले रखा गया -C फ्लैग एक दूसरा रास्ता प्रदान करता है: यह पहले 9sh नेमस्पेस के विरुद्ध पाथ को आज़माता है — local के तहत एक रिलेटिव पाथ, या एक एब्सोल्यूट पाथ जो 9sh द्वारा बाइंड की गई किसी भी चीज़ को रिज़ॉल्व कर सकता है — इससे पहले कि वह एक लिटरल OS पाथ पर वापस जाए। 9sh सेशन के बाहर यह फ्लैग git -C की तरह व्यवहार करता है। रिकवरी दस्तावेजीकृत रिकवरी पाथ में मर्ज या apply को रद्द करना, अनकमिटेड परिवर्तनों को रिकॉर्ड करना या मैन्युअल रूप से हटाना जो चेकआउट, मर्ज या apply को ब्लॉक करते हैं, restore के साथ व्यक्तिगत पाथ को head पर उनकी रिकॉर्ड की गई स्थिति में बहाल करना (बिना रिकॉर्ड की गई स्थिति वाला पाथ हटा दिया जाता है, इसलिए रीनेम को रिवर्ट करने का मतलब दोनों पाथ का नाम देना है), और एक पीयर फिंगरप्रिंट को फिर से पिन करना जो वैध रूप से बदल गया है, शामिल हैं। प्रोजेक्ट स्टेटस README टीम के साथ 9vcs का उपयोग करने और स्वयं टूल विकसित करने के बीच अंतर करता है, जो शॉर्ट-लिव्ड ब्रांच के साथ ट्रंक-आधारित विकास का पालन करता है, एक प्रोटेक्टेड master जहाँ कोई सीधे पुश नहीं करता, मर्ज करने से पहले बिल्ड, vet, gofmt और रेस-इनेबल्ड टेस्ट को कवर करने वाला CI, केवल स्क्वैश-मर्ज और स्वचालित ब्रांच विलोपन। वर्जनिंग रिलीज़ के लिए semver का पालन करती है, वर्तमान में v0.x रेंज में है। v1.0.0 से नीचे, ऑन-डिस्क पैच और बंडल फॉर्मेट के लिए कोई कम्पैटिबिलिटी प्रॉमिस नहीं है, जो बिना माइग्रेशन पाथ के बदल सकता है; v1.0.0 से आगे, रिलीज़ फॉर्मेट के तहत रिकॉर्ड किए गए किसी भी पैच या बंडल के डिकोडेबल रहने का दावा किया गया है, जिसमें भविष्य के असंगत परिवर्तनों को वास्तविक वर्जन डिस्पैच और शिप किए गए माइग्रेशन टूलिंग द्वारा संभाला जाएगा। एक चेंजलॉग रिकॉर्ड करता है कि प्रत्येक रिलीज़ में क्या शिप किया गया है।