مراجعة الكود كانت كابوساً: كيف أنقذتنا خطافات Pre-commit من جحيم الأخطاء التافهة؟

يا جماعة الخير، السلام عليكم ورحمة الله.

خلوني أحكيلكم قصة صارت معي قبل كم سنة، قصة علّمتني درس ما بنساه. كنا فريق صغير، شغالين على مشروع كبير ومهم للشركة، والضغط علينا كان فوق ما بتتصوروا. قرب موعد التسليم (الديدلاين)، وكنا سهرانين بالمكتب للصبح، والقهوة ما عادت تجيب نتيجة. الكل تعبان ومرهق، بس شغالين زي النحل.

في ليلة من هالليالي، وبعد ما خلصنا ميزة جديدة كنا بنشتغل عليها شهور، واحد من الشباب الطيبة عمل 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

لاحظوا الجمال! 🤩

  1. أداة black اشتغلت، وشافت إنه الملف تنسيقه غلط. وبما إنها أداة “ذكية”، قامت بتعديل الملف تلقائياً عشان يصير شكله مرتب.
  2. أداة flake8 اشتغلت، ولقت خطأ منطقي (متغير غير مستخدم)، وعرضتلي رسالة واضحة بالملف ورقم السطر.
  3. الأهم من كل هذا، عملية الـ 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 لمشروعكم القادم، وشوفوا الفرق بنفسكم. صدقوني، رح تدعولي.

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

اختبارات الاداء والجودة

كنا نطلق الميزات على أمل ألا ينهار النظام: كيف أنقذنا اختبار الحِمل (Load Testing) باستخدام k6 من جحيم التخمين؟

هل تطلق ميزات جديدة وأنت تدعو الله ألا ينهار الخادم؟ في هذه المقالة، أشارككم قصة حقيقية عن كيف انتقلنا من التخمين والقلق إلى الثقة والبيانات...

11 مايو، 2026 قراءة المزيد
أتمتة العمليات

كانت ‘ليالي الإطلاق’ كابوساً: كيف أنقذنا ‘خط أنابيب CI/CD’ من جحيم النشر اليدوي؟

أتذكر جيداً تلك الليالي المليئة بالتوتر والأخطاء الكارثية. في هذه المقالة، أشارككم قصة حقيقية ومفصلة حول كيف انتقلنا كفريق من فوضى النشر اليدوي إلى عالم...

10 مايو، 2026 قراءة المزيد
نصائح برمجية

كان إطلاق الميزات الجديدة كابوساً: كيف أنقذتنا ‘أعلام الميزات’ (Feature Flags) من جحيم عمليات النشر عالية المخاطر؟

تذكرون تلك الليالي الطوال التي نقضيها في إصلاح الأخطاء بعد كل عملية نشر؟ في هذه المقالة، أشارككم قصة كيف حولت 'أعلام الميزات' (Feature Flags) عمليات...

10 مايو، 2026 قراءة المزيد
​معمارية البرمجيات

لماذا اتخذنا هذا القرار؟: كيف أنقذتنا ‘سجلات القرارات المعمارية’ (ADRs) من جحيم النسيان

أشارككم قصة حقيقية من قلب المعركة البرمجية، وكيف أن أداة بسيطة تُدعى "سجلات القرارات المعمارية" (ADRs) أصبحت طوق النجاة لفريقي. اكتشفوا كيف يمكن لتوثيق "لماذا"...

10 مايو، 2026 قراءة المزيد
خوارزميات

كان البحث في موقعنا كالبحث عن إبرة في كومة قش: كيف أنقذتنا ‘خوارزمية البحث الثنائي’ من جحيم تجربة المستخدم البطيئة؟

أتذكر جيدًا كيف كانت الشكاوى تنهال علينا بخصوص بطء البحث في موقعنا الجديد. في هذه المقالة، أشارككم قصة حقيقية حول كيف أنقذتنا العودة لأساسيات الخوارزميات،...

10 مايو، 2026 قراءة المزيد
تسويق رقمي

كنا نستهدف الجمهور الخطأ: كيف أنقذتنا ‘التجزئة التنبؤية بالذكاء الاصطناعي’ من جحيم هدر ميزانية الإعلانات؟

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

10 مايو، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

كان كل فريق يغني على ليلاه: كيف أنقذ “نظام التصميم” مشروعنا من الفوضى البصرية؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف انتقلنا من فوضى الواجهات وتعدد الأزرار إلى نظام تصميم موحد أنقذ المشروع. هذه ليست مجرد مقالة تقنية،...

10 مايو، 2026 قراءة المزيد
برمجة وقواعد بيانات

كانت استعلاماتنا تزحف كالسلحفاة: كيف أنقذتنا ‘فهارس قواعد البيانات المركبة’ من جحيم الاستعلامات البطيئة؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، كيف تحولنا من استعلامات SQL تستغرق دقائق إلى أخرى تتم في أجزاء من الثانية. اكتشفوا معنا سر "الفهارس...

10 مايو، 2026 قراءة المزيد
البودكاست