يا جماعة الخير، السلام عليكم ورحمة الله.
خلوني أحكيلكم قصة صارت معي قبل كم سنة، قصة علّمتني درس ما بنساه. كنا فريق صغير، شغالين على مشروع كبير ومهم للشركة، والضغط علينا كان فوق ما بتتصوروا. قرب موعد التسليم (الديدلاين)، وكنا سهرانين بالمكتب للصبح، والقهوة ما عادت تجيب نتيجة. الكل تعبان ومرهق، بس شغالين زي النحل.
في ليلة من هالليالي، وبعد ما خلصنا ميزة جديدة كنا بنشتغل عليها شهور، واحد من الشباب الطيبة عمل push للكود تبعه، وتوكلنا على الله وعملنا merge للفرع الرئيسي. الكل فرحان ومبسوط، وروحنا على بيوتنا ونحنا بنحلم بالإجازة. صحيت ثاني يوم الصبح على صوت تلفوني برن زي المجنون. فتحت الخط وإلا مدير المشروع بصوت معصّب: “أبو عمر، السيستم كله واقع! الـ build فشل على السيرفر، شو اللي عملتوه؟”.
رجعت عالمكتب ركض، وبدأنا رحلة البحث عن السبب. بعد ساعات من التوتر والضغط، شو اكتشفنا؟ سطر كود فيه قوس ناقص… آه والله، قوس واحد ناقص في ملف إعدادات JSON. خطأ تافه، خطأ ما بستاهل دقيقة تفكير، بس كلفنا ساعات من العمل الضايع، وسمعة بدن، ووجعة راس ما الها أول من آخر. وقتها قلت لحالي: “لهون وبس! بالزلمة هالشغلانة ما بتنعاد”. لازم نلاقي طريقة تمنع هاي الأخطاء السخيفة توصل للفرع الرئيسي من أصله. ومن هنا بدأت رحلتي مع عالم جميل اسمه “خطافات ما قبل الإيداع” أو الـ Pre-commit Hooks.
ما هي “خطافات ما قبل الإيداع” (Pre-commit Hooks)؟ ببساطة يا جماعة
فكرة الـ Hooks في عالم البرمجة، وخصوصاً مع Git، بسيطة وعبقرية. تخيل Git زي مبنى كبير فيه أبواب ونوافذ. الـ Hooks هي الحارس اللي واقف على كل باب. قبل ما Git يعمل أي عملية مهمة (مثل commit, push, merge)، بروح يسأل الحارس: “يا حارس، الأمور تمام؟ أفوّت هالشغلة ولا لأ؟”. الحارس (اللي هو عبارة عن سكربت إحنا بنكتبه) بفحص الشغلة، وإذا كل شي سليم بيعطي الضوء الأخضر، وإذا فيه مشكلة بمنع العملية كلها.
لماذا “ما قبل الإيداع” (Pre-commit) بالذات؟
من بين كل “الحراس” اللي بوفرهم Git، أهم واحد فيهم من وجهة نظري هو حارس “ما قبل الإيداع” أو pre-commit. ليش؟ لأنه بشتغل في أبكر مرحلة ممكنة.
لما تيجي تعمل git commit، وقبل ما Git يسجل الكود تبعك في تاريخ المشروع بشكل دائم، بيشتغل هذا الخطاف. وظيفته يفحص الكود اللي أنت بتحاول تعمل له commit. لو لقى فيه مشاكل (مثل أخطاء تنسيق، متغيرات غير مستخدمة، أسرار أو مفاتيح API بالغلط)، بيصرخ وبيقول “ممنوع الدخول!” وبيلغي عملية الـ commit كلها. ما في كود سيء بيدخل على تاريخ المشروع من الأساس.
تشبيه بسيط: الـ Pre-commit hook هو زي المدقق الإملائي في برنامج Word. قبل ما تبعت الإيميل المهم، هو بنبهك على الأخطاء الإملائية والنحوية عشان ما تتفشل قدام المدير. هو صديقك الصدوق اللي بحميك من نفسك وأنت مستعجل.
العدة والأدوات: كيف نبدأ مع إطار عمل pre-commit؟
زمان، كانت كتابة هاي الخطافات وإدارتها شغلانة معقدة. كل مطور لازم ينسخ السكربتات يدويًا لمجلد .git/hooks عنده. بس الحمد لله، اليوم صار عنا أدوات بتخلي الموضوع سهل جداً. أشهر وأفضل أداة هي إطار عمل اسمه pre-commit (نعم، نفس اسم الخطاف)، وهو أداة مكتوبة بلغة بايثون.
خلونا نمشي خطوة بخطوة ونشوف كيف نجهزها.
الخطوة الأولى: التثبيت (يا دوب كبسة زر)
أول شي، لازم نثبت الأداة على جهازنا. لو عندك بايثون و pip، الموضوع بسيط جداً. افتح الطرفية (Terminal) واكتب الأمر التالي:
pip install pre-commit
هذا الأمر بثبت الأداة على مستوى النظام، وبتصير متاحة لكل مشاريعك.
الخطوة الثانية: ملف الإعدادات .pre-commit-config.yaml
هذا هو قلب النظام كله. في جذر مشروعك (root directory)، بدك تنشئ ملف جديد اسمه .pre-commit-config.yaml. هذا الملف هو اللي بنحدد فيه شو هي الفحوصات (الخطافات) اللي بدنا إياها تشتغل.
هذا مثال لملف إعدادات أساسي ومفيد جداً لمعظم المشاريع (خصوصاً مشاريع بايثون وويب):
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace # بحذف المسافات الزايدة في آخر السطر
- id: end-of-file-fixer # بتأكد إنه كل ملف بنتهي بسطر فاضي
- id: check-yaml # بفحص صحة ملفات الـ YAML
- id: check-added-large-files # بمنع إضافة ملفات كبيرة بالخطأ
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black # المنسق التلقائي لكود بايثون (ما في نقاش على الستايل بعد اليوم)
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
hooks:
- id: flake8 # مدقق جودة كود بايثون (بلاقي الأخطاء المنطقية والمتغيرات غير المستخدمة)
شرح بسيط للملف:
repos: قائمة بالمستودعات (repositories) اللي بتحتوي على الخطافات اللي بدنا نستخدمها.repo: رابط مستودع Git اللي فيه الخطاف.rev: رقم الإصدار (version) اللي بدنا نستخدمه. مهم جداً نثبت الإصدار عشان ما يتغير السلوك فجأة.
– hooks: قائمة بالخطافات اللي بدنا نفعّلها من هذا المستودع، وكل خطاف له id فريد.
الخطوة الثالثة: تفعيل الخطافات في مستودعك
بعد ما جهزنا ملف الإعدادات، باقي خطوة واحدة بس. لازم نحكي لـ Git في هذا المشروع إنه يستخدم هاي الإعدادات. بنعمل هيك عن طريق الأمر التالي (بتنفذه مرة واحدة لكل مشروع):
pre-commit install
هذا الأمر ببساطة بنشئ سكربت صغير في .git/hooks/pre-commit وبيوصله بإطار العمل اللي ثبتناه. هيك، كل مرة أي مطور في الفريق (بعد ما ينفذ هذا الأمر) بحاول يعمل commit، رح تشتغل الفحوصات اللي حددناها في ملف الـ YAML تلقائياً.
سيناريو عملي: لنشاهد السحر بأعيننا
كلام نظري كثير، صح؟ تعالوا نشوف مثال عملي.
تخيل إني كتبت كود بايثون “معفشك” شوي عن قصد في ملف اسمه main.py:
# main.py
import os
def my_func( ):
name = "Abu Omar"
print("Hello World" ) # في مسافة زايدة هون
return 123
الكود شغال، لكن تنسيقه سيء جداً حسب معايير أداة black، وفيه متغير name غير مستخدم حسب معايير flake8، وفيه مسافة بيضاء زائدة في آخر السطر.
الآن، بحاول أعمل commit لهذا الكود:
$ git add main.py
$ git commit -m "إضافة دالة جديدة"
فوراً، رح أشوف المخرجات التالية على شاشتي:
Trim Trailing Whitespace...........(no files to check)Skipped
Fix End of Files.................(no files to check)Skipped
Check Yaml.......................(no files to check)Skipped
Check for added large files......(no files to check)Skipped
Black....................................................Failed
- hook id: black
- files were re-formatted:
main.py
Flake8...................................................Failed
- hook id: flake8
- exit code: 1
main.py:5:5: F841 local variable 'name' is assigned to but never used
لاحظوا الجمال! 🤩
- أداة
blackاشتغلت، وشافت إنه الملف تنسيقه غلط. وبما إنها أداة “ذكية”، قامت بتعديل الملف تلقائياً عشان يصير شكله مرتب. - أداة
flake8اشتغلت، ولقت خطأ منطقي (متغير غير مستخدم)، وعرضتلي رسالة واضحة بالملف ورقم السطر. - الأهم من كل هذا، عملية الـ commit نفسها فشلت. الكود السيء لم يدخل إلى تاريخ المشروع أبداً.
الآن، كل اللي علي أعمله هو: أفتح ملف main.py وأشوف شو صار. رح ألاقي أداة black صلحت التنسيق تلقائياً:
# main.py (بعد تعديل black)
import os
def my_func():
name = "Abu Omar"
print("Hello World")
return 123
بشوف رسالة flake8 وبقرر إما أحذف متغير name أو أستخدمه. بعد ما أصلح المشكلة، بعمل git add main.py مرة ثانية وبحاول أعمل commit. هذه المرة، كل الفحوصات رح تنجح، والـ commit رح يتم بنجاح.
نصائح من أبو عمر: كنوز من الخبرة
بعد سنوات من استخدام هاي الأداة في كل مشاريعي، جمعتلكم شوية نصائح من القلب:
- ابدأ صغيراً ثم توسّع: لا تتحمس وتضيف 20 خطاف من أول يوم. رح تلاقي مقاومة من الفريق. ابدأ بـ 2-3 خطافات أساسية (مثل
trailing-whitespaceوblack/prettier)، ولما الفريق يتعود عليها، ابدأ بإضافة المزيد تدريجياً. - اجعلها جزءاً من ثقافة الفريق: اشرح للفريق إنه هاي الأداة مش عشان “نصيد أخطاء بعض”، بل هي مساعد آلي (روبوت) بنظفل الكود تبعنا ببلاش وبخلي مراجعات الكود أسرع وأكثر تركيزاً على المنطق بدلاً من التنسيق.
- لا تنسَ الـ CI/CD: دائماً فيه شخص “ذكي” رح يحاول يتجاوز الخطافات باستخدام
git commit --no-verify. عشان هيك، ضيف خطوة في الـ CI/CD pipeline تبعك بتشغل نفس الفحوصات. الأمر بسيط:pre-commit run --all-files. هاي بتكون شبكة الأمان الثانية. - التخصيص هو المفتاح: أحياناً بتحتاج تستثني ملفات معينة من فحص معين. إطار العمل
pre-commitبسمحلك تعمل هيك بسهولة في ملف الإعدادات باستخدام خاصيةexclude. - إضافتها لمشروع قديم: لو عندك مشروع قديم وكبير، تشغيل الخطافات على كل الملفات رح يكون كابوس. الحل هو إنك تبدأ بتشغيلها على الملفات اللي بتتغير فقط (وهذا هو السلوك الافتراضي). ومع الوقت، كل ما عدلت على ملف، رح يتنظف تلقائياً.
الخلاصة: ارتاح من وجعة الراس! 😌
يا جماعة، الاستثمار في أتمتة جودة الكود هو أفضل استثمار ممكن يعمله أي فريق برمجي. خطافات ما قبل الإيداع، وخصوصاً مع إطار عمل pre-commit، بتحول عملية كتابة الكود من فوضى ونقاشات لا تنتهي حول المسافات والفواصل، إلى عملية منظمة وموحدة.
الفوائد واضحة:
- كود نظيف ومتسق: كل الكود في المشروع بصير كأنه مكتوب بنفس الشخص.
- اكتشاف مبكر للأخطاء: بنصيد الأخطاء التافهة قبل ما تكلفنا وقت وجهد.
- مراجعات كود أسرع وأفضل: المراجعين بركزوا على منطق العمل (Business Logic) بدل ما يضيعوا وقتهم في تعليقات مثل “نسيت فاصلة منقوطة”.
- إنتاجية أعلى وسعادة أكبر: المطور برتاح من المهام الروتينية المزعجة وبركز على الإبداع وحل المشاكل الحقيقية.
نصيحتي الأخيرة إلكم: لا تنتظروا تصير معكم قصة زي قصتي عشان تقتنعوا. ابدأوا اليوم. ضيفوا ملف .pre-commit-config.yaml لمشروعكم القادم، وشوفوا الفرق بنفسكم. صدقوني، رح تدعولي.