يا هلا بيكم يا جماعة الخير. اسمي أبو عمر، مطور برمجيات قضيت سنين عمري بين الأكواد والخوارزميات، وشفت من العجايب ما يكفي لكتابة مجلدات. اليوم بدي أحكيلكم قصة صارت معي ومع فريقي، قصة عن الإحباط واليأس، وكيف شعاع من نور الأتمتة أنقذنا من حفرة كنا نحفرها لأنفسنا كل يوم.
بتذكرها زي كأنه امبارح… كانت ليلة خميس، والكل بيستعد لعطلة نهاية الأسبوع. فجأة، رن جوالي. على الطرف الثاني كان صوت مدير المشروع، متوتر ومضغوط. “أبو عمر، الموقع واقع! في مشكلة كبيرة في الإنتاج والعملاء بشتكوا!”. يا ساتر! نزلت الكنافة من إيدي وركضت على اللابتوب. بعد ساعة من البحث والتحقيق والضغط النفسي، شو اكتشفنا؟
مطور جديد في الفريق، بحسن نية، كان بيعمل تعديل بسيط. لكنه نسي يمسح سطر console.log("test") من ملف JavaScript. هذا السطر، في بيئة الإنتاج مع متصفح قديم عند أحد العملاء الكبار، كان كفيل إنه يكسر الدنيا كلها ويعطل الموقع. المشكلة مش في المطور الجديد، كلنا بنغلط. المشكلة كانت فينا إحنا، في عمليتنا الهشة اللي سمحت لخطأ تافه زي هاد إنه يوصل للفرع الرئيسي (main branch) وينتشر للإنتاج.
في ذلك اليوم، بعد ما صلحنا المشكلة، عقدنا اجتماع طارئ. كان النقاش حاد: “لازم نراجع كل سطر كود!”، “لازم نعمل عشرين Pull Request review!”… كلها حلول بشرية، معرضة للخطأ والنسيان. وقتها، وقفت وحكيتلهم: “يا جماعة، الحل مش في زيادة الشغل اليدوي، الحل في أتمتة الدفاعات. لازم يكون عنا حارس بوابة يمنع هاي الأخطاء قبل ما تصير commit أصلاً”. ومن هنا، بدأت رحلتنا مع خطافات Git، أو الـ Git Hooks.
ما هي خطافات Git (Git Hooks) يا أبو عمر؟ وليش لازم نهتم؟
بكل بساطة، تخيل إن مستودع الكود (Git repository) تبعك هو بناية مهمة، والفرع الرئيسي main هو الخزنة اللي فيها كل الكنوز. خطافات Git هي الحراس اللي واقفين على كل باب وفي كل ممر. هم عبارة عن سكربتات (scripts) برمجية بتشتغل تلقائياً عند نقاط معينة في عملية Git.
عندما تحاول تعمل git commit، بيشتغل حارس. عندما تحاول تعمل git push، بيشتغل حارس ثاني. لو الحارس شاف إنه في إشي غلط (مثلاً، كود لا يتبع معايير الجودة، أو فيه أخطاء واضحة)، بيمنع العملية وبيقولك: “لو سمحت، ارجع صلح شغلك قبل ما تفوت!”.
هناك نوعان رئيسيان من الخطافات:
- خطافات العميل (Client-Side Hooks): بتشتغل على جهازك الشخصي. هاي هي اللي رح نركز عليها اليوم، لأنها خط الدفاع الأول. أمثلتها:
pre-commit,prepare-commit-msg,pre-push. - خطافات الخادم (Server-Side Hooks): بتشتغل على الخادم اللي مستضيف الـ repository (مثل GitHub أو GitLab). هاي مفيدة لفرض سياسات على مستوى الفريق كله، مثل منع الـ force push على فروع معينة.
بطل القصة: خطاف الـ pre-commit
من بين كل الخطافات، في واحد هو البطل الحقيقي لقصتنا: خطاف الـ pre-commit. هذا الخطاف هو الحارس اللي بيوقف على باب الـ commit. بيشتغل قبل ما Git يقوم بإنشاء الـ commit. إذا نجح السكربت تبع الخطاف، بتكمل عملية الـ commit. إذا فشل، بتتوقف العملية كلها، ولا يتم إنشاء أي commit، وبيعطيك رسالة بالخطأ.
طيب، شو ممكن نعمل فيه؟ (أمثلة عملية)
الجميل في الـ pre-commit هو إنه ممكن يعمل أي إشي بتقدر تبرمجه في سكربت. هاي بعض الاستخدامات اللي غيرت حياتنا:
- فحص جودة وتنسيق الكود (Linting & Formatting): هاي أهم شغلة. بنشغل أدوات مثل ESLint (لـ JavaScript) أو Flake8 (لـ Python) للتأكد من خلو الكود من الأخطاء الشائعة، وأدوات مثل Prettier أو Black لإعادة تنسيق الكود تلقائياً عشان كل الكود في المشروع يكون بنفس الشكل. وداعاً للنقاشات البيزنطية حول المسافات والفواصل!
- منع إضافة الأسرار (Secrets): كم مرة سمعت عن مطور بالغلط رفع مفتاح API أو كلمة سر على GitHub؟ باستخدام أدوات مثل
trufflehogأوgitleaksفي الـ pre-commit hook، بنقدر نعمل فحص تلقائي يمنع هاي الكارثة قبل وقوعها. - تشغيل الاختبارات الوحدوية السريعة (Unit Tests): ممكن تشغل مجموعة من الاختبارات الأساسية للتأكد من إنك ما كسرت إشي موجود. (نصيحة: الاختبارات الطويلة خليها لخطاف الـ
pre-pushأو لـ CI/CD server). - فحص صيغة رسائل الـ Commit: ممكن تفرض على الفريق يكتب رسائل commit واضحة وذات صيغة محددة (مثل Conventional Commits) عشان يكون تاريخ المشروع سهل القراءة والفهم.
يلا نشتغل: كيف نفعّل أول خطاف Git إلنا؟ (الطريقة اليدوية)
عشان تفهم المبدأ، خلينا نعمل أول خطاف بإيدينا. الموضوع أسهل مما بتتخيل.
في أي مستودع Git عندك، في مجلد مخفي اسمه .git. جواته في مجلد اسمه hooks. هذا المجلد بيحتوي على أمثلة لخطافات، كلها بتنتهي بـ .sample. عشان تفعّل أي واحد فيهم، كل اللي عليك تعمله هو إنك تشيل الـ .sample من اسمه.
خلينا نعمل خطاف pre-commit بسيط بيمنعنا من إضافة console.log في ملفات JavaScript.
- اذهب إلى مجلد المشروع في الـ terminal.
- أنشئ ملف جديد:
touch .git/hooks/pre-commit - اجعل الملف قابل للتنفيذ:
chmod +x .git/hooks/pre-commit - افتح الملف بأي محرر نصوص والصق الكود التالي:
#!/bin/sh
echo "تشغيل خطاف الـ pre-commit..."
# ابحث عن ملفات JavaScript المعدّلة (staged) التي تحتوي على "console.log"
# git diff --cached بيفحص فقط الملفات اللي أنت عملتلها "git add"
STAGED_JS_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep ".js$")
if [ -z "$STAGED_JS_FILES" ]; then
exit 0 # لا يوجد ملفات JS، استمر
fi
# تحقق من وجود "console.log" في هذه الملفات
if grep -q "console.log" $STAGED_JS_FILES; then
echo "🚫 خطأ: تم العثور على 'console.log' في أحد الملفات."
echo "الرجاء إزالته قبل تنفيذ الـ commit."
exit 1 # فشل الخطاف، أوقف الـ commit
fi
echo "✅ تمام، الأمور طيبة. استمر!"
exit 0 # نجاح الخطاف، اسمح بالـ commit
الآن، جرب تعدل أي ملف JavaScript، ضيف فيه سطر console.log("hello");، ثم نفذ git add . و git commit -m "test". رح تشوف كيف الخطاف رح يشتغل ويمنعك من إكمال العملية! سحر، مش هيك؟
الطريقة اليدوية منيحة، بس مش عملية… خلينا نصير محترفين!
الطريقة اليدوية ممتازة عشان نتعلم، لكنها بتعاني من مشكلة كبيرة: مجلد .git لا يتم إضافته لنظام إدارة الإصدارات. هذا يعني إن الخطافات اللي بتعملها رح تضل على جهازك فقط، وما رح تتشارك مع باقي الفريق. وهيك بنرجع لنفس المشكلة.
وهنا يأتي دور الأدوات الاحترافية اللي بتدير هاي العملية.
أهلاً وسهلاً في pre-commit: الأداة السحرية
pre-commit هي أداة مكتوبة بلغة Python (لكنها بتشتغل مع أي لغة برمجة) بتحل كل مشاكل الطريقة اليدوية. هي عبارة عن إطار عمل (framework) لإدارة الخطافات.
نصيحة أبو عمر: لا تخلط بين “خطاف الـ pre-commit” كحدث في Git، وبين “أداة pre-commit” كإطار عمل. الأداة بتساعدك تدير الحدث.
ليش هي سحرية؟
- ملف إعدادات مركزي: كل إعدادات الخطافات بتنحط في ملف واحد اسمه
.pre-commit-config.yaml. هذا الملف بتعمله commit وبترفعوا مع المشروع، فكل الفريق بيستخدم نفس الإعدادات. - إدارة تلقائية للأدوات: هل خطافك بيحتاج أداة Black (لـ Python) وخطاف ثاني بيحتاج Prettier (لـ JavaScript)؟ ما في مشكلة. أداة
pre-commitبتنزل هاي الأدوات وبتديرها في بيئات معزولة بدون ما تلوث جهازك. - مكتبة ضخمة من الخطافات الجاهزة: في آلاف الخطافات الجاهزة اللي عملوها مطورين ثانيين. كل اللي عليك تعمله هو إنك تضيفها لملف الإعدادات.
كيف نستخدمها؟
- التثبيت: (تحتاج Python مثبت على جهازك)
pip install pre-commit - إنشاء ملف الإعدادات: في جذر مشروعك، أنشئ ملف اسمه
.pre-commit-config.yaml. - إضافة الخطافات: الصق هذا المثال كبداية في الملف. هذا المثال بيصلح المسافات الزائدة، وبيفحص ملفات YAML، وبيشغل فورماتر لـ Python و JavaScript.
# .pre-commit-config.yaml repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: - id: trailing-whitespace # يزيل المسافات في نهاية السطر - id: end-of-file-fixer # يتأكد من وجود سطر فارغ في نهاية الملف - id: check-yaml # يفحص صحة ملفات YAML - id: check-added-large-files # يمنع إضافة ملفات كبيرة الحجم - id: check-merge-conflict # يمنع عمل commit لملفات فيها conflict markers - repo: https://github.com/psf/black rev: 24.4.2 hooks: - id: black # فورماتر للغة بايثون - repo: https://github.com/prettier/prettier rev: 3.2.5 hooks: - id: prettier # فورماتر للويب (JS, HTML, CSS, JSON, ...) - تثبيت الخطافات في مستودعك المحلي:
pre-commit installهذا الأمر مرة واحدة لكل مشروع. هو اللي بيربط أداة
pre-commitبحدث.git/hooks/pre-commitالفعلي.
وهيك خلصنا! الآن، في كل مرة أي مطور في الفريق (بعد ما ينفذ الخطوتين 1 و 4) بيحاول يعمل git commit، رح تشتغل هاي الخطافات تلقائياً. إذا الكود مش منسق، رح يتم تنسيقه تلقائياً. إذا في مشكلة، رح يتوقف الـ commit مع رسالة واضحة. يا سلام على الروقان!
الخلاصة: نصيحة من أخوك أبو عمر 👨💻
يا جماعة، البرمجة مش بس كتابة كود، البرمجة هي بناء أنظمة وعمليات مستدامة. قصة “الـ main branch مقبرة الأخطاء” انتهت في فريقنا من اليوم اللي اعتمدنا فيه خطافات Git بشكل جدي. تحولنا من فريق إطفاء حرائق إلى فريق بناء صواريخ.
الاستثمار في الأتمتة في البداية قد يبدو وكأنه عمل إضافي، لكن صدقني، الساعات القليلة اللي رح تقضيها في إعداد pre-commit رح توفر عليك وعلى فريقك مئات الساعات من تصحيح الأخطاء التافهة، والنقاشات غير المجدية، والإحباط. أنت بتبرمج جهازك عشان يحميك من نفسك ومن زلاتك البشرية.
نصيحتي الأخيرة: لا تنتظر حتى تحترق أصابعك. ابدأ اليوم. افتح مشروعك، طبق الخطوات اللي حكيناها، وشاركها مع فريقك. اجعلوا الجودة والأتمتة جزءاً لا يتجزأ من ثقافتكم. صدقني، رح تدعيلي. 😉