الدرس 28 · الاستعادة
عكس تغيير في تاريخ مشترك
تراجَع عن تغيير سيئ يملكه الآخرون بالفعل بإضافة إيداع جديد يلغيه بدل حذف التاريخ، وانشر الإصلاح بدفع عادي.
- المستوى: متوسط
- قراءة 8 دقائق
- فيديو 4 دقائق
- آخر تحديث
- قبل هذا الدرس: ادمج فرعين تباعد سجلهما
حُفظ التقدّم في هذا المتصفح.
يحمّل التشغيل الفيديو من YouTube (وضع الخصوصية المحسّنة).
ما ستتعلمه
- أن تشرح العكس إيداعًا معاكسًا، ولماذا يناسب تاريخًا يملكه الآخرون.
- أن تتوقع أب الإيداع الجديد والملف الذي يتركه.
- أن تتعامل مع عكس يتعارض، وتعرف لماذا يسألك عكس الدمج عن أب.
- أن تنشر الإصلاح دون فرض.
قبل البدء
أنت على shared/dark-regression، وهو فرع من ناتج الدرس 18 (M). آخر إيداع فيه، «style: introduce the rehearsal contrast regression»، يضيف قاعدة واحدة إلى styles.css هي body { color: #f7f8fa; }، فيصير نص الصفحة بلون الخلفية الباهت نفسه. هذا الإيداع موجود بالفعل على خادم محلي أعددته لهذا الدرس، فقد يملكه زميل. تريد أن يعود النص مقروءًا دون إعادة كتابة شيء يملكه الآخرون.
كل شيء هنا محلي وضمن الخطة المجانية (يطلب GitTree تسجيل الدخول): دون حساب استضافة أو مزوّد أو إنترنت. الخادم مستودع محلي مجرّد (bare)، وليس GitHub. كل الهويات خيالية (example.com). لا تنفّذ الدرس في مشروع حقيقي.
نفّذ التغييرات في GitTree أو بأوامر Git الأصلية، لا بالطريقتين في النسخة نفسها. القراءة بعد التنفيذ آمنة دائمًا. تسميات القوائم مأخوذة من نصوص GitTree 2.0 نفسها، وشُغّلت الأوامر الأصلية بـ Git 2.43 في نسخ مؤقتة. لم تُشغَّل خطوات GitTree على macOS أو Windows أو Linux.
الفكرة وأثر الأفعال
ينظر العكس إلى ما غيّره إيداع واحد ويضيف إيداعًا جديدًا يطبّق التغيير المعاكس. يبقى الإيداع السيئ في التاريخ، ويبقى معه الدليل على حدوثه. أما إعادة التعيين فتفعل العكس: تعيد الفرع إلى الخلف وتترك الإيداع خارجه، وهذا مقبول للعمل الذي لا يملكه غيرك، لكنه يجبر كل من يملك الإيداع على إصلاح نسخته.
هنا أب الإيداع الجديد هو الإيداع السيئ، ويعود الملف كما كان بالضبط. يتقدم الفرع إيداعًا واحدًا ويقبله الخادم بدفع عادي، لأنه يضيف فقط إلى ما هو موجود.
يعتمد التغيير المعاكس على ما حوله. إن غيّر أحدهم الأسطر نفسها بعد الإيداع السيئ فسيتوقف العكس بتعارض، وتحلّه كأي تعارض آخر (الدرس 23) أو توقفه. وعكس إيداع دمج يسألك أي أب تُقاس به التغييرات: عادةً الأول، أي الفرع الذي دُمج فيه. وهو يخبر Git أيضًا أن تغييرات الدمج عولجت، فقد يقول دمج الفرع نفسه لاحقًا إنه لا شيء للدمج. يعكس هذا الدرس إيداعًا عاديًا ويعرض ذلك الحوار فقط.
لا يحصل إلا الفرع الحالي على إيداع. ولا يتحرك شيء آخر حتى تدفع.
إعداد حالة المشروع المحددة
ابدأ من نسخة عادية منفصلة من ناتج الدرس 18 (M) وأبقِ أصلك دون مساس. أنشئ الفرع واحفظ DOC_DARK_BAD فوق styles.css وأودِعه، وأنشئ مستودعًا مجرّدًا فارغًا جديدًا بجانب النسخة، وأضفه مستودعًا بعيدًا باسم rehearsal، وادفع الفرع مع الفرع المتتبَّع. أما CSS_RESTORED فهو ما يجب أن يبدو عليه الملف بعد العكس.
مدخلات الملفات كاملة
احفظ في المرحلة المحددة فقط بصيغة UTF-8 وLF وسطر نهائي. لا تلصق أسوار Markdown. ترث الملفات الثابتة نقطة البداية؛ لا تستبدل الأصل بنسخة إعادة منفصلة.
styles.css — DOC_DARK_BAD
:root {
color-scheme: light;
--page: #f7f8fa;
--surface: #ffffff;
--text: #17212e;
--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;
}
body { color: #f7f8fa; }styles.css — CSS_RESTORED
:root {
color-scheme: light;
--page: #f7f8fa;
--surface: #ffffff;
--text: #17212e;
--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;
}في GitTree
افتح لوحة الأوامر بـ Command+Shift+P (وCtrl+Shift+P على Ubuntu). تستخدم أفعال الإيداع قائمة النقر بزر الفأرة الأيمن على الإيداع.
- ابنِ الفرع والإيداع والخادم المحلي كما يبيّن القسم التالي. أبقِ
shared/dark-regressionمحدَّدًا ومجلد العمل خاليًا. - في المخطط حدّد الإيداع السيئ واقرأ تفاصيله: مسار واحد متغيّر هو
styles.css، وسطر واحد مضاف. - انقره بزر الفأرة الأيمن واختر عكس الإيداع (Revert Commit). يُطبَّق فورًا على الفرع الذي أنت عليه؛ ولا محرر رسالة. يقول الإشعار «تم العكس.» وإن توقف بدل ذلك فيعرض الشريط «جارٍ عكس … على shared/dark-regression» مع حلّ (Resolve) ومتابعة (Continue) وإيقاف… (Abort…).
- حدّد الإيداع الجديد. عنوانه
Revert "style: introduce the rehearsal contrast regression"وأبوه هو الإيداع السيئ. الإيداع السيئ ما زال في المخطط. - افتح
styles.css: هو CSS_RESTORED، دون القاعدة المضافة. - اضغط دفع (Push) في الشريط العلوي. هذا دفع عادي للفرع إلى فرعه المتتبَّع؛ لا تختر دفع قسري آمن (with-lease)… (Force Push (With Lease)…). يقول الإشعار «دُفع shared/dark-regression إلى rehearsal/shared/dark-regression.»
- افحص النتيجة: مجلد العمل خالٍ، والإيداعان في المخطط، وفرع الخادم على الإيداع الجديد.
إن نقرت إيداع دمج بزر الفأرة الأيمن فإن عكس الإيداع يفتح «عكس إيداع الدمج …» مع الأب الأول (الفرع الذي دُمج فيه) والأب الثاني (الفرع الذي دُمج). لا تنفّذه هنا.
لكل إيداع عادي في الدورة: الملخّص (Summary) هو العنوان المحدد، والوصف (Description) خالٍ، وتبقى الخيارات تعديل الإيداع الأخير وتخطّي الخطّافات وإضافة Signed-off-by ومؤلف مختلف والدفع بعد الإيداع والسماح بإيداع فارغ معطّلة.
في الطرفية
في نسخة منفصلة من ناتج الدرس 18:
git switch --create shared/dark-regressionاحفظ DOC_DARK_BAD باسم styles.css ثم:
git add -- styles.css
git commit --quiet -m "style: introduce the rehearsal contrast regression"
BAD_SHA="$(git rev-parse HEAD)"
git init --quiet --bare --initial-branch=main ../gittree-revert-origin.git
git remote add rehearsal ../gittree-revert-origin.git
git push --quiet --set-upstream rehearsal shared/dark-regressionالآن اعكس وانشر واقرأ النتيجة:
git revert --no-edit "$BAD_SHA"
git merge-base --is-ancestor "$BAD_SHA" HEAD; echo $?
git log -1 --format=%s
git push --quiet rehearsal shared/dark-regression
git status --short
git ls-remote --heads rehearsal refs/heads/shared/dark-regression
git rev-parse HEAD0
Revert "style: introduce the rehearsal contrast regression"يطبع فحص السلف 0: الإيداع السيئ ما زال خلف HEAD. وstyles.css هو CSS_RESTORED، والحالة خالية، والمعرّفان من ls-remote وrev-parse متساويان. ولم يُستخدم أي خيار فرض. وفي نسخة منفصلة يعدّل فيها إيداع لاحق السطر نفسه يتوقف git revert بعبارة «CONFLICT (content)» وتلميحي git revert --continue وgit revert --abort. ويرفض git revert على إيداع دمج بعبارة «is a merge but no -m option was given»؛ و-m 1 يختار الأب الأول.
النتيجة
أين تنتهي: في shared/dark-regression إيداع جديد واحد يلغي الإيداع السيئ. تستخدم الصفحة CSS_RESTORED، والإيداع السيئ ما زال في التاريخ، وفرع الخادم على الإيداع الجديد، ومجلد العمل خالٍ، ولم يُفرض شيء.
أخطاء شائعة
- استخدام إعادة التعيين ودفع قسري «لإزالة» إيداع يملكه الآخرون بالفعل.
- توقع أن يختفي الإيداع السيئ من السجل.
- عكس إيداع دمج دون اختيار أبيه عن قصد.
- الدفع قبل النظر في الملف الذي تركه العكس.
إن حدث خطأ
إن توقف العكس بتعارض فاقرأ الشريط. حلّ ومتابعة تنهيانه كما في الدرس 23، وإيقاف… يعيد الفرع إلى حيث كان. وإن كان العكس نفسه خطأً بعد أن انتهى فاعكس العكس: هو إيداع آخر فقط.
اختبر فهمك
أجب عن كل سؤال ثم اقرأ السبب. الأسئلة المعلَّمة «مطلوب» تُحتسب لإكمال الدرس.
0 من 6 صحيحة
أجب عن الأسئلة المطلوبة إجابة صحيحة لتكمل الدرس.
جرى التحقق في هذا المتصفح.
تدريب
اذكر عنوان الإيداع المعاكس وأباه، وهل الإيداع السيئ ما زال سلفًا، وهل فرع الخادم يساوي HEAD. ثم توقّع ماذا يحدث لو كان إيداع لاحق قد غيّر السطر نفسه قبل أن تعكس.
تأكيد منك أنت: لا يستطيع الموقع رؤية جهازك.
لإكمال الدرس، أجب عن الأسئلة المطلوبة إجابة صحيحة وأكّد تنفيذ التمرين العملي.
خلاصة
- العكس يضيف إيداعًا يلغي إيداعًا آخر.
- يبقى التاريخ ويعود الملف.
- يكفي دفع عادي.
ذو صلة
المصطلحات الجديدة
Revert — عكس; inverse change — تغيير معاكس; mainline parent — الأب الرئيسي.
نص الفيديو
ترجمة التعليق الصوتي الإنجليزي للفيديو، مقطعًا بعد مقطع.
اعرض النص
- تراجَع عن تغيير يملكه الآخرون بالفعل.
- إعادة التعيين ترجع بالفرع. أما العكس فيضيف إيداعًا جديدًا.
- الآخرون يملكون الإيداع القديم. والعكس يُبقي نسختهم صالحة.
- ابنِ الفرع المشترك بإيداع سيئ، وخادمًا محليًا يملكه.
- يعرض المخطط M والإيداع السيئ فوقه.
- يضيف الإيداع السيئ سطرًا واحدًا فيصير النص باهتًا.
- دوّن معرّفه.
- انقره بزر الفأرة الأيمن واختر عكس الإيداع.
- يُطبَّق فورًا. لا محرر رسالة.
- يقول الإشعار تم العكس.
- سُمّي الإيداع الجديد باسم القديم.
- أبوه هو الإيداع السيئ. لم يُزل شيء.
- عاد الملف كما كان. اختفت القاعدة الباهتة.
- ويعرض المخطط الإيداعين. التاريخ زاد فقط.
- تحرك هذا الفرع فقط. ولم يُنشر شيء بعد.
- الفرع متقدم عن الخادم بإيداع واحد.
- اضغط دفع. هذا دفع عادي.
- يسمّي الإشعار الفرع والخادم.
- لم يلزم فرض. أضاف الدفع إيداعًا فقط.
- في الطرفية يفعل git revert مع no-edit الشيء نفسه.
- الإيداع السيئ ما زال سلفًا. الجواب صفر.
- والعنوان يبدأ بكلمة Revert.
- ادفع ثم قارن معرّف الخادم بـ HEAD. هما متساويان.
- غيّر المُدخل: عدّل أحدهم السطر نفسه لاحقًا.
- يتوقف العكس بتعارض. حلّه وتابع، أو أوقف.
- عكس الدمج يسأل عن أب. وعادةً هو الأول.
- بعد عكس دمج قد لا يفعل دمج ذلك الفرع شيئًا.
- تدريب: اذكر العنوان والأب وفحص السلف ومعرّف الخادم.
- التالي: اعثر على إيداع ضائع بسجل المراجع.