دليل للتراجع عن الأخطاء باستخدام Git (الجزء الثاني)

نشرت: 2022-03-10
ملخص سريع أخطاء. هؤلاء الأشرار القاسيون لا يتوقفون حتى عند عالم تطوير البرمجيات الجميل. لكن على الرغم من أننا لا نستطيع تجنب ارتكاب الأخطاء ، إلا أنه يمكننا تعلم التراجع عنها! ستعرض هذه المقالة الأدوات المناسبة لعملك اليومي مع Git. قد ترغب في التحقق من المقالة الأولى من السلسلة أيضًا.

في هذا الجزء الثاني من سلسلتنا حول "Undoing Mistakes with Git" ، سننظر إلى الخطر بشجاعة مرة أخرى: لقد أعددت أربعة سيناريوهات جديدة ليوم القيامة - بما في ذلك ، بالطبع ، بعض الطرق الذكية لإنقاذ أعناقنا! ولكن قبل أن نتعمق في الأمر: ألق نظرة على المقالات السابقة على Git للاطلاع على المزيد من أساليب الإنقاذ الذاتي التي تساعدك على التراجع عن أخطائك مع Git!

دعنا نذهب!

استعادة فرع محذوف باستخدام Reflog

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

لحسن الحظ ، هناك طريقة لإعادة هذا الفرع من الموت - بمساعدة أداة Git المسماة "Reflog". لقد استخدمنا هذه الأداة في الجزء الأول من سلسلتنا ، ولكن إليك القليل من التنشيط: إن Reflog يشبه دفتر اليومية حيث يلاحظ Git كل حركة لمؤشر HEAD في مستودعك المحلي. بعبارات أخرى أقل غرابة: في أي وقت تقوم فيه بتسجيل الخروج ، أو الالتزام ، أو الدمج ، أو تغيير العنوان الأساسي ، أو اختيار الكرز ، وما إلى ذلك ، يتم إنشاء إدخال دفتر يومية. هذا يجعل Reflog شبكة أمان مثالية عندما تسوء الأمور!

دعنا نلقي نظرة على مثال ملموس:

 $ git branch * feature/login master

يمكننا أن نرى أن لدينا حاليًا feature/login الخاصة بنا التي تم التحقق منها. لنفترض أن هذا هو الفرع الذي سنحذفه (بدون قصد). قبل أن نتمكن من القيام بذلك ، ومع ذلك ، نحتاج إلى التبديل إلى فرع مختلف لأننا لا نستطيع حذف فرع HEAD الحالي الخاص بنا!

 $ git checkout master $ git branch -d feature/login

لقد انتهى الآن فرع الميزات القيمة الخاص بنا - وسأمنحك دقيقة (أ) لفهم خطورة خطأنا و (ب) للحزن قليلاً. بعد أن تمسح الدموع ، نحتاج إلى إيجاد طريقة لإعادة هذا الفرع! لنفتح Reflog (ببساطة عن طريق كتابة git reflog ) ونرى ما يخبئه لنا:

تقوم Git’s Reflog ببروتوكول جميع الإجراءات الرئيسية في مستودعنا المحلي
تقوم Git's Reflog ببروتوكول جميع الإجراءات الرئيسية في مستودعنا المحلي. (معاينة كبيرة)

فيما يلي بعض التعليقات لمساعدتك في فهم النتيجة:

  • بادئ ذي بدء ، عليك أن تعرف أن Reflog يفرز إدخالاته ترتيبًا زمنيًا: العناصر الأحدث موجودة في أعلى القائمة.
  • العنصر العلوي (وبالتالي الأحدث) هو أمر git checkout الذي قمنا به قبل حذف الفرع. تم تسجيله هنا في Reflog لأنه أحد "حركات مؤشر HEAD" التي يسجلها Reflog بشكل كامل.
  • للتراجع عن خطأنا الجسيم ، يمكننا ببساطة العودة إلى الحالة السابقة - والتي تم تسجيلها أيضًا بشكل نظيف وواضح في Reflog!

لذلك دعونا نجرب هذا ، من خلال إنشاء فرع جديد (باسم الفرع "المفقود") يبدأ عند هذه الحالة "قبل" SHA-1:

 $ git branch feature/login 776f8ca

وفويلا! ستسعد برؤية أننا استعدنا الآن فرعنا الذي يبدو أنه مفقود!

إذا كنت تستخدم واجهة مستخدم رسومية لسطح المكتب من Git مثل "Tower" ، فيمكنك أن تأخذ اختصارًا لطيفًا: ما عليك سوى الضغط على CMD + Z على لوحة المفاتيح للتراجع عن الأمر الأخير - حتى لو قمت بحذف فرع عنيف!

يمكن أن تجعل واجهة المستخدم الرسومية لسطح المكتب مثل Tower عملية التراجع عن الأخطاء أسهل.
المزيد بعد القفز! أكمل القراءة أدناه ↓

نقل الالتزام إلى فرع مختلف

في العديد من الفرق ، هناك اتفاق على عدم الالتزام بفروع طويلة الأمد مثل الفروع main أو develop : يجب أن تتلقى الفروع مثل هذه التزامات جديدة فقط من خلال عمليات الدمج (مثل عمليات الدمج أو إعادة التأسيس). ومع ذلك ، فإن الأخطاء لا مفر منها بالطبع: فنحن ننسى أحيانًا هذه الفروع ونرتكبها! إذن كيف يمكننا تنظيف الفوضى التي أحدثناها؟

نقل الالتزام إلى فرع الوجهة الصحيح
وقع التزامنا على الفرع الخطأ. كيف يمكننا نقله إلى فرع الوجهة الصحيح؟ (معاينة كبيرة)

لحسن الحظ ، يمكن تصحيح هذه الأنواع من المشاكل بسهولة. دعونا نشمر عن سواعدنا ونبدأ العمل.

الخطوة الأولى هي التبديل إلى فرع الوجهة الصحيح ثم نقل الالتزام بإفراط باستخدام أمر cherry-pick :

 $ git checkout feature/login $ git cherry-pick 776f8caf

سيكون لديك الآن الالتزام على الفرع المطلوب ، حيث كان يجب أن يكون في المقام الأول. مدهش!

ولكن لا يزال هناك شيء واحد يجب القيام به: نحن بحاجة إلى تنظيف الفرع الذي هبط فيه عن طريق الخطأ في البداية! أنشأ أمر cherry-pick ، ​​إذا جاز التعبير ، نسخة من الالتزام - لكن الأصل لا يزال موجودًا في فرعنا طويل الأمد:

نسخة من الالتزام على الفرع الصحيح ، ولكن لا يزال يتم عرض الأصل على الفرع الخطأ
لقد نجحنا في إنشاء نسخة من الالتزام في الفرع الصحيح ، ولكن الأصل لا يزال هنا - في الفرع الخطأ. (معاينة كبيرة)

هذا يعني أنه يتعين علينا العودة إلى الفرع طويل الأمد واستخدام git reset لإزالته:

 $ git checkout main $ git reset --hard HEAD~1

كما ترى ، نحن نستخدم الأمر git reset هنا لمحو الالتزام الخاطئ. تخبر المعلمة HEAD~1 Git بـ "الرجوع إلى مراجعة واحدة خلف HEAD" ، مما يمحو بفعالية الالتزام الأعلى (وفي حالتنا: غير المرغوب فيه) من تاريخ هذا الفرع.

وفويلا: أصبح الالتزام الآن حيث كان يجب أن يكون في المقام الأول وفرعنا الذي يمتد لفترة طويلة نظيف - كما لو أن خطأنا لم يحدث أبدًا!

تحرير رسالة التزام قديم

من السهل جدًا تهريب خطأ مطبعي في رسالة الالتزام - واكتشافه فقط في وقت لاحق. في مثل هذه الحالة ، لا يمكن استخدام خيار --amend git commit القديم الجيد لإصلاح هذه المشكلة ، لأنه يعمل فقط مع آخر التزام. لتصحيح أي التزام أقدم من ذلك ، يتعين علينا اللجوء إلى أداة Git تسمى “Interactive Rebase”.

رسالة الالتزام تستحق التغيير
إليك رسالة الالتزام تستحق التغيير. (معاينة كبيرة)

أولاً ، علينا إخبار Interactive Rebase أي جزء من سجل الالتزام نريد تعديله. يتم ذلك عن طريق إدخال تجزئة التزام: يلتزم الوالد بالشيء الذي نريد التلاعب به.

 $ git rebase -i 6bcf266b

سيتم فتح نافذة محرر بعد ذلك. يحتوي على قائمة بجميع الالتزامات بعد ذلك الذي قدمناه كأساس لـ Interactive Rebase في الأمر:

عرض نطاق الالتزامات التي اخترناها للتحرير في جلسة Rebase التفاعلية الخاصة بنا
نطاق الالتزامات التي اخترناها للتحرير في جلسة Rebase التفاعلية. (معاينة كبيرة)

هنا ، من المهم ألا تتبع دافعك الأول: في هذه الخطوة ، لا نقوم بتحرير رسالة الالتزام حتى الآن. بدلاً من ذلك ، نخبر Git فقط بنوع التلاعب الذي نريد القيام به مع الالتزام (الالتزامات). ملائم تمامًا ، هناك قائمة بالكلمات الرئيسية للإجراءات المذكورة في التعليقات أسفل هذه النافذة. بالنسبة لحالتنا ، نقوم بترميز السطر رقم 1 بإعادة reword (وبالتالي استبدال pick القياسي).

كل ما تبقى للقيام به في هذه الخطوة هو حفظ وإغلاق نافذة المحرر. في المقابل ، ستفتح نافذة محرر جديدة تحتوي على الرسالة الحالية للالتزام الذي قمنا بترميزه. والآن حان الوقت أخيرًا لإجراء تعديلاتنا!

إليك العملية برمتها في لمحة سريعة بالنسبة لك:

استخدام Interactive Rebase لتحرير رسالة التزام قديمة ، من البداية إلى النهاية.

تصحيح الالتزام المنكسر (بطريقة أنيقة للغاية)

أخيرًا ، سنلقي نظرة على fixup ، سكين الجيش السويسري لأدوات التراجع. ببساطة ، يسمح لك بإصلاح الالتزام المكسور / غير الكامل / غير الصحيح بعد حدوثه. إنها حقًا أداة رائعة لسببين:

  1. لا يهم ما هي المشكلة.
    ربما نسيت إضافة ملف ، أو كان يجب حذف شيء ما ، أو إجراء تغيير غير صحيح ، أو مجرد خطأ إملائي. fixup يعمل في كل هذه المواقف!
  2. إنه أنيق للغاية.
    رد فعلنا الطبيعي الغريزي على خطأ في الالتزام هو إنتاج التزام جديد يعمل على حل المشكلة. طريقة العمل هذه ، مهما بدت بديهية ، تجعل سجل الالتزام الخاص بك يبدو فوضويًا للغاية ، قريبًا جدًا. لديك التزامات "أصلية" ومن ثم هذه الالتزامات الصغيرة "الإسعافات الأولية" التي تعمل على إصلاح الأخطاء التي حدثت في الالتزامات الأصلية. تاريخك مليء بالتعهدات الصغيرة التي لا معنى لها والتي تجعل من الصعب فهم ما حدث في قاعدة التعليمات البرمجية الخاصة بك.
قد يكون من الصعب جدًا قراءة سجل الالتزام الخاص بك إذا قمت بإصلاح الأخطاء الصغيرة باستمرار باستخدام ما يسمى بارتكاب الإسعافات الأولية
يؤدي إصلاح الأخطاء الصغيرة باستمرار باستخدام "عمليات الإسعافات الأولية" إلى صعوبة قراءة سجل الالتزام. (معاينة كبيرة)

هذا هو المكان الذي يأتي فيه fixup . فهو يسمح لك بالاستمرار في تنفيذ تصحيح الضمادة المساعدة. ولكن هنا يأتي السحر: ثم يطبقه على الالتزام الأصلي المكسور (إصلاحه بهذه الطريقة) ثم يتجاهل الالتزام الإسعافي القبيح تمامًا!

يطبق Fixup تصحيحاتك على الالتزام الأصلي ثم يتخلص من الالتزام الإضافي غير الضروري
يطبق Fixup تصحيحاتك على الالتزام الأصلي ثم يتخلص من الالتزام الإضافي غير الضروري. (معاينة كبيرة)

يمكننا أن نذهب من خلال مثال عملي معًا! لنفترض أن الالتزام المحدد هنا معطل.

إصلاح الخطأ المحدد بطريقة أنيقة
الالتزام المحدد غير صحيح - وسنصلحه بطريقة أنيقة. (معاينة كبيرة)

لنفترض أيضًا أنني أعددت تغييرات في ملف باسم error.html من شأنها حل المشكلة. إليك الخطوة الأولى التي يتعين علينا القيام بها:

 $ git add error.html $ git commit --fixup 2b504bee

نحن ننشئ التزامًا جديدًا ، لكننا نخبر Git أن هذا التزام خاص: إنه إصلاح لالتزام قديم باستخدام تجزئة SHA-1 المحددة ( 2b504bee في هذه الحالة).

الخطوة الثانية ، الآن ، هي بدء جلسة Rebase التفاعلية - لأن fixup ينتمي إلى مجموعة الأدوات الكبيرة لـ Interactive Rebase.

 $ git rebase -i --autosquash 0023cddd

هناك شيئان يستحقان الشرح حول هذا الأمر. أولاً ، لماذا قدمت 0023cddd المراجعة هنا؟ لأننا بحاجة إلى بدء جلسة Rebase التفاعلية الخاصة بنا عند التزام الوالدين بزميلنا المكسور.

ثانيًا ، ما هو خيار --autosquash ؟ يستغرق الكثير من العمل عن أكتافنا! في نافذة المحرر التي تفتح الآن ، كل شيء جاهز بالفعل لنا:

نافذة جلسة Rebase التفاعلية
نافذة جلسة Rebase التفاعلية (معاينة كبيرة)

بفضل خيار --autosquash ، قامت Git بالفعل بالرفع الثقيل لنا:

  1. لقد وضع علامة على الالتزام الصغير الخاص بنا باستخدام الكلمة الأساسية fixup . بهذه الطريقة ، سيقوم Git بدمجه مع الالتزام أعلاه مباشرةً ثم يتجاهله.
  2. كما أعاد ترتيب الأسطر وفقًا لذلك ، ونقل التزام المساعدة الشريطية الخاص بنا مباشرةً أسفل الالتزام الذي نريد إصلاحه (مرة أخرى: يعمل fixup من خلال الجمع بين الالتزام المرمز مع الالتزام أعلاه !).

باختصار: ليس لدينا ما نفعله سوى إغلاق النافذة!

دعنا نلقي نظرة أخيرة على النتيجة النهائية.

  • تم إصلاح الالتزام الذي تم كسره سابقًا: فهو يحتوي الآن على التغييرات التي أعددناها في التزام المساعدة الأساسية.
  • تم التخلي عن الالتزام القبيح للإسعافات الأولية: سجل الالتزام نظيف وسهل القراءة - كما لو لم يكن هناك خطأ على الإطلاق.
مثال على كيف يبدو سجل الالتزام النظيف
النتيجة النهائية بعد استخدام أداة الإصلاح: سجل تنفيذ نظيف! (معاينة كبيرة)

إن معرفة كيفية التراجع عن الأخطاء قوة عظمى

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

إذا كنت تريد معرفة المزيد حول التراجع عن الأخطاء مع Git ، يمكنني أن أوصي بـ "First Aid Kit for Git" ، وهي سلسلة من مقاطع الفيديو القصيرة حول هذا الموضوع بالضبط.

استمتع بارتكاب الأخطاء - وبالطبع التراجع عنها بسهولة!