تخطَّ إلى المحتوى
GitTree

الدرس 32 · الاستعادة

التعافي من أخطاء بعد الدفع

أصلح خطأً قد يملكه الآخرون بالفعل: فضّل إيداعًا جديدًا، وحين يلزم أن تعيد كتابة فرع تملكه فادفع قسرًا بقفل مثبَّت على رأس الفرع البعيد الذي راجعته بالضبط.

حُفظ التقدّم في هذا المتصفح.

يحمّل التشغيل الفيديو من YouTube (وضع الخصوصية المحسّنة).

تعليق صوتي بالإنجليزية · ترجمة إنجليزية وعربية

افتح صفحة الفيديوشاهد على YouTube

ما ستتعلمه

  • أن تختار بين إصلاح بالإضافة وإعادة كتابة لخطأ مدفوع.
  • أن تشرح ما يفحصه القفل ولماذا يهم الإيداع المتوقَّع.
  • أن تتوقع رفض قفل قديم وتحافظ على عمل زميل.
  • أن تعرف ما يحفظه GitTree قبل الدفع القسري.

قبل البدء

حالتان على خادم تجريبي محلي. على shared دُفع إيداع سيئ وقد يملكه آخرون. وعلى lease دفعت مسودة ثم أعدت كتابتها محليًا، لكن ليو دفع إيداعًا أحدث إلى الفرع نفسه في هذه الأثناء.

كل شيء هنا محلي وضمن الخطة المجانية (يطلب GitTree تسجيل الدخول): دون حساب استضافة أو مزوّد أو إنترنت. كل الهويات خيالية (example.com). لا تنفّذ الدرس في مشروع حقيقي.

نفّذ التغييرات في GitTree أو بأوامر Git الأصلية، لا بالطريقتين في النسخة نفسها. القراءة بعد التنفيذ آمنة دائمًا. تسميات القوائم مأخوذة من نصوص GitTree 2.0 نفسها، وشُغّلت الأوامر الأصلية بـ Git 2.43 في نسخ مؤقتة. لم تُشغَّل خطوات GitTree على macOS أو Windows أو Linux.

الفكرة وأثر الأفعال

إن كان زملاؤك يملكون الإيداع السيئ فأصلحه بإيداع جديد (عكس، الدرس 28) وادفع دفعًا عاديًا: يبقى الخطأ في التاريخ ولا تُبطَل نسخة أحد. ولا تعد كتابة فرع منشور إلا إن كنت تملكه.

يجعل القفل الدفع القسري مشروطًا: لا يستبدل Git الفرع البعيد إلا إن كان ما زال حيث تتوقع. ويسمّي --force-with-lease=<ref>:<commit> الإيداع المتوقَّع. أما --force-with-lease المجرد فيستخدم مرجعك المتتبِّع للبعيد، وgit fetch يحرّك ذلك المرجع، فالجلب ثم الدفع قد يكتب فوق ما نزّلته للتو. ويثبّت GitTree الإيداع المجلوب أخيرًا ويعرضه في حواره ويحتفظ بالرأس المستبدَل تحت refs/ogt/trash.

ولا يقرر القفل هل يحق لك الكتابة فوق عمل زميل. هو يحميك فقط من الكتابة فوق شيء لم تره.

إعداد حالة المشروع المحددة

ابدأ من نسخة عادية منفصلة من ناتج الدرس 18 ومستودع محلي مجرّد جديد خادمًا وحيدًا. RECOVERY_BAD هي ورقة الأنماط السيئة؛ وLEASE_A وLEASE_B وLEASE_REWRITE ثلاث نسخ من ملاحظة.

مدخلات الملفات كاملة

احفظ كل ملف أدناه كما هو بالضبط: ترميز UTF-8 ونهايات أسطر LF وسطر نهائي واحد، دون أسطر أسوار Markdown. والملفات غير المدرجة تبقى بمحتواها في M.

styles.css — RECOVERY_BAD

مقتطف من ملف · css
:root {
  color-scheme: light;
  --page: #f7f8fa;
  --surface: #ffffff;
  --text: #f7f8fa;
  --link: #154ab5;
  --line: #bac4d0;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--text);
  font: 1rem/1.6 system-ui, sans-serif;
}

a {
  color: var(--link);
}

.site-header,
main,
footer {
  width: min(68rem, 100% - 2rem);
  margin-inline: auto;
}

.site-header {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1rem;
}

.hero {
  max-width: 48rem;
  padding-block: 3rem;
}

h1 {
  font-size: clamp(2rem, 5vw, 3.5rem);
  line-height: 1.2;
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: 1rem;
}

.feature-card {
  padding: 1rem;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
  background: var(--surface);
}

section {
  margin-block-end: 2rem;
}

button,
input {
  font: inherit;
}

button,
input {
  padding: 0.5rem 0.75rem;
}

:focus-visible {
  outline: 3px solid var(--link);
  outline-offset: 3px;
}

form {
  display: grid;
  max-width: 28rem;
  gap: 0.5rem;
}

docs/lease-note.md — LEASE_A

الناتج
# Private release rehearsal

The reviewed draft is still private.

docs/lease-note.md — LEASE_B

الناتج
# Private release rehearsal

Leo added a review that must not be overwritten.

docs/lease-note.md — LEASE_REWRITE

الناتج
# Private release rehearsal

This alternative draft has not seen Leo's review.

في GitTree

افتح لوحة الأوامر بـ Command+Shift+P (وCtrl+Shift+P على Ubuntu).

  1. ابنِ البروفة كما يبيّن القسم التالي: الإيداع السيئ مدفوعًا إلى shared، وفرع lease وعليه إيداع ليو الأحدث في الخادم.
  2. إصلاح بالإضافة. على shared انقر الإيداع السيئ بزر الفأرة الأيمن واختر عكس الإيداع (Revert Commit) ثم اضغط دفع (Push). هذا دفع عادي؛ لا تختر دفع قسري آمن (with-lease)….
  3. قفل قديم. على private/lease أعد كتابة المسودة محليًا ليخلو الفرع من الإيداع المدفوع وحاول دفعه بزر الدفع في الشريط. يسأل GitTree أولًا أين يدفع، لأن private/lease يتتبع origin/lease باسم مختلف: اختر الدفع إلى origin/lease. ثم يعرض حوار عنوانه «رفض المستودع البعيد private/lease» الخيارات جلب فقط وإعادة تأسيس ثم دفع ودمج ثم دفع ودفع قسري….
  4. اختر جلب فقط أولًا واقرأ المخطط: في الفرع البعيد الآن إيداع ليو، وليس في إعادة كتابتك. هذا عمل زميل.
  5. افتح دفع قسري…. يقول حوار «دفع private/lease قسريًا إلى origin/lease؟» إن الإيداعات التي ينقصها فرعك ستُزال من المستودع البعيد، وإن الدفع لا يمضي إلا ما دام البعيد عند الإيداع المعروض، وإن الرأس المستبدَل يُحفظ تحت refs/ogt/trash. اختر الإلغاء؛ فعمل ليو ليس لك لتستبدله.
  6. أو وفِّق بدل ذلك: إعادة تأسيس ثم دفع يضع مسودتك فوق مسودة ليو، أو اسأله أولًا. وإن نُفّذ دفع قسري فعلًا فيقول الإشعار «اكتمل الدفع القسري. الرأس البعيد المستبدَل محفوظ في …» ويعدّ تراجع الدفع القسري تغييرًا لمستودع بعيد تدفع مجددًا لإرجاعه.

في الطرفية

بعد العكس، على shared:

الأمر · bash
git revert --no-edit "$BAD_SHA"
git push origin HEAD:shared
git merge-base --is-ancestor "$BAD_SHA" HEAD; echo $?

الجواب 0: يبقى الخطأ في التاريخ ولم يُجبَر أحد على إصلاح نسخة.

على private/lease وإيداع ليو في الخادم، جرّب القفل المثبَّت بالإيداع الذي راجعته:

الأمر · bash
git push --force-with-lease=refs/heads/lease:"$EXPECTED_SHA" origin HEAD:lease; echo $?
git ls-remote origin refs/heads/lease
git status --short
الناتج
 ! [rejected]        HEAD -> lease (stale info)
error: failed to push some refs to '../origin.git'
1

يرفض Git («stale info») وما زال الخادم يسمّي إيداع ليو والحالة خالية. والأمر git push --force-with-lease origin HEAD:lease المجرد يُرفض أيضًا ما دام مرجعك المتتبِّع قديمًا، لكن بعد git fetch origin lease يستبدل الأمر نفسه إيداع ليو، لأن الجلب حرّك المرجع الذي يقارن به. سمِّ الإيداع الذي راجعته، أو وفِّق بإعادة تأسيس.

النتيجة

أين تنتهي: الإيداع السيئ ما زال في تاريخ shared وفوقه عكس دُفع دفعًا عاديًا. وعلى lease رُفض الدفع المثبَّت، وما زال الخادم يحمل إيداع ليو، وإعادة كتابتك سليمة محليًا. ولم يُنفَّذ أي دفع قسري.

أخطاء شائعة

  • إعادة كتابة فرع سحبه الآخرون بالفعل مع أن العكس يكفي.
  • الجلب ثم الدفع القسري بقفل مجرد، فيثق الآن بما نزّلته للتو.
  • اعتبار القفل إذنًا باستبدال إيداع زميل.
  • افتراض أن التراجع يستطيع عكس دفع قسري في الخادم.

إن حدث خطأ

إن استبدل دفع قسري الرأس الخطأ فالإيداع المستبدَل محفوظ تحت refs/ogt/trash (وفي الدفع الأصلي في سجل المراجع ونسخة الزميل). أخبر الزميل واستعد الرأس فرعًا وادفعه من جديد باتفاقكما. والدفع المرفوض لم يغيّر شيئًا.

اختبر فهمك

أجب عن كل سؤال ثم اقرأ السبب. الأسئلة المعلَّمة «مطلوب» تُحتسب لإكمال الدرس.

  1. السؤال 1 من 6

    إيداع سيئ على الفرع المشترك بالفعل. ما أأمن إصلاح؟

    اختر إجابة واحدة.

  2. السؤال 2 من 6

    أي مما يلي صحيح عن --force-with-lease؟

    اختر كل إجابة صحيحة.

  3. السؤال 3 من 6
    مطلوب

    تدفع بقفل مثبَّت على الإيداع الذي راجعته، لكن ليو دفع بعد ذلك. ماذا يحدث؟

    اختر إجابة واحدة.

  4. السؤال 4 من 6

    غيّر المُدخل: تنفّذ git fetch origin lease ثم git push --force-with-lease origin HEAD:lease المجرد. ماذا يحدث؟

    اختر إجابة واحدة.

  5. السؤال 5 من 6
    مطلوب

    يقول زميل «القفل يجعل الدفع القسري آمنًا للجميع». ما الرد الصحيح؟

    اختر إجابة واحدة.

  6. السؤال 6 من 6
    مطلوب

    بعد الدفع المثبَّت، أي قراءات تبيّن أن شيئًا لم يضع؟

    اختر كل إجابة صحيحة.

0 من 6 صحيحة

أجب عن الأسئلة المطلوبة إجابة صحيحة لتكمل الدرس.

جرى التحقق في هذا المتصفح.

تدريب

اذكر فحص السلف على shared، ورمز الخروج ورسالة الدفع المثبَّت، والإيداع الذي يعرضه ls-remote للفرع lease، وهل كان القفل المجرد سيُرفض قبل الجلب وبعده.

تأكيد منك أنت: لا يستطيع الموقع رؤية جهازك.

لإكمال الدرس، أجب عن الأسئلة المطلوبة إجابة صحيحة وأكّد تنفيذ التمرين العملي.

خلاصة

  • فضّل إيداعًا جديدًا لكل ما قد يملكه الآخرون.
  • ثبّت القفل على الإيداع الذي راجعته.
  • القفل يحميك لا نية زميلك.

المصطلحات الجديدة

Lease — قفل; stale info — معلومات قديمة; replaced tip — الرأس المستبدَل.

نص الفيديو

ترجمة التعليق الصوتي الإنجليزي للفيديو، مقطعًا بعد مقطع.

اعرض النص
  1. دفعت خطأً. ماذا الآن؟
  2. إن كان الآخرون يملكون الإيداع فأصلحه بإضافة إيداع.
  3. يقول القفل: استبدل البعيد فقط إن كان ما زال حيث أتوقع.
  4. لكن الجلب يحرّك ما يتوقعه القفل المجرد.
  5. فرعان على خادم محلي: shared وlease.
  6. على shared اعكس الإيداع السيئ.
  7. ادفع دفعًا عاديًا. بلا فرض.
  8. يبقى الخطأ في التاريخ ولا يضطر أحد إلى إصلاح نسخة.
  9. على lease يُرفض الفرع المعاد كتابته.
  10. اجلب فقط وانظر. إيداع ليو هناك.
  11. لا يمضي الدفع إلا والبعيد عند هذا الإيداع، ويحفظ الرأس المستبدَل.
  12. عمل ليو ليس لك لتستبدله. أعد التأسيس عليه أو اسأله.
  13. في الطرفية فحص السلف على shared صفر.
  14. سمِّ الإيداع الذي راجعته. يقول Git معلومات قديمة.
  15. ما زال الخادم يسمّي إيداع ليو.
  16. القفل المجرد بعد جلب كان سيستبدله.
  17. التراجع لا يعكس دفعًا قسريًا في الخادم.
  18. تدريب: اذكر رمز الخروج وإيداع الخادم والحالة.
  19. التالي: اعمل على فرعين معًا بمجلدات العمل المتعددة.