٥، ٥، المساهمة في مشروع
— فريق خصوصي بمدير دمج
سنتناول الآن أدوار المساهمين في مجموعة خصوصية أكبر. ستتعلم كيف تعمل في بيئة فيها مجموعات صغيرة تتعاون في أمور مختلفة ثم يدمج عملهم أحدٌ آخر.
لنقُل إن سمير وسميرة يعملان معًا في ميزة واحدة (ولتكن “featureA”)، بينما تعمل سميرة مع سمر، وهي مطوِّرة ثالثة في الفريق، تعملان في ميزة أخرى (ولتكن “featureB”). في هذه الحالة تتبع الشركة نوعًا من أسلوب مدير الدمج، حيث لا يدمج أعمال مجموعات المبرمجين إلا مهندسون محددون، والفرع الرئيس للمستودع الرئيس لا يدفع إليه إلا هؤلاء المهندسون. في هذا الموقف، كل العمل يحدث في فروع مجموعات المبرمجين، ثم يجذبه الدامجون فيما بعد.
لنتابع سميرة وهي تعمل على الميزتين وتتعاون مع مبرمجَيْن مختلفين في آن واحد في هذه البيئة.
استنسخت سميرة مستودعها، ثم رأت أن تعمل على featureA أولًا.
فأنشأت فرعًا جديدًا لهذه الميزة وبدأت بالعمل فيه:
# حاسوب سميرة
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ vim lib/simplegit.rb
$ git commit -am 'Add limit to log function'
[featureA 3300904] Add limit to log function
1 files changed, 1 insertions(+), 1 deletions(-)
عندئذٍ احتاجت أن تشارك عملها مع سمير، فدفعت إيداعات فرعها featureA إلى الخادوم.
ولكن ليس لسميرة إذن الدفع إلى الفرع الرئيس (الدامجون فقط لديهم هذا الإذن)، فاحتاجت إلى الدفع إلى فرع آخر حتى تتعاون مع سمير:
$ git push -u origin featureA
...
To sameera@githost:simplegit.git
* [new branch] featureA -> featureA
ثم أرسلت سميرة إلى سمير بريدًا تخبره بدفعها شيئًا إلى فرع اسمه featureA حتى ينظر فيه.
وحتى يرد سمير، رأت سميرة أن تشرع في العمل على featureB مع سمر.
ولكي تبدأ، أنشأت فرع موضوع جديد مبني على الفرع الرئيس للخادوم:
# حاسوب سميرة
$ git fetch origin
$ git checkout -b featureB origin/master
Switched to a new branch 'featureB'
ثم صنعت سميرة إيداعين في فرع featureB الذي أنشأته:
$ vim lib/simplegit.rb
$ git commit -am 'Make ls-tree function recursive'
[featureB e5b0fdc] Make ls-tree function recursive
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'Add ls-files'
[featureB 8512791] Add ls-files
1 files changed, 5 insertions(+), 0 deletions(-)
يبدو الآن مستودع سميرة هكذا:
ثم وجدت أن عملها جاهزٌ للدفع، لكن وصلها بريد من سمر أنها قد أنشأت فرعًا فيه بعض العمل على الميزة الثانية (“featureB”) ودفعته إلى الخادوم في الفرع featureBee.
فتحتاج سميرة إلى دمج تلك التعديلات في عملها قبل دفعه إلى الخادوم.
فأولًا استحضرت سميرة تعديلات سمر بأمر الاستحضار:
$ git fetch origin
...
From sameera@githost:simplegit
* [new branch] featureBee -> origin/featureBee
وسميرة ما زالت في فرع featureB الخاص بها، فتستطيع الآن دمج عمل سمر في فرعها بأمر الدمج:
$ git merge origin/featureBee
Auto-merging lib/simplegit.rb
Merge made by the 'recursive' strategy.
lib/simplegit.rb | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
عندئذٍ أرادت سميرة دفع عمل “featureB” المدموج إلى الخادوم، لكنها لم تشأ دفع فرعها featureB نفسه؛
فلأن سمر قد أنشأت فرع featureBee على الخادوم، فأرادت سميرة أن تدفع إلى ذلك الفرع نفسه، وذلك بالأمر:
$ git push -u origin featureB:featureBee
...
To sameera@githost:simplegit.git
fba9af8..cd685d1 featureB -> featureBee
يسمى هذا «مُعرِّف إشارة» (“refspec”).
انظر فصل معرف الإشارة (refspec) لنقاش مفصّل عن معرِّفات الإشارة في جت وعن أمور أخرى يمكن أن تفعلها بها.
لاحظ كذلك الخيار -u؛ هذا اختصار --set-upstream («تعيين المنبع»)، الذي يهيّئ الفروع للدفع والجذب بسهولة أكبر فيما بعد.
فجأةً أتى سميرة بريدٌ من سمير يخبرها أنه دفع إيداعاتٍ إلى فرع featureA الذي يتعاونان فيه، ويسألها أن تنظر فيها.
فكررت سميرة أمر الاستحضار git fetch لاستحضار كل جديد لدى الخادوم، شاملًا بالطبع عمل سمير الأخير:
$ git fetch origin
...
From sameera@githost:simplegit
3300904..aad881d featureA -> origin/featureA
تستطيع سميرة الآن أن تعرض سجل أعمال سمير الجديدة بمقارنة محتوى الفرع المستحضَر حديثًا featureA مع نسختها المحلية من الفرع نفسه:
$ git log featureA..origin/featureA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: Samir Samara <samsam@example.com>
Date: Fri May 29 19:57:33 2009 -0700
Increase log output to 30 from 25
فإذا راق سميرة ما رأت، فتستطيع دمج عمل سمير في فرع featureA الخاص بها بالأمر:
$ git checkout featureA
Switched to branch 'featureA'
$ git merge origin/featureA
Updating 3300904..aad881d
Fast forward
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
وأخيرًا قد تود سميرة أن تغير أشياءً يسيرة فيه بعد الدمج، فيمكنها عمل هذه التعديلات، وإيداعها في فرع featureA المحلي الخاص بها، ثم دفع الناتج النهائي إلى الخادوم:
$ git commit -am 'Add small tweak to merged content'
[featureA 774b3ed] Add small tweak to merged content
1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To sameera@githost:simplegit.git
3300904..774b3ed featureA -> featureA
والآن يبدو تاريخ الإيداعات عند سميرة هكذا:
وفيما بعد، سميرة وسمير وسمر يخبرون الدامجين أن الفرعين featureA وfeatureBee على الخادوم جاهزان للدمج في الفرع الرئيس.
وبعد أن يدمجهما الدامجون في الفرع الرئيس، فإن الاستحضار منه سيجلب إيداع الدمج، فيصير التاريخ هكذا:
ينتقل الكثيرون إلى جت لقدرته هذه أن يقبل عمل عدة مجموعات على التوازي، ثم دمج مسارات عمل مختلفة بعد هذا. إنها لمزيّة عظيمة في جت أن يسمح لمجموعات فرعية صغيرة من فريق واحد أن تتعاون عبر الفروع البعيدة بغير الاضطرار إلى إشراك الفريق كله أو تعطيله. الشكل العام لتسلسل الأحداث الذي رأيته للتو هكذا: