الدرس 25 · السجل والتكامل
نقل إيداعات مختارة بالانتقاء (cherry-pick)
انسخ إصلاح زميلة إلى فرع الإصدار دون دمج فرعها كله، ثم افحص الإيداع الجديد ومؤلفه وملفاته وما بقي خلفك.
- المستوى: متوسط
- قراءة 9 دقائق
- فيديو 5 دقائق
- آخر تحديث
- قبل هذا الدرس: اقرأ التاريخ دون تحريك HEAD, حلّ تعارضات الدمج وإعادة التأسيس
حُفظ التقدّم في هذا المتصفح.
يحمّل التشغيل الفيديو من YouTube (وضع الخصوصية المحسّنة).
ما ستتعلمه
- أن تختار الإيداع الواحد الذي تنسخه، وتفهم لماذا لا يأتي أبوه معه.
- أن تتوقع معرّف الإيداع الجديد ومؤلفه ومن أودعه.
- أن تتعرّف الاعتماد المفقود أو التغيير المطبَّق من قبل قبل أن تفرض أي شيء.
- أن تفحص الناتج مقابل فرع المصدر.
قبل البدء
في فرع بريا priya/label إيداعان فوق أساس مشترك B (صفحة التسجيل). الأول ملاحظة غير متعلقة «docs: unrelated source note» تضيف docs/temporary-review.md. والثاني إصلاحها «fix: clarify the fictional email label» الذي يغيّر التسمية في index.html. وفرعك release/label يبدأ من الأساس B نفسه وفيه إيداع واحد لك «docs: record target review» يضيف docs/integration-note.md. فرع release/label محدَّد ومجلد العمل خالٍ. تريد إصلاحها على فرعك، دون ملاحظتها.
كل شيء هنا محلي وضمن الخطة المجانية (يطلب GitTree تسجيل الدخول): دون حساب استضافة أو مزوّد أو إنترنت. كل الهويات خيالية (example.com). لا تنفّذ الدرس في مشروع حقيقي.
نفّذ التغييرات في GitTree أو بأوامر Git الأصلية، لا بالطريقتين في النسخة نفسها. القراءة بعد التنفيذ آمنة دائمًا. تسميات القوائم مأخوذة من نصوص GitTree 2.0 نفسها، وشُغّلت الأوامر الأصلية بـ Git 2.43 في نسخ مؤقتة. لم تُشغَّل خطوات GitTree على macOS أو Windows أو Linux.
الفكرة وأثر الأفعال
يأخذ الانتقاء التغيير الذي أجراه إيداع واحد، مقيسًا إلى أبيه هو، ويطبّقه على الفرع الذي أنت عليه إيداعًا جديدًا. لا يجلب الأب ولا الإيداعات التي قبله. ولهذا تستطيع أخذ إصلاح بريا وترك ملاحظتها.
إيداع المصدر لا يُمَسّ. وللإيداع الجديد معرّف جديد لأن له أبًا جديدًا، لكنه يحتفظ بالمؤلف الأصلي والرسالة. أما المُودِع، من أنشأ هذا الإيداع، فهو أنت. التغيير نفسه بالرسالة نفسها يظل إيداعًا آخر.
الاعتماديات ما زالت مهمة. يعدّل الإصلاح سطرًا من نموذج التسجيل، فيجب أن يملك الفرع الهدف هذا النموذج. إن لم يملكه يتوقف Git بتعارض. وإن كان الهدف يحوي التغيير نفسه فسيكون الانتقاء فارغًا فيتوقف Git من جديد. في الحالتين اقرأ ما تقوله العملية؛ ولا تفرض إيداعًا فارغًا لمجرد التجاوز.
يتحرك الفرع الهدف وحده. يبقى priya/label وكل ما على الخوادم كما هو. ويضيف الإيداع الجديد تغيير التسمية إلى release/label ولا شيء غيره.
إعداد حالة المشروع المحددة
ابدأ من نسخة عادية منفصلة من المشروع كما تركه الدرس 18، وأبقِ gittree-features الأصلي دون مساس. احفظ SIGNUP أساسًا ثم ابنِ الفرعين. النصوص أدناه هي صفحة الأساس (SIGNUP) والملاحظة غير المتعلقة (DOC_NOISE) والصفحة المصحَّحة (SIGNUP_LABEL) وملاحظتك (DOC_MERGE).
مدخلات الملفات كاملة
احفظ في المرحلة المحددة فقط بصيغة UTF-8 وLF وسطر نهائي. لا تلصق أسوار Markdown. ترث الملفات الثابتة نقطة البداية؛ لا تستبدل الأصل بنسخة إعادة منفصلة.
index.html — SIGNUP
<!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>docs/temporary-review.md — DOC_NOISE
Temporary rehearsal note, deliberately dropped.index.html — SIGNUP_LABEL
<!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">Fictional email address</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>docs/integration-note.md — DOC_MERGE
# Integration review
This note was written on main while signup work was private.في GitTree
افتح لوحة الأوامر بـ Command+Shift+P (وCtrl+Shift+P على Ubuntu). تستخدم أفعال الإيداع قائمة النقر بزر الفأرة الأيمن على الإيداع.
- ابنِ الأساس والفرعين كما يبيّن القسم التالي. حدّد
release/labelوتأكد أن مجلد العمل خالٍ. - في المخطط ابحث عن إيداع بريا «fix: clarify the fictional email label» لا الملاحظة التي تحته. حدّده واقرأ تفاصيله: مسار واحد متغيّر هو
index.html، وأبوه هو الملاحظة غير المتعلقة. - انقر ذلك الإيداع بزر الفأرة الأيمن واختر انتقاء الإيداع (Cherry-Pick Commit). يُطبَّق فورًا على الفرع الذي أنت عليه؛ لا منتقي فروع. والأمر معطَّل على الإيداع الذي هو الحالي بالفعل.
- انتظر النتيجة الفعلية. إن توقفت عملية فاستخدم حلّ (Resolve) أو متابعة (Continue) أو إيقاف… (Abort…) من الشريط بدل أن تنتقي من جديد.
- حدّد الإيداع الجديد على
release/label. معرّفه يختلف عن معرّف بريا، والمؤلف Priya Nair والمُودِع GitTree Demo. - افتح
index.html: هو SIGNUP_LABEL. وdocs/temporary-review.mdغير موجود، وdocs/integration-note.mdالخاص بك موجود. ما زالpriya/labelيسمّي رأسه القديم. - أبقِ
release/labelخاليًا. لا تدفع، ولا تدمجpriya/label.
إن حدّدت إيداعين أو أكثر في المخطط تعرض القائمة انتقاء الإيداعات (Cherry-Pick Commits) وتنسخها بالترتيب. هذا الدرس ينسخ إيداعًا واحدًا.
لكل إيداع عادي في الدورة: الملخّص (Summary) هو العنوان المحدد، والوصف (Description) خالٍ، وتبقى الخيارات تعديل الإيداع الأخير وتخطّي الخطّافات وإضافة Signed-off-by ومؤلف مختلف والدفع بعد الإيداع والسماح بإيداع فارغ معطّلة.
في الطرفية
في نسخة منفصلة من ناتج الدرس 18، أنشئ فرع الأساس قبل حفظ SIGNUP:
git switch --create label-baseاحفظ SIGNUP باسم index.html ثم:
git add -- index.html
git commit --quiet -m "feat: prepare the shared signup baseline"
BASE_SHA="$(git rev-parse HEAD)"
git switch --create priya/labelاحفظ DOC_NOISE باسم docs/temporary-review.md ثم:
git add -- docs/temporary-review.md
git commit --quiet -m "docs: unrelated source note"احفظ SIGNUP_LABEL باسم index.html ثم:
git add -- index.html
git -c user.name="Priya Nair" -c user.email=priya@example.com commit --quiet -m "fix: clarify the fictional email label"
PICK_SHA="$(git rev-parse HEAD)"
git switch --create release/label "$BASE_SHA"احفظ DOC_MERGE باسم docs/integration-note.md ثم:
git add -- docs/integration-note.md
git commit --quiet -m "docs: record target review"انتقِ الإصلاح الآن واقرأ الناتج:
git cherry-pick "$PICK_SHA"
git log -1 --format='%s%n%an <%ae>%n%cn <%ce>'
git diff-tree --no-commit-id --name-only -r HEAD
git status --shortfix: clarify the fictional email label
Priya Nair <priya@example.com>
GitTree Demo <demo@example.com>
index.htmlيختلف معرّف الإيداع الجديد عن PICK_SHA، وindex.html هو SIGNUP_LABEL، وdocs/temporary-review.md غائب، والحالة خالية. وهناك حالتان تعرفهما وتجرّبهما في نسخ منفصلة لا في النسخة الأساسية: git cherry-pick -x "$PICK_SHA" يضيف سطر «(cherry picked from commit …)» إلى الرسالة الجديدة، وهو مفيد حين تنتقي بين فروع مشتركة؛ وعلى هدف لا يملك نموذج التسجيل يتوقف الأمر نفسه بتعارض في index.html تحلّه (الدرس 23) أو تتركه بـ git cherry-pick --abort. وإن كان الهدف يملك التغيير فيتوقف Git من جديد بانتقاء فارغ، والمخرج git cherry-pick --skip أو --abort.
النتيجة
أين تنتهي: في release/label إيداع جديد واحد بإصلاح بريا، مؤلفه Priya Nair ومُودِعه GitTree Demo، بمعرّف جديد. في الصفحة التسمية الموضَّحة، ولم تأتِ الملاحظة غير المتعلقة، ولم يتغير priya/label ولا الخادم، ومجلد العمل خالٍ.
أخطاء شائعة
- الظن أن الانتقاء ينقل الإيداع. هو ينسخ التغيير؛ ويبقى الأصل مكانه.
- انتقاء الإيداع الخطأ، الملاحظة غير المتعلقة بدل الإصلاح.
- فرض إيداع فارغ حين يكون التغيير موجودًا على الفرع بالفعل.
- استخدام الانتقاء لنسخ ميزة كاملة إيداعًا إيداعًا بدل دمجها.
إن حدث خطأ
إن توقف الانتقاء فاقرأ الشريط. حلّ ومتابعة تنهيانه كما في الدرس 23، وإيقاف… يعيد الفرع إلى حيث كان. وإن كان الانتقاء خطأً بعد أن انتهى فالإيداع الجديد على release/label وحده: تراجع عنه هناك، ولم يُمَسّ فرع المصدر أصلًا.
اختبر فهمك
أجب عن كل سؤال ثم اقرأ السبب. الأسئلة المعلَّمة «مطلوب» تُحتسب لإكمال الدرس.
0 من 6 صحيحة
أجب عن الأسئلة المطلوبة إجابة صحيحة لتكمل الدرس.
جرى التحقق في هذا المتصفح.
تدريب
اكتب معرّف الإيداع الجديد ومؤلفه ومُودِعه والمسارات المتغيرة، ووجود docs/temporary-review.md من عدمه. ثم توقّع ما يحدث لو انتقيت الإيداع نفسه مرة أخرى إلى release/label.
تأكيد منك أنت: لا يستطيع الموقع رؤية جهازك.
لإكمال الدرس، أجب عن الأسئلة المطلوبة إجابة صحيحة وأكّد تنفيذ التمرين العملي.
خلاصة
- ينسخ الانتقاء تغيير إيداع واحد إيداعًا جديدًا.
- يبقى الأب والإيداعات التي قبله خلفك.
- افحص الاعتماديات والانتقاء الفارغ قبل أن تفرض شيئًا.
ذو صلة
المصطلحات الجديدة
انتقاء — Cherry-pick؛ إيداع المصدر — source commit؛ الهدف — target؛ اعتماد — dependency.
نص الفيديو
ترجمة التعليق الصوتي الإنجليزي للفيديو، مقطعًا بعد مقطع.
اعرض النص
- خذ إصلاحًا واحدًا من فرع آخر، واترك الباقي.
- ينسخ الانتقاء التغيير الذي أجراه إيداع واحد، إيداعًا جديدًا هنا.
- للنسخة معرّف جديد، لكنها تحتفظ بالمؤلف والرسالة.
- ابنِ أساسًا وفرع بريا بملاحظة وإصلاح، وفرع الإصدار الخاص بك.
- افتح المجلد. يعرض المخطط الفرعين من الأساس نفسه.
- إصلاح بريا فوق ملاحظة غير متعلقة. نريد الإصلاح وحده.
- حدّد الإصلاح. مسار واحد متغيّر: index.html.
- تأكد أن release/label هو الحالي وأن مجلد العمل خالٍ.
- انقر الإصلاح بزر الفأرة الأيمن واختر انتقاء الإيداع.
- لا منتقي فروع. يُطبَّق على الفرع الذي أنت عليه.
- على الإيداع الحالي نفسه يكون الأمر معطّلًا.
- نفّذه وانتظر النتيجة الفعلية.
- إيداع جديد فوق release/label.
- يختلف معرّفه عن معرّف بريا لأن أباه مختلف.
- ما زالت بريا المؤلفة. والمُودِع هو أنت.
- تحمل الصفحة التسمية الموضَّحة.
- لم تأتِ الملاحظة غير المتعلقة. وملاحظتك ما زالت هنا.
- فرع بريا كما كان تمامًا.
- في الطرفية يعرض git log مع التنسيق العنوان والمؤلف والمُودِع.
- يسرد git diff-tree المسارات التي غيّرها هذا الإيداع.
- الحالة خالية. لم يُترك شيء.
- بخيار x تسجّل الرسالة من أين جاء الانتقاء.
- انتقِ الإيداع نفسه مرة أخرى فيتوقف Git: الانتقاء فارغ.
- غيّر المُدخل: الهدف بلا نموذج التسجيل.
- يتوقف الانتقاء بتعارض. حلّه وتابع، أو أوقف.
- قد يعتمد التغيير على إيداعات لم تأخذها. اختبر الهدف.
- يعيد الإيقاف الفرع. ولا يُعدَّل المصدر أبدًا.
- تدريب: اذكر المعرّف الجديد والمؤلف والمُودِع والملفات.
- التالي: اترك العمل غير المنتهي جانبًا بأمان بالمخبأ.