اذهب إلى المحتوى

إعادة تأسيس تفريعات طلب السحب وتحديثه في git


زينب الزعيم

تُعد مساهمتك في المشاريع مفتوحة المصدر تجربةً مجزيةً، إذ تتمثل في سعيك لتحسين تجربة المستخدمين النهائيين أمثالك في استخدام البرامج؛ فعندما تقدم طلب سحب pull request، ستتطلب عملية المساهمة في مشروعٍ ما بعضًا من إعادة تأسيس تفريعات rebase الشيفرة البرمجية وإعادة صياغتها قبل قبولها، متبوعةً بعملية تنظيفٍ عامة لفروعك.

سيدلك هذا الدرس التعليمي على بعض الخطوات التي تلي تقديمك طلب سحب إلى مشروع برنامجٍ مفتوح المصدر.

المتطلبات الأساسية

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

ألغى موقع غيت هَب GitHub الاستيثاق Authentication من خلال كلمة المرور في شهر تشرين الثاني من عام 2020. لذلك، حتى تتمكن من الوصول إلى مستودعات repositories موقع غيت هَب من خلال سطر الأوامر، فعليك إنشاء مفتاح الوصول الشخصي Personal Access Token -أو اختصارًا PAT-، أو إضافة معلومات مفتاح SSH العام public SSH key.

لتتعلم أكثر عن المساهمة في المشاريع مفتوحة المصدر اقرأ هذه المقدمة، ولتعلُّم كيفية إنشاء طلبات سحب، اقرأ المقالة إنشاء طلب سحب على Github.

إعادة تأسيس الشيفرة البرمجية وتنظيف التعليقات

عندما تساهم في البرامج مفتوحة المصدر، قد تجد بعض التعارضات conflicts بين فروعك أو طلب السحب الذي قدمته، وبين الشيفرة البرمجية الأولية upstream. وقد ترد رسالة خطأ على الصدفة shell لديك كما في المثال التالي:

CONFLICT (content): Merge conflict in your-file.py
Automatic merge failed; fix conflicts and then commit the result.

أو كما في الصورة التالية عندما تقدم طلب سحب على موقع غيت هَب:

01conflicts.png

(تعارضات)

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

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

سننتقل إلى مجلد الشيفرة البرمجية، تمامًا كما فعلنا في المقال السابق:

$ cd repository

ومن ثم ينبغي عليك التأكُّد من أنك في الفرع الصحيح بالانتقال إليه من خلال استخدام الأمر git checkout:

$ git checkout new-branch

ثم نفذ الأمر git fetch للحصول على أحدث نسخةٍ أولية للشيفرة البرمجية:

$ git fetch origin

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

لبدء هذه العملية، ستنفِذ عملية إعادة تأسيس التفريعات التفاعلية المُستخدمة لتعديل رسائل إيداع سابقة، أو جمع عدة رسائل إيداع في رسالة واحدة، أو حذف أو التراجع عن رسائل إيداع لم تَعُد ضرورية؛ ولتنفيذ ذلك، علينا أن نتمكن من ذكر رسائل الإيداع التي أنشأناها، إما برقمها، أو بسلسلة المحارف التي تذكر أساس الفروع لدينا.

لمعرفة عدد الإيداعات التي أنشأناها، يمكننا تفقُّد الرقم الإجمالي للإيداعات المُنشأة في المشروع من خلال الأمر التالي:

$ git log

وسيكون الخرج مشابهًا للخرج التالي:

commit 46f196203a16b448bf86e0473246eda1d46d1273
Author: username-2 <email-2>
Date:   Mon Dec 14 07:32:45 2015 -0400

    Commit details

commit 66e506853b0366c87f4834bb6b39d941cd034fe3
Author: username1 <email-1>
Date:   Fri Nov 27 20:24:45 2015 -0500

    Commit details

يعرض السجل جميع الإيداعات المُنشأة في مستودع المشروع المحدد، لذلك ستُعرَض الإيداعات التي أنشأها آخرون إلى جانب الإيداعات التي أنشأتها أنت. وبالتالي، عندما يكون للمشاريع سجلًا حافلًا من الإيداعات التي أنشأها عدة مؤلفين، ستحتاج إلى تحديد نفسك على أنك مؤلفًا من خلال الأمر:

$ git log --author=your-username

سيتيح لك هذا المعامل عدَّ الالتزامات التي أنشأتها؛ فإذا كنت تعمل على عدة فروع، تستطيع إضافة branches[=<branch>]‎-- في نهاية الأمر لتظهر النتيجة حسب الفرع.

والآن بعد أن عرفت عدد الإيداعات التي أنشأتها على الفرع الذي تريد إعادة تأسيسه، يمكنك تنفيذ الأمر git rebase كما يلي:

$ git rebase -i HEAD~x

تشير i- في هذا المثال إلى أن إعادة تأسيس التفريعات تفاعلية، و HEAD إلى أحدث إيداع في الفرع الرئيسي، بينما تشير x إلى عدد الإيداعات التي أنشأتها في فرعك منذ أن جلبته في البداية.

لكن إذا كنت لا تعرف عدد الإيداعات التي أنشأتها في فرعك، عليك أن تعرف ما هو الإيداع الذي يمثِّل أساس الفرع خاصتك، من خلال تنفيذ الأمر التالي:

$ git merge-base new-branch main

وسيكون خرج هذا الأمر سلسلة محارف طويلة تُعرف باسم الإيداع المعمَّى Hash، كما يبدو في المثال التالي:

66e506853b0366c87f4834bb6b39d341cd094fe9

سنمرر الإيداع المعمَّى هذا إلى الأمر git rebase:

$ git rebase -i 66e506853b0366c87f4834bb6b39d341cd094fe9

ستكون نتيجة كلا الأمرين السابقين فتح ملفٍ في محرر نصوص واجهة الأوامر يتضمن قائمةً بجميع الإيداعات في فرعك، ويمكنك الآن إما دمجها أو إعادة صياغتها.

دمج الإيداعات

تتمثل عملية دمج رسائل الإيداع بدمج أو جمع عدة إيداعات صغيرة في رسالة أكبر.

ستجد بداية كل إيداع كلمة انتقاء "pick"، لذا سيبدو ملفك مشابهًا للملف التالي إذا كان لديك إيداعين:

  • الملف "‎…username/repository/.git/rebase-merge/git-rebase-todo":
pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

ولدمج الإيداع، ينبغي عليك تبديل الكلمة "pick" بالكلمة "squash" في كل سطر من سطور الملف الموجود ضمن المسار "username/repository/.git/rebase-merge/git-rebase-todo…" باستثناء السطر الأول:

pick a1f29a6 Adding a new feature
squash 79c0e80 Here is another new feature

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

ستتلقى ملاحظةً بمجرد إغلاق الملف على النحو التالي:

Successfully rebased and updated refs/heads/new-branch.

لقد جمعت الآن جميع الإيداعات في إيداعٍ واحد بدمجها معًا.

إعادة صياغة الإيداعات

تُعد إعادة صياغة رسائل الإيداع رائعةً عند ملاحظتك خطًأ إملائيًا، أو عندما تدرك أنك تستخدم صياغةً مختلفةً في كل إيداع لديك.

بمجرد أن تنفذ عملية إعادة تأسيس التفريعات التفاعلية باتباع الخطوات التي ذكرناها من خلال تنفيذ الأمر git rebase -i، سيُفتح ملفٌ مشابهٌ للملف في المسار "username/repository/.git/rebase-merge/git-rebase-todo…" على النحو التالي:

pick a1f29a6 Adding a new feature
pick 79c0e80 Here is another new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

بدِّل الكلمة "reword" بالكلمة "pick"، أي إعادة الصياغة في كل إيداع تريد إعادة صياغته، فمثلًا في الملف الموجود ضمن المسار "username/repository/.git/rebase-merge/git-rebase-todo…"، ستكون إعادة الصياغة على النحو التالي:

pick a1f29a6 Adding a new feature
reword 79c0e80 Adding a second new feature

# Rebase 66e5068..79c0e80 onto 66e5068 (2 command(s))

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

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

عندما تجد عدد الإيداعات التي تنشئها ورسائل الإيداع المتعلقة بها مناسبًا، عليك استكمال إعادة تأسيس فرعك بناءً على أحدث نسخةٍ من الشيفرة البرمجية الأولية للمشروع، وذلك بتنفيذ هذا الأمر من دليل directory المستودع الخاص بك:

$ git rebase origin/main

سيبدأ نظام غيت في هذه المرحلة بإعادة تنفيذ إيداعاتك في أحدث نسخةٍ من الفرع الرئيسي؛ وفي حالة حدوث تعارضات في تلك العملية، سيوقفها غيت مؤقتًا ليطالبك بمعالجة تلك التعارضات قبل متابعة العملية؛ أما إذا لم يجد تعارضات، فسيرِد في الخرج ما يلي:

Current branch new-branch is up to date.

بعد معالجة التعارضات، نفِّذ الأمر:

$ git rebase --continue

إذ سيشير هذا الأمر إلى غيت بأنه يستطيع الآن متابعة إعادة تنفيذ إيداعاتك.

إذا سبق ودمجت الإيداعات من خلال استخدام أمر squash، فستضطر إلى معالجة التعارضات مرةً واحدةً فقط.

تحديث طلب السحب باستخدام الدفع القسري Force-Push

عندما تجري إعادة تأسيس التفريعات، يتغير سجل الفرع الخاص بك، ولن تتمكن من استخدام الأمر get push لأن المسار المباشر قد عُدِّل، وسنضطر عوضًا عن ذلك استخدام force-- أو الراية f- لفرض دفع التغييرات، وهذا يبلغ غيت أنك على درايةٍ كاملة بالذي تدفعه.

دعنا أولًا نتأكد من أن push.default الخاص بنا مضبوطٌ على simple (وهو الإعداد الافتراضي في الإصدار 2.0 وما بعده من نظام غيت) من خلال تنفيذ ما يلي لإعداده:

$ git config --global push.default simple

علينا أن نتأكد في هذه المرحلة أننا في الفرع الصحيح من خلال التحقُّق من الفرع الذي نعمل عليه على النحو التالي:

$ git checkout new-branch

Already on 'new-branch'
. . .

نستطيع حينها تنفيذ عملية الدفع القسري كما يلي:

$ git push -f

سيرد إليك الآن تعليقٌ عن التحديثات التي أجريتها إلى جانب رسالةٍ تشير إلى أن هذا التحديث كان forced update أي تحديثًا قسريًا، وأصبح طلب السحب الذي قدمته محدثًا الآن.

استعادة الإيداعات الضائعة

إذا أزلت في مرحلةٍ ما إيداعًا تحتاج فعلًا إلى دمجه مع مُجمَل المشروع، تستطيع استخدام الأمر git لاستعادة الإيداعات التي أزلتها من دون قصد.

سنستخدم الأمر git reflog للبحث عن الإيداعات الناقصة، ثم ننشئ فرعًا جديدًا من ذلك الإيداع، إذ تشير كلمة Reflog إلى اختصارٍ لعبارة السجل المرجعي reference log، الذي يسجل آخر تحديثٍ للإيداعات في الفروع والمراجع الأخرى ضمن المستودع المحلي.

سننفِّذ الأمر التالي من الدليل الحالي لمستودع الشيفرة البرمجية الذي نعمل فيه:

$ git reflog

وسيكون الخرج عند تنفيذ هذا الأمر مشابهًا للخرج التالي:

46f1962 HEAD@{0}: checkout: moving from branch-1 to new-branch
9370d03 HEAD@{1}: commit: code cleanups
a1f29a6 HEAD@{2}: commit: brand new feature 
38f2fc2 HEAD@{3}: commit: remove testing methods
. . .

ستعرف عند الاطلاع على رسائل الإيداع أيُّ الإيداعات التي أزلتها، وستجد سلسلة المحارف المتعلقة بها قبل معلومات HEAD@{x}‎ في الجهة اليسارية من نافذة الطرفية.

تستطيع الآن الاستفادة من تلك المعلومة وإنشاء فرعٍ جديدٍ من الإيداع المناسب:

$ git checkout -b new-new-branch a1f29a6

أنشأنا في المثال السابق فرعًا جديدًا من ثالث إيداع حصلنا عليه في الخرج السابق، وهو الإيداع الذي بدأ تنفيذ وسم خاصية جديدة "brand new feature"، مُتمثِّل بسلسلة المحارف a1f29a6.

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

اقتباس

ملاحظة: إذا نفذت الأمر git gc مؤخرًا لتنظيف الملفات غير الضرورية وتحسين أداء المستودع المحلي، قد لا تستطيع استعادة الإيداعات المفقودة.

ما الذي تتوقع رؤيته في مراجعة الشيفرة البرمجية؟

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

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

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

سيكون الإشراف على طلب السحب الذي قدمته مستمرًا من خلال نظام غيت، وسيُحدَّث تلقائيًا طوال العملية طالما واصلت إضافة إيداعات إلى نفس الفرع وطبقتها على فرعك المشتق.

عندما تنشر شيفرتك البرمجية ليراجعها أقرانك، لا يجب أن تشعر أبدًا أن المراجعة تتخذ منحًى شخصيًا، لذا احرص على قراءة ملفات "CONTRIBUTION.md" ذات الصلة أو مدونات قواعد السلوك. ومن الضروري أن تتأكد من توافق إيداعاتك مع الإرشادات المحددة ضمن المشروع؛ ولكن إذا بدأت تشعر بالاستياء، فقد لا يستحق المشروع الذي تعمل عليه مساهمتك.

توجد العديد من المساحات الترحيبية في مجتمع البرامج مفتوحة المصدر، وبما أنك تتوقع أن يُنظَر إلى الشيفرة البرمجية التي تشاركها بعينٍ ناقدة، يجب أن تكون جميع الملاحظات التي تتلقاها مهنيةً ولبِقة.

قبول طلب السحب وحذف فرعك

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

يمكنك فعل ذلك من خلال تنفيذ عدة أوامر في نافذة طرفيتك:

$ git checkout main
$ git pull --rebase origin main
$ git push -f origin main

عليك الآن تنظيف كلٍ من فروعك المحلية والبعيدة بحذف الفرع الذي أنشأته في كلا الموضعين لأنك لن تحتاج إليهما بعد الآن. لنحذف أولًا الفرع المحلي:

$ git branch -d new-branch

مهمة الراية d- المُضافة إلى أمر git branch هي حذف الفرع الذي سنذكره في هذا الأمر، والذي سميناه في مثالنا السابق "new-branch".

ثم سنحذف الفرع البعيد على النحو التالي:

$ git push origin --delete new-branch

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

الخاتمة

تناول هذا الدرس التعليمي بعض الخطوات التي قد تلي عملية تقديم طلب السحب إلى مستودع برنامجٍ مفتوح المصدر.

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

ترجمة -وبتصرف- للمقال How To Rebase and Update a Pull Request لصاحبته Lisa Tagliaferri.

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...