مشروع: تصميم سير عمل Git لفريق
مشروع: تصميم سير عمل Git لفريق
كل ما تناولناه في هذا البرنامج التعليمي — نماذج التفريع، ونظافة إعادة التأسيس، والتطوير القائم على الجذع، وأعلام الميزات، وبوابات مراجعة الكود، والخطافات، ومقارنة المستودعات — يتلخص في نتيجة عملية واحدة يحتاجها كل فريق هندسي في نهاية المطاف: وثيقة تصميم سير عمل Git تخبر كل مهندس بالضبط ماذا يفعل منذ لحظة بدء ميزة جديدة حتى لحظة إطلاقها في الإنتاج. هذا الدرس عملي بالكامل: ستنتج تلك الوثيقة لفريق واقعي، وتتخذ قرارات ملموسة مع مبررات حقيقية، وتربطها بملفات إعداد فعّالة.
الفريق النموذجي
أنت كبير مهندسي DevOps في شركة Nexora، شركة منتج تضم 40 موظفاً تتوزعون على ثلاثة فرق: Platform (8 مهندسين)، وGrowth (10 مهندسين)، وCore API (12 مهندساً)، إضافةً إلى فريق SRE الصغير المؤلف من 4 أشخاص. يشحنون منتجاً SaaS عدة مرات يومياً. الوضع الراهن مؤلم: فروع ميزات طويلة الأمد، وتعارضات دمج تستغرق ساعات لحلها، وعملية مراجعة غير متسقة، وإصدارات تعيق بعضها البعض.
الخطوة الأولى — اختيار نموذج التفريع المناسب
وضع Nexora — فرق متعددة، ونشر متكرر — يجعله مرشحاً مثالياً لنهج التطوير القائم على الجذع (TBD) مع فروع ميزات قصيرة الأمد (بحد أقصى يومين). نموذج Git Flow مستبعد صراحةً: فروع develop وrelease الطويلة ستجعل آلام الدمج الحالية أشد، لا أخف.
اتفاقية التفريع بسيطة لكنها صارمة:
main— الجذع. دائماً قابل للنشر. محمي. لا دفع مباشر.feature/{ticket-id}-short-description— مثلfeature/NX-412-user-invites. الحد الأقصى للعمر: يومان. إذا استغرقت الميزة وقتاً أطول، تُشحن خلف علم ميزة.fix/{ticket-id}-short-description— إصلاحات الأخطاء، نفس قواعد فروع الميزات.hotfix/{ticket-id}-short-description— حوادث الإنتاج فقط. يُدمج مباشرةً فيmainبعد مراجعة طارئة.
main كل ساعة، مما يجعل تعارضات الدمج أشد تعقيداً بصورة أسية. إذا لم تكن الميزة جاهزة، أخفِها خلف علم وادمج الكود على أي حال. الفرع يُشحن، لكن واجهة المستخدم لا.
الخطوة الثانية — حماية الفروع ومتطلبات الدمج
فرّض النموذج على مستوى المنصة. على GitHub، اضبط ما يلي لفرع main مُرمَّزاً كـ Terraform حتى لا يستطيع أحد إضعافه بهدوء:
علامة require_linear_history حرجة. تجبر كل طلب سحب على الدمج بالضغط أو إعادة التأسيس، مما يبقي تاريخ main خطاً نظيفاً قابلاً للمسح الثنائي. دمج الالتزامات ذات الآباء المتعددة يُعقّد git bisect وتوليد سجل التغييرات تلقائياً كثيراً.
تعيين المراجعين تلقائياً عبر CODEOWNERS:
الخطوة الثالثة — اتفاقية طلب السحب
طلب السحب هو أداة تواصل، ليس مجرد آلية تسليم كود. تُوحّد Nexora وصف الطلب بقالب مخزن في المستودع. كل حقل إلزامي — يفشل CI إذا حُذفت أقسام القالب:
الخطوة الرابعة — مخطط سير العمل الشامل
يوضح المخطط التالي الدورة الحياتية الكاملة للميزة من إنشاء التذكرة إلى وسم الإنتاج. يمكن لكل مهندس في Nexora الرجوع إلى هذه الصورة الواحدة عند الشك.
الخطوة الخامسة — اتفاقية الإصدار والإصدار الدلالي
يُفرض الإصدار الدلالي تلقائياً. تشغّل خطوة CI أداة semantic-release على كل دفعة إلى main، تقرأ الالتزامات التقليدية لتحديد ما إذا كان الرفع رئيسياً أو ثانوياً أو ترقيعياً:
feat: …— رفع ثانوي (1.4.0 → 1.5.0)fix: …— رفع ترقيعي (1.5.0 → 1.5.1)feat!: …أو تذييلBREAKING CHANGE:— رفع رئيسي (1.5.1 → 2.0.0)
يُنشئ روبوت الإصدار إصداراً على GitHub مع سجل تغييرات مُوَلَّد، ويدفع وسم git، ويُشغّل خط أنابيب نشر الإنتاج. لا أحد بحاجة لتذكر وسم إصدار — انضباط رسائل الالتزام يفعل ذلك تلقائياً.
commitlint كخطاف commit-msg في Git حتى يرى المهندسون خطأً فورياً عند كتابة رسالة غير متوافقة، قبل أن تصل إلى الخادم البعيد. أضفه إلى .husky/commit-msg:
npx --no -- commitlint --edit "$1"
هذا لا يكلف شيئاً ويمنع بأكمله حوادث "عطل رسالتي روبوت الإصدار".
الخطوة السادسة — تشغيل سير العمل فعلياً
وثيقة سير عمل لا يجدها أحد لا قيمة لها. تجعل Nexora سير العمل مفروضاً ذاتياً على كل طبقة:
- تسمية الفروع عبر خطاف — خطاف
pre-pushعلى جهاز كل مطوّر يرفض الدفع من فروع لا تطابق^(main|feature|fix|hotfix|release)/. يُثبَّت عبر سطر واحد في نصsetup.shالتمهيدي للمستودع. - حماية الفروع عبر Terraform — إعدادات GitHub هي كود. يتطلب طلب السحب لإضعافها موافقة اثنين من SRE.
- التعيين التلقائي عبر CODEOWNERS — لا يحتاج المهندسون لتذكّر من يضيفونه مراجعاً؛ GitHub يفعل ذلك عند فتح الطلب.
- الحقول الإلزامية في قالب الطلب — يفحص CI نص الطلب بحثاً عن عناوين القالب عبر GitHub API ويفشل إذا كان أي قسم فارغاً.
- روبوت الفروع القديمة — يعمل إجراء GitHub ليلاً، يعلّق على فروع أعمر من يومين، ويغلقها عند خمسة أيام. لا يمكن للمهندسين نسيان فروعهم الطويلة لأن الروبوت سيذكّرهم بصوت عالٍ.
- نظافة أعلام الميزات — كل علم له تاريخ
remove_byفي إعداد الأعلام. يعمل فحص الأعلام القديمة أسبوعياً وينشئ تذاكر Jira تلقائياً للإزالات المتأخرة.
تسليم وثيقة التصميم
نتيجتك النهائية لهذا المشروع هي ملف CONTRIBUTING.md مُلتزم به في جذر المستودع. يجب أن يشمل:
- اتفاقية تسمية الفروع مع أمثلة
- قاعدة عمر الفرع يومين وما تفعله بدلاً من ذلك (أعلام الميزات)
- كيفية فتح طلب سحب: حقول القالب، من يُعيَّن تلقائياً، الفحوصات المطلوبة
- استراتيجية الدمج (squash في main) والسبب
- تنسيق رسالة الالتزام (الالتزامات التقليدية) مع أمثلة
- عملية الإصدار: كيف يقرر semantic-release الإصدار
- عملية الإصلاح الطارئ: خطوة بخطوة، من تُخطر، اتفاقية مستوى الخدمة
- كيفية التصعيد إذا كانت قاعدة فرع محمي تعيق عملاً طارئاً مشروعاً
إيداع هذا الملف في main يُغلق الحلقة: سير العمل مُنسخ، قابل للمقارنة بين الإصدارات، ومكتشف من كل مهندس يستنسخ المستودع. مقرون بحماية الفروع عبر Terraform والخطافات المثبّتة بواسطة setup.sh، يصبح سير العمل موثقاً ومفروضاً معاً — الخاصيتان اللتان تجعلان أي سير عمل Git يعمل فعلاً على نطاق الفريق.