पाठ 21 · इतिहास और एकीकरण
मर्ज बनाम रीबेस: ग्राफ़ के साथ चुनें
एक ही विचलन की दो समान प्रतियों से मर्ज और रीबेस चलाएं, दो ग्राफ़, माता-पिता और फ़ाइल पेड़ों की तुलना करें, और एक नियम सीखें जो उनके बीच निर्णय लेता है: और किसके पास पहले से ही आपकी प्रतिबद्धताएं हैं।
- स्तर: इंटरमीडिएट
- 11 मिनट पढ़ा
- 6 मिनट का वीडियो
- अद्यतन किया गया
- इस पाठ से पहले: अलग-अलग इतिहास वाली शाखाओं को मिलाएँ, तेजी से आगे बढ़ने वाले मर्ज को समझें, अप्रकाशित कार्य को नए आधार पर पुनः आधार बनाएँ
प्रगति इस ब्राउज़र में सहेजी गई.
चलाने से YouTube से वीडियो लोड होता है (गोपनीयता-उन्नत मोड)।
आप क्या सीखेंगे
- समान प्रतियों से मर्ज और रीबेस प्रारंभ करें, ताकि तुलना निष्पक्ष हो।
- एक मर्ज कमिट के दो पैरेंट और एक पुनर्आधारित कमिट के एकल नए पैरेंट को पढ़ें।
- बताएं कि क्यों दो प्रतियां एक ही फाइल के साथ समाप्त हो सकती हैं और फिर भी उनका इतिहास अलग-अलग हो सकता है।
- एक नियम से चुनें: केवल वही प्रतिबद्धता दोबारा लिखें जो किसी और ने नहीं की है।
शुरू करने से पहले
आपको पाठ 20 से विचलन की दो अलग-अलग प्रतियों की आवश्यकता है, जिनका नाम gittree-merge और gittree-rebase है। प्रत्येक प्रतिलिपि में शाखा feature/signup-form आपकी एक प्रतिबद्धता रखती है (इसे एस कहें), शाखा updated-main एक अलग प्रतिबद्धता रखती है (इसे एन कहें), दोनों एक ही प्रतिबद्धता एम से शुरू होती हैं, और rescue/signup-before-rebase एस पर अंक रखती हैं। विषय शाखा की जांच की जाती है और कार्य वृक्ष साफ है। पहले के परिणाम से दूसरी प्रति न बनाएं।
Everything here is local and on the Free plan (GitTree asks you to sign in): no hosting account, no provider, no internet. Every identity is fictional (example.com), and you should never run this lesson inside a real project.
परिवर्तन GitTree या मूल Git कमांड के साथ करें, दोनों एक ही प्रतिलिपि में नहीं। बाद में परिणाम पढ़ना हमेशा सुरक्षित होता है। मेनू लेबल 2.0 की अपनी स्ट्रिंग्स से आते हैं; मूल कमांड Git 2.43 के साथ डिस्पोजेबल प्रतियों में चलाए गए थे। GitTree चरण macOS, Windows या Linux पर नहीं चलाए गए थे; ऐप के शॉर्टकट्स macOS पर कमांड का उपयोग करते हैं जहां यह पेज Ctrl लिखता है।
अवधारणा और राज्य प्रभाव
तुलना तभी उचित है जब दोनों प्रतियां एक ही रेफरी और एक ही फाइलों से शुरू हों। यदि आप पहले मर्ज करते हैं और फिर उस परिणाम को दोबारा आधार बनाते हैं, तो आप एक अलग प्रश्न पूछ रहे हैं: रीप्ले की सीमा में अब मर्ज कमिट है।
Merge कार्य की दोनों पंक्तियाँ रखता है। यह दो अभिभावकों के साथ एक नई प्रतिबद्धता, K जोड़ता है: पहले S, फिर N. S और N अपनी आईडी रखते हैं।
Rebase आपके कमिट को एन के शीर्ष पर दोबारा चलाता है। परिणाम, एस' में एस के समान परिवर्तन होता है लेकिन एक नया पैरेंट होता है, और एक कमिट की आईडी में उसका पैरेंट शामिल होता है, इसलिए एस' के पास एक नई आईडी होती है। पुराना एस केवल इसलिए जीवित है क्योंकि बचाव शाखा अभी भी उस पर इशारा कर रही है।
जब कुछ भी विरोध नहीं होता है, तो दोनों प्रतियां एक ही फ़ाइल ट्री के साथ समाप्त हो जाती हैं। समान पेड़ों का मतलब समान इतिहास नहीं है: एक ग्राफ़ एक हीरा रखता है, दूसरा एक सीधी रेखा रखता है, और प्रतिबद्ध आईडी अलग-अलग होती हैं।
कौन सा सही है यह स्वाद का विषय नहीं है। यदि अन्य लोगों के पास पहले से ही आपकी प्रतिबद्धताएं हैं, तो उन्हें दोबारा चलाने से उनकी प्रतियां टूट जाती हैं, इसलिए विलय करें। यदि कमिट निजी हैं, तो रिबेस सुरक्षित है और यदि आपकी टीम इसे पसंद करती है तो यह एक रेखीय इतिहास देता है। न ही कोड को बेहतर बनाता है।
प्रत्येक प्रति में केवल विषय शाखा चलती है। सर्वर, updated-main और मूल मुख्य को छुआ नहीं गया है।
सटीक प्रोजेक्ट स्थिति तैयार करें
एक विचलन करें, फिर उसे दो बार कॉपी करें। प्रोजेक्ट की एक अलग सामान्य प्रतिलिपि से प्रारंभ करें क्योंकि पाठ 18 ने इसे छोड़ दिया है (मुख्य मर्ज कमिट एम है)। अपने मूल gittree-features को अछूता छोड़ दें, और इसे कभी भी स्रोत चेकआउट में न चलाएं। डेमो पहचान GitTree डेमो, Demo@example.com है, केवल इस रिपॉजिटरी में हस्ताक्षर करना बंद है।
पूर्ण फ़ाइल इनपुट
केवल नीचे नामित चरण पर ही सहेजें। ये अंतिम नई लाइन के साथ पूर्ण UTF-8/LF निकाय हैं; कभी भी मार्कडाउन बाड़ चिपकाएँ नहीं। अपरिवर्तित चलने योग्य फ़ाइलें नामित इनपुट प्राप्त करती हैं। अलग-अलग संस्करणों में मूल को अधिलेखित नहीं किया जाना चाहिए।
Index.html - साइन अप करें
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">See your work clearly.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
<section aria-labelledby="signup-title">
<h2 id="signup-title">Try the demo form</h2>
<form id="signup-form" novalidate>
<label for="demo-email">Demo email</label>
<input id="demo-email" name="email" type="email" autocomplete="off" aria-describedby="signup-hint">
<p id="signup-hint">Use a fictional example.com address. Nothing is sent.</p>
<button type="submit">Check the address locally</button>
<p id="signup-result" role="status"></p>
</form>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>दस्तावेज़/एकीकरण-नोट.एमडी - DOC_MERGE
# Integration review
This note was written on main while signup work was private.GitTree में
कमांड+Shift+P (Ubuntu पर Ctrl+Shift+P) के साथ पैलेट खोलें, सटीक कमांड नाम टाइप करें और इसे चुनें। किसी नामित शाखा पर कार्रवाइयां उस शाखा के राइट-क्लिक मेनू का उपयोग करती हैं।
- gittree-merge खोलें. फिर इसकी Recent सूची में से New Tab चुनें और gittree-rebase खोलें। प्रत्येक टैब को उसके फ़ोल्डर नाम के साथ शीर्षक दिया गया है, ताकि आप दोनों को अलग-अलग बता सकें।
- gittree-merge टैब में
feature/signup-formको चेक आउट करते रहें।updated-mainपर राइट-क्लिक करें और Merge updated-main into feature/signup-form चुनें। - Record it as के अंतर्गत Always a merge commit चुनें, फिर एक बार Merge चुनें। नई प्रतिबद्धता के दो माता-पिता हैं: पहले S, फिर N।
- gittree-rebase टैब पर स्विच करें. यह अभी भी S और N पर है, ठीक वैसे ही जैसे आपने इसे सहेजा था। मर्ज प्रतिलिपि का उपयोग न करें.
updated-mainपर राइट-क्लिक करें और Rebase feature/signup-form onto updated-main चुनें। Options for this rebase पढ़ें और दोनों विकल्पों को छोड़ दें, फिर Rebase feature/signup-form को एक बार चुनें।- दोबारा चलाए गए कमिट का चयन करें. इसका मूल नाम N है और इसकी आईडी नई है। पुराने S को अभी भी
rescue/signup-before-rebaseनाम दिया गया है। - प्रत्येक टैब में Show Files →
index.htmlऔरdocs/integration-note.mdखोलें। वे दोनों प्रतियों में एक ही पृष्ठ और एक ही नोट हैं। फिर Back to Graph के साथ वापस लौटें। - दो ग्राफ़ की तुलना करें, फिर परिणाम चुनने से पहले बताएं कि कौन सा नियम इस शाखा के लिए विकल्प तय करता है। दोनों प्रतियाँ ज्यों की त्यों रखें।
पाठ्यक्रम में प्रत्येक सामान्य प्रतिबद्धता के लिए: Summary बताया गया विषय है, Description खाली है और विकल्प Amend Previous Commit, Skip Hooks, Add Signed-off-by, Different Author, Push After Commit और Allow Empty Commit बंद रहते हैं। यह पाठ कोई सामान्य प्रतिबद्धता नहीं बनाता।
टर्मिनल में
पाठ 18 के परिणाम की एक अलग साफ प्रतिलिपि में विचलन बनाएं (आपके द्वारा ऐप में किया गया कार्य, मूल कमांड के रूप में लिखा गया है):
git switch --create feature/signup-formसंपूर्ण साइनअप पृष्ठ को index.html के रूप में सहेजें, फिर:
git add -- index.html
git commit --quiet -m "feat: add the local signup demonstration"
git branch rescue/signup-before-rebase
BASE_SHA="$(git rev-parse HEAD~1)"
git switch --quiet --create updated-main "$BASE_SHA"updated-main पर संपूर्ण DOC_MERGE नोट को docs/integration-note.md के रूप में सहेजें, फिर:
git add -- docs/integration-note.md
git commit --quiet -m "docs: add the integration review"
git switch --quiet feature/signup-formBASE_SHA वह प्रतिबद्ध एम है जिससे दोनों पंक्तियाँ बढ़ती हैं। अब इस सटीक स्थिति (cd .. && cp -R gittree-features gittree-merge && cp -R gittree-features gittree-rebase) से दो स्वतंत्र प्रतियां बनाएं। मर्ज कॉपी में:
git merge --quiet --no-ff --no-edit updated-main
git rev-list --parents -n 1 HEAD
git rev-parse 'HEAD^{tree}'
git status --shortअछूती रीबेस कॉपी में:
git rebase --quiet --no-autostash --no-update-refs --no-autosquash updated-main
git rev-list --parents -n 1 HEAD
git rev-parse 'HEAD^{tree}'
git status --shortgit rev-list --parents -n 1 HEAD कमिट की आईडी को उसके माता-पिता द्वारा प्रिंट करता है: मर्ज कॉपी में तीन आईडी, रीबेस कॉपी में दो आईडी। दो HEAD^{tree} पंक्तियाँ एक ही आईडी हैं, और git status --short दोनों में कुछ भी प्रिंट नहीं करता है। दोनों HEAD कमिट आईडी अलग-अलग हैं। आपकी आईडी किसी अन्य से भिन्न होगी; अपनी तुलना एक दूसरे से करें, इस पेज से नहीं।
यदि विषय की अपनी कोई प्रतिबद्धता नहीं है और updated-main बस उससे आगे है, तो git merge डिफ़ॉल्ट रूप से तेजी से आगे बढ़ेगा और कोई मर्ज प्रतिबद्धता नहीं बनाएगा। वह एक अलग इनपुट और एक अलग परिणाम है; इसे जानबूझकर चुनें, कभी भी दो-अभिभावक विलय का दिखावा न करें।
नतीजा
Where you end: मर्ज कॉपी में माता-पिता S और N के साथ एक नया कमिट K है; रिबेस कॉपी में मूल N के साथ S' है, और पुराने S को बचाव शाखा द्वारा रखा जाता है। फ़ाइल ट्री समान हैं, दोनों स्थितियाँ साफ़ हैं, और मूल मुख्य, एम और सर्वर अछूते हैं।
सामान्य गलतियाँ
- एक सीधा ग्राफ़ मानने का मतलब है कि पुरानी प्रतिबद्ध आईडी बची हुई है। एक रिबेस हमेशा नए कमिट बनाता है।
- मर्ज परिणाम से रिबेस प्रारंभ करना। यह एक अलग प्रयोग है, और रीप्ले में मर्ज कमिट शामिल हो सकता है।
- दो हेड आईडी की तुलना करना और उनसे सहमत होने की उम्मीद करना। इसके बजाय पेड़ों की तुलना करें।
- मर्ज या रिबेस समाप्त होने के बाद उसे दोहराना।
अगर कुछ गलत होता है
किसी भी परिणाम को मेल खाने के लिए मजबूर करने के लिए उसे त्यागें नहीं। यदि पेड़ भिन्न हैं, तो शुरुआती रेफरी, किसी भी संघर्ष समाधान और किसी अतिरिक्त प्रतिबद्धता की तुलना करें, फिर सहेजे गए विचलन से फिर से शुरू करें। एक बचाव शाखा केवल प्रतिबद्ध इतिहास रखती है; यह अप्रतिबद्ध फ़ाइलें नहीं रखता है.
अपनी समझ की जाँच करें
प्रत्येक प्रश्न का उत्तर दें, फिर क्यों पढ़ें। "आवश्यक" चिह्नित प्रश्न पाठ को पूरा करने में गिने जाते हैं।
6 में से 0 सही
पाठ को पूरा करने के लिए आवश्यक प्रश्नों के सही उत्तर दें।
इस ब्राउज़र में चेक किया गया.
अभ्यास करें
दो मूल सूचियों, दो HEAD आईडी और दो ट्री आईडी की रिपोर्ट करें। बताएं कि अलग-अलग HEAD आईडी के आगे समान ट्री आईडी अपेक्षित परिणाम क्यों है। फिर बिना ऐसा किए भविष्यवाणी करें कि जब विषय की अपनी कोई प्रतिबद्धता नहीं है तो डिफ़ॉल्ट मर्ज क्या करता है।
आपकी अपनी पुष्टि: साइट आपका कंप्यूटर नहीं देख सकती।
पाठ को पूरा करने के लिए आवश्यक प्रश्नों के सही उत्तर दें और व्यावहारिक अभ्यास की पुष्टि करें।
पुनर्कथन
- एक ही शुरुआत, अलग इतिहास.
- समान वृक्षों का अर्थ समान इतिहास नहीं है।
- जब दूसरों के पास आपकी प्रतिबद्धता हो तो विलय करें। केवल निजी को ही रीबेस करें।
संबंधित
शब्दावली शब्द प्रस्तुत किये गये
रिबेस - إعادة تأسيس; फिर से खेलना - إعادة تطبيق; बचाव शाखा - فرع حفظ.
वीडियो प्रतिलेख
वीडियो का वर्णन, संकेत दर संकेत।
प्रतिलिपि दिखाएँ
- विलय या पुनः आधार? वही काम छूट सकता है दो अलग इतिहास.
- हम दोनों को एक ही शुरुआत से चलाएंगे इंगित करें और तुलना करें.
- आपकी शाखा में एक प्रतिबद्धता है. अद्यतन शाखा में एक और है.
- दोनों एक ही प्रतिबद्धता से विकसित हुए, इसलिए कोई भी नहीं अन्य शामिल है.
- सबसे पहले, विचलन तैयार करें और दो बनाएं समान प्रतियाँ.
- एक निष्पक्ष परीक्षण के लिए समान रेफरी और फाइलों की आवश्यकता होती है दोनों प्रतियों में.
- यहाँ पहली प्रति है. हम विलीन हो जायेंगे यह वाला.
- और यह दूसरी प्रति है. हम इसे रखते हैं रिबेस के लिए अछूता।
- अपडेटेड-मेन पर राइट-क्लिक करें और उसका चयन करें मर्ज आदेश.
- इसे इस रूप में रिकॉर्ड करें के अंतर्गत, हमेशा एक मर्ज चुनें प्रतिबद्ध.
- एक बार मर्ज चुनें, और वास्तविक की प्रतीक्षा करें परिणाम.
- नई प्रतिबद्धता के दो माता-पिता हैं: आपका प्रतिबद्ध, फिर अद्यतन-मुख्य।
- अब दूसरी प्रति. इसमें अभी भी दो हैं मूल प्रतिबद्धताएँ.
- अपडेटेड-मेन पर दोबारा राइट-क्लिक करें और चुनें इस बार रिबेस करें.
- संवाद शाखा का नाम देता है और लक्ष्य. दोनों विकल्प छोड़ दें.
- एक बार रिबेस करें. Git आपके कमिट को दोबारा चलाता है अद्यतन-मुख्य के शीर्ष पर।
- दोबारा चलाए गए कमिट में एक नया पैरेंट है, इसलिए इसे एक नई आईडी मिलती है।
- पुरानी प्रतिबद्धता ख़त्म नहीं हुई है: बचाव शाखा अभी भी इसकी ओर इशारा करती है।
- अब फाइलों की तुलना करें. पेज है दोनों प्रतियों में समान.
- एकीकरण नोट भी ऐसा ही है। वही फ़ाइलें, अलग इतिहास.
- दो ग्राफ़ देखें: एक हीरा मर्ज कमिट, और एक सीधी रेखा।
- तो आपको किसका उपयोग करना चाहिए? पूछो और कौन आपकी प्रतिबद्धताएँ हैं।
- यदि दूसरों के पास है, तो विलय करें। एक रिबेस होगा उनका इतिहास फिर से लिखें.
- यदि कमिट निजी हैं, तो रिबेस है सुरक्षित, और एक सीधी रेखा देता है।
- न ही आपके कोड को बेहतर बनाता है। नियम स्वामित्व के बारे में है.
- अब इसे टर्मिनल में सिद्ध करें। सबसे पहले, प्रत्येक टिप के माता-पिता।
- मर्ज कॉपी के लिए तीन आईडी: कमिट, और इसके दो माता-पिता हैं।
- रीबेस कॉपी के लिए दो आईडी: कमिट, और इसका एक अभिभावक है.
- फिर फ़ाइल ट्री: एक आईडी, मुद्रित दो बार. वही फ़ाइलें.
- लेकिन दोनों प्रतिबद्ध आईडी अलग-अलग हैं। बराबर पेड़, अलग-अलग इतिहास।
- इनपुट बदलें: मान लीजिए कि आपकी शाखा में था अपनी कोई प्रतिबद्धता नहीं.
- एक डिफ़ॉल्ट मर्ज तब तेजी से आगे बढ़ेगा, बिना किसी मर्ज प्रतिबद्धता के।
- कभी भी किसी शाखा का नवीनीकरण किसी और से न कराएं पहले से ही है.
- यदि पेड़ भिन्न हैं, तो शुरुआत की तुलना करें पहले रेफरी.
- दोनों को बाध्य करने के लिए किसी परिणाम को न हटाएं मिलान.
- अभ्यास: माता-पिता, आईडी आदि की रिपोर्ट करें आपकी अपनी प्रतियों से पेड़।
- इसके बाद, पुनः व्यवस्थित करें, स्क्वैश करें और अपना पुनः लिखें स्थानीय प्रतिबद्धताएँ।