| # | القسم |
|---|---|
| 1 | التعاون: نموذجان |
| 2 | Fork و clone |
| 3 | مزامنة الـ fork (upstream) |
| 4 | القضايا |
| 5 | ممارسات الفريق الجيدة |
| 6 | اختبار — سير العمل التعاوني |
| 7 | تطبيق عملي — المساهمة عبر fork |
| 8 | الخلاصة |
للعمل جماعة على مستودع، يوجد نموذجان كبيران للتعاون. الاختيار يعتمد أساساً على من له حق الكتابة في المستودع.
| النموذج | المبدأ | الحالة النموذجية |
|---|---|---|
| الفرع المشترَك | لكل الأعضاء حق الكتابة؛ كل شخص ينشئ فروعه في المستودع نفسه | فريق داخلي، شركة |
| Fork و pull | ننسخ المستودع على حسابنا، نعمل فيه، ثم نقترح طلب سحب نحو الأصل | مصدر مفتوح، مساهمون خارجيون |
في الشركة نستخدم تقريباً دائماً الفرع المشترَك (رأيناه في الدروس 01–03). للمساهمة في مشروع مفتوح المصدر ولست عضواً فيه، نمرّ بـ fork.
الـ fork نسخة شخصية من مستودع على حسابك في GitHub. تملك فيه كل الحقوق، دون المساس بالأصل. أما الـ clone فينزّل مستودعاً على جهازك المحلي.
لا تخلط :
| المصطلح | أين؟ | الفعل |
|---|---|---|
| Fork | على GitHub | ينسخ المستودع إلى حسابك |
| Clone | من GitHub إلى جهازك | ينزّل المستودع محلياً |
| origin | الـ fork البعيد الخاص بك | حيث تدفع |
| upstream | المستودع الأصلي | المصدر الذي تتابعه |
# 1. الـ fork عبر زر Fork على GitHub (أو CLI)
gh repo fork projet/app --clone
# المكافئ اليدوي بعد fork:
# 2. استنساخ الـ fork الخاص بك
git clone https://github.com/vous/app.git
cd app
# 3. التحقق من الـ remote
git remote -v
# origin https://github.com/vous/app.git (fetch/push)الـ fork «صندوق رمل» لك: يمكنك كسر كل شيء بلا خطر على المشروع الأصلي. عندما يصبح عملك جاهزاً، يقترحه طلب سحب على المشرف، الذي يقرر قبوله.
تمرين مصغّر — بـ gh، انسخ مستودع projet/app (fork) واستنسخه على جهازك بأمر واحد.
gh repo fork projet/app --clone
أثناء عملك، يتطوّر المستودع الأصلي. لا يتحدّث الـ fork وحده. يجب إضافة remote اسمه upstream يشير إلى الأصل، ثم استرجاع تغييراته بانتظام.
# 1. إعلان المستودع الأصلي باسم upstream
git remote add upstream https://github.com/projet/app.git
# 2. استرجاع آخر تغييراته
git fetch upstream
# 3. تحديث main المحلي
git switch main
git merge upstream/main
# 4. الدفع نحو الـ fork الخاص بك
git push origin main| الـ Remote | الدور | اتجاه الاستخدام |
|---|---|---|
origin | الـ fork الخاص بك | push عملك |
upstream | المستودع الأصلي | fetch تحديثات الآخرين |
المزامنة المبكرة والمتكررة مع
upstreamتمنع «انحراف» الـ fork عن المشروع. كلما انتظرت أكثر، كثرت التعارضات يوم طلب السحب.
تمرين مصغّر — اكتب الأمر لإعلان المستودع الأصلي https://github.com/projet/app.git كـ remote باسم upstream.
git remote add upstream https://github.com/projet/app.git
القضية (issue) تذكرة: مكان للإبلاغ عن خطأ، أو اقتراح ميزة، أو طرح سؤال. هو نظام المتابعة لمشروع GitHub.
ما نضعه في قضية خطأ جيدة :
| العنصر | مثال |
|---|---|
| عنوان واضح | «انهيار عند النقر على تصدير» |
| خطوات إعادة الإنتاج | 1. افتح X، 2. انقر Y… |
| السلوك المتوقَّع | «يُنزَّل الملف» |
| السلوك المرصود | «يغلق التطبيق» |
| البيئة | نظام التشغيل، المتصفح، الإصدار |
# إنشاء قضية من الطرفية
gh issue create --title "انهيار عند النقر على تصدير" \
--body "الخطوات: 1) افتح X 2) انقر تصدير ← يغلق التطبيق."
# سرد القضايا المفتوحة
gh issue list
# ربط طلب سحب بقضية: في وصف طلب السحب
# Closes #42 ← يغلق القضية 42 تلقائياً عند الدمجالتسميات تنظّم القضايا: bug، enhancement، documentation، good first issue، help wanted…
تحوّل القضايا جملة «ينبغي تصحيح هذا يوماً» إلى مهام قابلة للتتبّع والنقاش. ربط طلب سحب بـ
Closes #Nيغلق القضية تلقائياً عند الدمج: صفر نسيان.
تمرين مصغّر — بـ gh، أنشئ قضية عنوانها «انهيار عند النقر على تصدير».
gh issue create --title "انهيار عند النقر على تصدير" --body "يغلق التطبيق عند النقر على تصدير."
أبعد من الأوامر، يقوم التعاون الفعّال على اتفاقيات مشتركة. هذه التي تصنع الفرق.
| الممارسة الجيدة | عملياً |
|---|---|
| رسائل إيداع واضحة | «يصحّح حساب ضريبة القيمة المضافة»، لا «update» |
| اتفاق تسمية | feature/، fix/، docs/ للفروع |
| فروع قصيرة | ادمج مبكراً لتقليل التعارضات |
| طلبات صغيرة ومراجَعة | مراجعة جدية، أخطاء أقل |
main قابلاً للنشر دائماً | لا نكسر الفرع الرئيسي أبداً |
ملف README + CONTRIBUTING | يوثّق كيف نساهم |
معيار « Conventional Commits »، الشائع جداً :
git commit -m "feat: إضافة تصدير CSV"
git commit -m "fix: يصحّح انهيار تسجيل الدخول"
git commit -m "docs: تحديث README"
git commit -m "refactor: يبسّط خدمة الدفع"| البادئة | المعنى |
|---|---|
feat: | ميزة جديدة |
fix: | تصحيح خطأ |
docs: | توثيق |
refactor: | إعادة كتابة دون تغيير السلوك |
test: | إضافة اختبارات أو تعديلها |
فريق يتقاسم الاتفاقيات لا يحتاج إلى التشاور بلا توقف: الشفرة والإيداعات والفروع «تتكلم» اللغة نفسها. هذه سيولة التعاون.
تمرين مصغّر — أضفت للتو تصدير CSV. اكتب رسالة الإيداع بصيغة Conventional Commits.
git commit -m "feat: إضافة تصدير CSV" (البادئة feat: لميزة جديدة).
السؤال 1: ما الـ fork؟
a) دمج فرعين
b) نسخة شخصية من مستودع على حسابك في GitHub
c) نوع تعارض
d) حذف السجل
الإجابة: b) — ينسخ الـ fork المستودع إلى حسابك؛ تعمل فيه بحرية دون المساس بالأصل.
السؤال 2: ما الفرق بين origin و upstream في نموذج fork و pull؟
a) لا فرق، هما مترادفان
b) origin هو الـ fork الخاص بك، و upstream هو المستودع الأصلي
c) origin محلي، و upstream على قرصك
d) upstream يُستخدم لحذف الفروع
الإجابة: b) — ندفع نحو origin (الـ fork) ونسترجع التحديثات من upstream (الأصل).
السؤال 3: لماذا تُستخدم القضية؟
a) لتجميع الشفرة
b) للإبلاغ عن خطأ، أو اقتراح ميزة، أو مناقشة مهمة
c) لدمج الفروع تلقائياً
d) لاستنساخ مستودع
الإجابة: b) — القضية تذكرة متابعة: خطأ، فكرة، سؤال، منظَّمة بتسميات.
السؤال 4: ماذا يفعل Closes #42 في وصف طلب سحب؟
a) يحذف الإيداع 42
b) يغلق القضية #42 تلقائياً عند دمج طلب السحب
c) يفتح قضية جديدة
d) يلغي طلب السحب
الإجابة: b) — الكلمة المفتاح Closes (أو Fixes) تربط طلب السحب بالقضية وتغلقها عند الدمج.
السؤال 5: ماذا تعني بادئة الإيداع fix: في Conventional Commits؟
a) ميزة جديدة
b) تصحيح خطأ
c) توثيق
d) اختبار
الإجابة: b) — fix: يشير إلى تصحيح خطأ؛ feat: ميزة، و docs: توثيق.
تريد المساهمة في مشروع مفتوح المصدر projet/app ولست عضواً فيه. نفّذ دورة نموذج fork و pull كاملة :
upstream وزامن main.# 1. fork + استنساخ
gh repo fork projet/app --clone
cd app
# 2. إضافة upstream والمزامنة
git remote add upstream https://github.com/projet/app.git
git fetch upstream
git switch main
git merge upstream/main
git push origin main
# 3. التفريع، الإيداع، الدفع
git switch -c fix/correction-typo-readme
# ... تصحيح ملف README ...
git commit -am "fix: يصحّح خطأ في README"
git push -u origin fix/correction-typo-readme
# 4. فتح طلب سحب نحو المستودع الأصلي
gh pr create --repo projet/app \
--base main --head vous:fix/correction-typo-readme \
--title "fix: خطأ مطبعي في README" \
--body "يصحّح زلة. Closes #8"النتيجة المتوقعة :
| الخطوة | التحقق |
|---|---|
| أُنشئ الـ fork | يظهر المستودع تحت github.com/vous/app |
أُضيف upstream | git remote -v يسرد origin و upstream |
| دُفع الفرع | الفرع موجود في الـ fork الخاص بك (origin) |
| فُتح طلب السحب | الهدف projet/app:main من vous:fix/... |
| قضية مرتبطة | Closes #8 سيغلق القضية عند دمج المشرف |
$ git remote -v
origin https://github.com/vous/app.git (push)
upstream https://github.com/projet/app.git (fetch)ينطلق طلب السحب من فرعك (
vous:fix/...) نحوmainللمستودع الأصلي. يراجعه المشرف ويقرر الدمج: ساهمت في المصدر المفتوح دون أن تملك يوماً حق كتابة على المشروع.
Closes #N يربط ويغلق عند الدمج.main مستقر.feat:، fix:، docs:…) توحد الرسائل.انتهت الوحدة 02: تعرف الآن التفريع والدمج وفتح طلبات السحب والتعاون على نطاق واسع. الوحدة 03 تواصل مسار DevOps مع التكامل المستمر (CI/CD)، الذي سيؤتمت الاختبارات والنشر انطلاقاً من طلبات السحب نفسها.
جميع الحقوق محفوظة. يُحظَر نسخ هذه الدورة أو نشرها أو استخدامها أو تكييفها، كلياً أو جزئياً، دون إذن كتابي مسبق من الدكتور هيثم رحومة.
دورة من إعداد الدكتور هيثم رحومة — تطوير ونشر حلول البيانات