٥، ٦، المساهمة في مشروع
 — مشروع عمومي باشتقاقات

المساهمة في مشروع عمومي أمرها مختلف. فليس لديك إذن الدفع فيه لتستطيع تحديث فروعه مباشرةً، فعليك إرسال عملك إلى القائمين عليه بطريقة أخرى. يشرح المثال الأول هذا المساهمة بالاشتقاق في مواقع استضافة جت التي تسهّل الاشتقاق. مواقع كثيرة تدعمه (منها جت‌هب GitHub، و BitBucket، و repo.or.cz، وآخرون)، والكثير من مديري المشروعات يتوقعون أسلوب المساهمة هذا. أما الفصل التالي فسيتناول المشروعات التي تحب قبول الرقع المساهم بها عبر البريد الشابكي.

أولًا عليك غالبًا استنساخ المستودع الرئيس، وإنشاء فرع موضوع للرقعة أو سلسلة الرقع التي تريد المساهمة بها، ثم العمل فيه. فسلسلة الأفعال تبدو هكذا:

$ git clone «رابط-المستودع»
$ cd project
$ git checkout -b featureA
  ... عمل ...
$ git commit
  ... عمل ...
$ git commit

قد تود استعمال إعادة التأسيس التفاعلية git rebase -i لهرس عملك (‪“squash”‬) إلى إيداع واحد، أو لإعادة ترتيب الإيداعات، حتى تسهّل مراجعة الرقعة على المشرف؛ انظر فصل تحرير التاريخ لمعلومات أزيد عن إعادة التأسيس التفاعلية.

عندما تفرغ من عملك في الفرع وتكون مستعدًا لمشاركته مع القائمين على المشروع، اذهب إلى صفحة المشروع الأصل واضغط زر ‪“Fork”‬ («اشتقاق»)، لتُنشئ نسختك الخاصة بك من المشروع التي تستطيع الدفع إليها. عندئذٍ تحتاج إضافة رابط هذا المستودع ليكون بعيدًا جديدًا في مستودعك المحلي؛ لنسمّيه فيه هذا المثال myfork:

$ git remote add myfork «الرابط»

عندئذٍ تدفع عملك إلى هذا المستودع. من الأسهل أن تدفع (إلى اشتقاقك) فرعَ الموضوع الذي عملت فيه، بدلًا من دمج عملك في الفرع الرئيس المحلي ودفع هذا الفرع. وذلك حتى لا تضطر إلى إرجاع فرعك الرئيس إلى الخلف، إن لم يقبلوا عملك أو أنهم اصطفوه (نتناول عملية الاصطفاء cherry-pick في جت بمزيد من التفصيل في فصل أساليب الاصطفاء وإعادة التأسيس). فإذا القائمون على المشروع دمجوا عملك (merge)، أو أعادوا تأسيسه (rebase)، أو اصطفوه (cherry-pick)، فستحتاج إلى إحضاره من جديد بالجذب من مستودعهم بطريقة ما.

وعموما، يمكنك دفع عملك بالأمر:

$ git push -u myfork featureA

ما إن يتم دفع عملك إلى اشتقاقك من المستودع، عليك إعلام القائمين على المشروع الأصل أن لديك شيئًا تود منهم أن يدمجوه. في الغالب يسمى هذا «طلب جذب» (pull request)، وفي المعتاد تُنشئ هذا الطلب إما عبر الموقع (فلدى جت‌هب آلية طلبات الجذب الخاصة به التي سنتناولها في باب ؜GitHub) وإما بالأمر git request-pull وإرسال ناتجه بالبريد بنفسك إلى القائمين على المشروع.

(من المترجم) يسمى هذا «طلب جذب» في جت نفسه وفي عدة مواقع استضافة جت، ويسمى «طلب دمج» في مواقع جت أخرى. واختلف الناس في علة الاختلاف بين الاسمين؛ انظر الإجابات على هذا السؤال: Pull request vs Merge request.

و«الجذب» أقرب لعمل جت، فإنك تطلب من القائمين على المشروع الأصل أن يجذبوا (pull) عملك، والجذب يشمل الدمج. لكن «الدمج» أوضح لمن لم يضطلع بجت. فمن اختار «طلب جذب» اتبع جت نفسه، ومن اختار «طلب دمج» اختار الأوضح للمستخدمين.

ومما يؤيد «الجذب» أن الجذب هو استحضار fetch متبوعٌ إما بدمج merge وإما بإعادة التأسيس rebase. لكن في العربية «الدمج» يعني ‪“merge”‬ ويعني ‪“integrate”‬ في سياق إدارة المراجعات.

أمر git request-pull تعطيه: (١) الفرع الأساس الذي تريدهم أن يجذبوا فرعك إليه، و (٢) رابط مستوع جت الذي تريدهم أن يجذبوا منه؛ ويُنتج لك خلاصة التعديلات التي تسألهم أن يجذبوها. فمثلا، إذا أرادت سميرة أن ترسل إلى سمير طلب جذب، وقد صنعت إيداعين في فرع الموضوع الذي دفعت إليه للتو، يمكنها تنفيذ هذا الأمر:

$ git request-pull origin/master myfork
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
Sameera Samara (1):
        Create new function

are available in the git repository at:

  https://githost/simplegit.git featureA

Sameera Samara (2):
      Add limit to log function
      Increase log output to 30 from 25

 lib/simplegit.rb |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

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

وإن الأسهل غالبًا في مشروع لستَ القائم عليه أن تُبقي دومًا فرعك الرئيس المحلي يتبع الفرع البعيد المناظر له (مثلا master الخاص بك يتبع origin/master)، وأن تفعل كل شيء في فروع موضوعات، حتى تستطيع أن تلغيها بسهولة إن رُفضت. وكذلك فصل مسارات العمل في فروع موضوعات يسهّل عليك إعادة تأسيسها إذا تحرك رأس المستودع الرئيس خلال عملك ولم تبقَ إيداعاتك قابلة للتطبيق بنظافة. فمثلًا إذا أردت أن ترسل إلى المشروع تعديلات في موضوع آخر، فلا تستمر بالعمل في فرع الموضوع السابق الذي دفعته؛ بل ابدأ من جديد باشتقاق الفرع الرئيس للمستودع الأصل:

$ git checkout -b featureB origin/master
  ... عمل ...
$ git commit
$ git push myfork featureB
$ git request-pull origin/master myfork
  ... إرسال طلب الجذب الناتج بالبريد الشابكي إلى القائم على المشروع ...
$ git fetch origin

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

تاريخ الإيداعات عند بدء العمل في `featureB`
شكل ٦٩. تاريخ الإيداعات عند بدء العمل في featureB

لنقُل إن القائم على المشروع قد جذب عددًا من الرقع الأخرى ثم حاول جذب فرعك الأول فلم يجده يقبل الدمج بنظافة. يمكنك عندئذٍ أن تعيد تأسيس هذا الفرع على origin/master وتحلّ النزاعات نيابةً عن القائم على المشروع، ثم تُعيد إرسال تعديلاتك:

$ git checkout featureA
$ git rebase origin/master
$ git push -f myfork featureA

هذا يحرّر التاريخ ليبدو هكذا مثل شكل تاريخ الإيداعات بعد العمل في featureA.

تاريخ الإيداعات بعد العمل في `featureA`
شكل ٧٠. تاريخ الإيداعات بعد العمل في featureA

ولأنك أعدت تأسيس الفرع، فعليك الدفع عَنوةً (خيار -f مع أمر push)، حتى تبدل فرع featureA على الخادوم بإيداع ليس مبنيًّا عليه. ويمكنك بدلًا من ذلك أن تدفع العمل الجديد إلى فرع آخر على الخادوم (مثلا featureAv2).

لنرَ موقفًا محتملًا آخر: نظر القائم على المشروع إلى عملك في فرعك الثاني، وراقه المبدأ، لكنه ودّ أن تغيّر بعض التفاصيل. ورأيت أن تنتهز الفرصة لتعيد تأسيسه على الفرع الرئيس الحالي للمشروع. فبدأت فرعًا جديدًا من فرع origin/master الحالي، وهرست إيداعات featureB إليه (‪“squash”‬)، وحللت أي نزاعات ظهرت، وغيّرت له ما أراد، ثم دفعت هذا إلى فرع جديد على الخادوم:

$ git checkout -b featureBv2 origin/master
$ git merge --squash featureB
  ... change implementation ...
$ git commit
$ git push myfork featureBv2

خيار الهرس --squash يتناول كل العمل الذي في الفرع المدموج، ويهرسه (يجعله إيداعًا واحدًا) فيصير حال المستودع كأن ما حدث هو دمج حقيقي، بغير أن يصنع إيداع دمج. يعني هذا أن إيداعك الجديد سيكون له إيداع أب واحد، ويسمح لك باشتمال كل التعديلات التي في فرع آخر، ثم زيادة تعديلات أخرى عليها قبل صناعة الإيداع الجديد. وفي حالة الدمج العادي (وليس الهرس)، قد يفيدك أيضًا الخيار --no-commit لتأجيل إيداع الدمج.

عندئذٍ يمكنك إعلام القائم على المشروع أنك قد أتممت التعديلات المطلوبة، وأنه سيجدها في فرع featureBv2.

تاريخ الإيداعات بعد العمل في `featureBv2`
شكل ٧١. تاريخ الإيداعات بعد العمل في featureBv2