دليل إرشادي لإعادة بناء Git التفاعلي، مع أمثلة عملية

توفر التحكم في الإصدارات باستخدام Git أصبح الأداة الافتراضية في حزمة الأدوات لكل مبرمج معاصر. الأوامر مثل commit, push, و pull أصبحت جزءًا من ذاكرة العضلات لأصابعنا. ولكن عددًا قليلاً نسبيًا من المبرمجين يعرفون عن الميزات “المتقدمة” في Git – وكم هي قيمة لا تصدق! في هذا المقال، سنستكشف “الإعادة التأسيس التفاعلية”، وهي إحدى أقوى الأدوات في Git.

لماذا يجب أن تكون الإعادة التأسيس التفاعلية هي جزء من أدوات كل مبرمج

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

لماذا يعتبر سجل الإصدار المنظم مهمًا؟ تخيل العكس: سجل إصدار يصعب قراءته، حيث لا تعرف بالفعل ما فعله زملاؤك بتغييراتهم الأخيرة. يبدأ المزيد والمزيد من “الزوايا المظلمة” في الظهور في مثل هذا المشروع، وأنت تفهم فقط الأجزاء الصغيرة التي عملت عليها نفسك.

قارن هذا مع سجل إصدار نظيف ومنظم: يساعد على جعل قاعدة كود المشروع أكثر قابلية للقراءة وأسهل في الفهم. هذه مكون أساسي لمشروع صحي ومستدام على المدى الطويل!

ما يمكن للإعادة التأسيس التفاعلية أن تفعله لك

تساعدك الإعادة التأسيس التفاعلية في تحسين وتنظيف سجل إصدارك. تشمل الأحوال التي تغطيها العديد من الاستخدامات المختلفة، بعضها يسمح لك بالقيام بما يلي:

  • تعديل رسالة إصدار قديمة
  • حذف إصدار
  • دمج/جمع إصدارات متعددة
  • إعادة ترتيب الإصدارات
  • تصحيح المراجعات القديمة
  • تقسيم/إعادة فتح المراجعات القديمة للتعديل

متى يجب استخدام الإعادة إلغاء التسلسل التفاعلي (ومتى لا يجب!)

مثل بضعة أدوات جيت أخرى، الإعادة إلغاء التسلسل التفاعلي “يعيد كتابة التاريخ”. وهذا يعني أنه عندما تقوم بالتلاعب بسلسلة من المراجعات باستخدام الإعادة إلغاء التسلسل التفاعلي، فإن هذا الجزء من تاريخ المراجعات سيتم إعادة كتابته: تغيير تجزئة SHA-1 للمراجعة ستكون مختلفة. إنها مراجعات جديدة تمامًا، إذا جاز التعبير.

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

الآلية الأساسية لعملية إعادة إلغاء التسلسل التفاعلي

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

الخطوة 1: من أين يجب أن تبدأ الجلسة؟

السؤال الأول الذي تحتاج إلى الإجابة عليه هو: “أي جزء من تاريخ المراجعات الخاص بي أرغب في التلاعب به؟” هذا يخبرك من أين يجب أن تبدأ جلسة إعادة إلغاء التسلسل التفاعلي الخاصة بك. دعونا نأخذ مثال عملي ونقول إننا نرغب في تعديل رسالة مراجعة قديمة (وهو ما سنقوم به بالفعل في الممارسة في لحظة من الآن).

الوضع الأولي الذي نعمل فيه موضح أدناه، حيث نقوم بتعديل رسالة التأشير القديمة عبر إعادة التأشير التفاعلي.

لتغيير رسالة التأشير في C2، نحتاج إلى بدء جلسة إعادة التأشير التفاعلي من التأشير الأب (أو حتى قبل ذلك، إن أردت ذلك). في هذه الحالة المثالية، سنستخدم C1 كنقطة بداية جلسة إعادة التأشير التفاعلي.

الخطوة 2: بدء الجلسة الفعلية!

بدء الجلسة الفعلية بسيط نسبيًا:

$ git rebase -i HEAD~3

نستخدم أمر git rebase مع علامة -i (للإشارة إلى أننا نريدها أن تكون “تفاعلية”) ونقدم التأشير الأساسي (الذي اشتقناه في الخطوة الأولى أعلاه). في هذا المثال، استخدمت HEAD~3 لتحديد التأشير الذي يكون “3 خلف تأشير HEAD”. بدلاً من ذلك، كان يمكنني توفير معرف SHA-1 محدد.

الخطوة 3: إخبار Git بما تريد القيام به

بعد بدء جلسة إعادة التأشير التفاعلي، ستُعرض عليك نافذة محرر حيث يُظهر Git سلسلة من التأشيرات — من أحدث التأشيرات إلى آخرها (بدون تضمين) التي اخترتها كتأشير أساسي في الخطوة 1.

هناك أمران مهمان يجب تذكرهما في هذه الخطوة:

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

بإزالة هذا النظر النظرية من الطريق، دعونا نغوص في بعض الحالات العملية معًا!

تعديل رسالة تأكيد قديمة

إحدى الاستخدامات الشائعة جدًا للإعادة بسيطة التفاعلية هي أنه يمكنك تعديل رسالة تأكيد قديمة بعد الأمر. قد تكون على دراية بأن git commit --amend تسمح لك أيضًا بتغيير رسالة التأكيد — ولكن فقط إذا كان التأكيد الأخير جدًا. بالنسبة لأي تأكيد أقدم من ذلك، علينا استخدام الإعادة بسيطة التفاعلية!

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

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

في مثالنا، لنفترض أننا نرغب في تعديل رسالة التأكيد الحالية المسماة “تحسين بنية التوصيف في index…”

الخطوة الأولى هي تحديد التأسيس الأساسي لبدء جلسة الإعادة التأسيس التفاعلية. نظرًا لأننا بحاجة على الأقل إلى العودة إلى والد التأميم “التأميم السيئ” الخاص بنا، فإننا نبدأ جلستنا عند HEAD~3 (ثلاثة تأميمات خلف تأميم HEAD، وهو الذي يحمل عنوان “تغيير عنوان الرئيسية…”):

$ git rebase -i HEAD~3

بعد تنفيذ هذا الأمر، ستفتح محرر النص المفضل لديك وتعرض قائمة التأميمات التي اخترتها (من خلال توفير تأميم أساسي).

كتذكير: على الرغم من أنك قد تميل إلى فعل ذلك، فإننا لا نقوم لا بتغيير رسالة التأميم هنا. نحن نقوم فقط بتحرير السطر المعني بكلمة “كلمة الإجراء”. في حالتنا، نريد تعديل التأميم (مما يعني أننا نود تغيير رسالة التأميم، لكننا نترك بقية التأميم كما هو).

من العملي تمامًا، توجد جميع كلمات الإجراء المتاحة في الجزء السفلي من هذه النافذة – لذلك لا داعي لتذكر أي شيء بالذاكرة!

بمجرد استبدال كلمة pick القياسية (التي تعني “خذ التأميم كما هو”) بكلمة الإجراء المفضلة لديك، يمكنك ببساطة حفظ الملف وإغلاق النافذة.

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

بعد القيام بتغييرنا ومن ثم حفظ المحرر وإغلاق النافذة، تكتمل جلسة الإعادة التأسيس التفاعلية – وتم تحديث رسالة التأميم! 🎉

حذف تأميم غير مرغوب فيه

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

تذكر أيضاً أن مجرد حذف المعلومات والالتزام مرة أخرى لا يحل مشكلتك حقاً: هذا يعني أن الكلمة المرور ما زالت محفوظة في المستودع، على هيئة التزامير القديم. ما تريده حقاً هو حذف هذه البيانات بشكل نظيف وكامل من المستودع بأكمله!

لنبدأ بتحديد التزامير الأساسية لجلسة إعادة تبسيطنا التفاعلية. نظرًا لأننا بحاجة إلى البدء على الأقل من والد التزامير السيئة، فإننا نستخدم التزامير “تحسين بنية التحكم…” كأساس لدينا:

$ git rebase -i 6bcf266b

لاحظ أنني استخدمت هذه المرة كلمة مركبة SHA-1 محددة في أمر git rebase -i. بدلاً من رمز التزامير، بالطبع، كان بإمكاني استخدام HEAD~2 للإشارة إلى ذلك التزامير.

بعد تنفيذ هذا الأمر، يتم تقديم لنا قائمة بالتزامير مرة أخرى.

هذه المرة، نستخدم كلمة الأفعال drop للتخلص من التزامير غير المرغوب فيه. وبديلًا، في هذه الحالة الخاصة، يمكننا أيضًا مجرد حذف السطر بأكمله من المحرر. إذا لم يكن السطر (يمثل التزامير) موجودًا بعد الآن عند حفظ وإغلاق النافذة، سيقوم Git بحذف التزامير المقابل.

ولكن كيفما قررت القيام بذلك، بعد حفظك وإغلاق نافذة المحرر، سيتم حذف التزامير من تاريخ المستودع!

دمج التزامير المتعددة في تزامير واحد

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

بشكل عام، جعل التطورات “أكبر” (عن طريق دمج عدة في واحدة) ليس ليس استراتيجية جيدة في معظم الحالات. القاعدة العامة هي أن تحتفظ بالتطورات صغيرة قدر الإمكان، لأن “الصغر” يعني “أسهل في القراءة والفهم”. ومع ذلك، هناك حالات يكون فيها هذا منطقيًا. هنا مثالان:

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

المنطق هو نفسه في كلا المثالين: من خلال دمج تطورين (أو أكثر) يجب أن يكونا تطورًا واحدًا في المقام الأول، أنت تنتج تاريخ تطور أكثر نظافة وقراءة مباشرة!

دعونا نستعرض مثالًا عمليًا معًا ونأخذ الموقف الموضح أدناه كنقطة انطلاقنا.

دعونا نقول أنه من المنطقي أكثر من الناحية الدلالية أن يكون هذان التذكيران في واحد. باستخدام أداة الـ squash في الإعادة تلصق التفاعلية، يمكننا بالفعل دمجهما:

$ git rebase -i HEAD~3

الآن، لقد اعتدت بالفعل على ما يحدث بعد ذلك: يفتح نافذة محرر بها قائمة بالتذكير.

I already mentioned that we’re going to use the squash action keyword in this case. There’s an important thing to know about how squash works: the line you mark up with the keyword will be combined with the line directly above! This explains why I marked line 2 with the squash keyword in our example.

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

ما تراه في الصورة المقتبسة أعلاه هو ما أعده لنا Git: دمج رسائل التذكير للتذكيرات الأصلية مع بعض التعليقات. يمكنك حذف الرسائل القديمة والبدء من جديد – أو الاحتفاظ بها وإضافة بعض المعلومات.

بعد حفظ وإغلاق نافذة المحرر هذه، يمكننا القول بفخر: ما كان يعتبر تذكيرين منفصلين هو الآن تذكير واحد!

تسخير قوة الإعادة تلصق التفاعلية

I hope you agree that Git’s interactive rebase tools can be very valuable! As developers, it’s important for us to strive for a clean and clear commit history. It’s a crucial ingredient in keeping a codebase healthy and easy to understand (both for your teammates, and yourself, after some time has passed).

إذا كنت ترغب في التعلم أكثر، أوصي بشدة بـ “مجموعة الإسعاف الأولي لـ Git“. إنها مجموعة (مجانية) من مقاطع الفيديو القصيرة التي توضح لك كيفية تنظيف والتراجع عن الأخطاء في Git.

استمتع!

الأسئلة الشائعة (FAQs) حول Git Interactive Rebase

ما الفرق بين Git Rebase وGit Merge؟

تعد Git Rebase و Git Merge طريقتين مختلفتين لدمج التغييرات من فرع واحد إلى آخر. يعد Git Merge طريقة بسيطة لدمج الكود من فرعين مختلفين. يخلق تأسيس تصويري جديد في التاريخ، محفظة التسلسل الزمني للتصويرات. من ناحية أخرى، يعد Git Rebase طريقة لنقل أو دمج تسلسل من التصويرات إلى تأسيس تصويري جديد. إنه مثل القول “أريد أن أستند تغييراتي على ما قام به الجميع”. بمعنى آخر، يسمح لك بوضع التغييرات من الفرع الحالي فوق فرع آخر.

كيف يمكنني التراجع عن Git Rebase؟

إذا كنت ترغب في التراجع عن Git Rebase، يمكنك استخدام الأمر git reflog للعثور على التصوير الذي ترغب في العودة إليه، ثم استخدام الأمر git reset --hard HEAD@{number}. يظهر الأمر git reflog قائمة بكل التغييرات التي تم إجراؤها على HEAD، ويسمح لك الأمر git reset بتعيين HEAD الحالي إلى الحالة المحددة.

ما هو الغرض من Git Interactive Rebase؟

يسمح Git Interactive Rebase لك بتعديل التصويرات بطرق عديدة مثل التحرير والحذف والانضمام. لا يمكنك فقط تغيير رسالة التصوير، ولكن يمكنك أيضًا تغيير الكود الفعلي إذا ارتكبت خطأ. إنها أداة قوية تمنحك السيطرة الكاملة على تاريخ تصويرات مشروعك.

كيف يمكنني دمج التصويرات باستخدام Git Interactive Rebase؟

التكبير هو عملية دمج عدة التحولات في واحد. في Git، يمكنك تكبير التحولات باستخدام الأمر git rebase -i متبوعًا بأحرف التحول التي تريد تكبيرها. في محرر النص الذي يفتح، يمكنك تحديد التحولات التي تريد تكبيرها عن طريق استبدال pick بـ squash أو s بجانب كل تحول.

ما هي المخاطر المتعلقة باستخدام Git Interactive Rebase؟

على الرغم من قوة Git Interactive Rebase، يمكن أن يكون خطيرًا إذا لم يتم استخدامه بشكل صحيح. فهو يعيد كتابة التاريخ التحول، وهو ما يمكن أن يكون مشكلة إذا كنت تعمل على فرع عام يعمل عليه أيضًا غيرك. يوصى باستخدامه على الفروع المحلية التي لم يتم دفعها بعد.

كيف يمكنني حل النزاعات خلال إعادة Git Rebase؟

خلال إعادة التأليف، قد تحدث نزاعات. سيتوقف Git ويسمح لك بحل تلك النزاعات قبل المتابعة. يمكنك حل النزاعات عن طريق تعديل الملفات لإصلاح التغييرات المتعارضة وإضافة الملفات المحللة باستخدام git add. بعد حل جميع النزاعات، يمكنك متابعة إعادة التأليف باستخدام git rebase --continue.

هل يمكنني استخدام Git Interactive Rebase لتقسيم تحول؟

نعم، يمكنك استخدام Git Interactive Rebase لتقسيم تحول إلى أصغر عدة. يمكن أن يكون هذا مفيدًا إذا قمت بعمليات عدة في تحول واحد ولكن تقرر لاحقًا أنها يجب أن تكون تحولات منفصلة.

كيف يمكنني تعديل رسالة تحول باستخدام Git Interactive Rebase؟

يمكنك تعديل رسالة التزامن خلال إعادة التوجيه التفاعلية. في قائمة التزامنات، استبدل pick بـ reword أو r بجانب التزامن الذي ترغب في تعديله. عندما تواصل، سيفتح Git محرر نص لكل تزامن مميز بـ reword، مما يسمح لك بتغيير رسالة التزامن.

ما الفرق بين Git Rebase و Git Pull؟

Git Pull هو أمر يستلهم التغييرات من مستودع عن بعد ويدمجها في الفرع الحالي الذي تعمل عليه. من ناحية أخرى، Git Rebase هو أمر يحرك أو يجمع تسلسلًا من التزامنات إلى تزامن أساسي جديد. على الرغم من أن كلا الأمرين يُستخدم لدمج التغييرات، إلا أنهما يفعلان ذلك بطرق مختلفة.

هل يمكنني استخدام Git Interactive Rebase لتغيير ترتيب التزامنات؟

نعم، يمكنك تغيير ترتيب التزامنات باستخدام Git Interactive Rebase. في قائمة التزامنات، يمكنك ببساطة تغيير ترتيب الأسطر لتغيير ترتيب التزامنات. يمكن أن يكون هذا مفيدًا إذا كنت ترغب في جعل تاريخ تزامنك أكثر منطقية أو وضوحًا.

Source:
https://www.sitepoint.com/git-interactive-rebase-guide/