سير عمل Git لـ TypeScript: كيف تتوقف عن الخوف من تعارض الدمج
\n\nإذا سبق لك أن حاولت دمج فرعين، حيث قام أحدهما بتغيير واجهة User، والآخر بإضافة نوع جديد في نفس الوحدة، فأنت تعرف ما هي أزمة المطور الوجودية. يمنحنا TypeScript نظام أنواع قوي، لكن بدون سير عمل Git صحيح، تتحول هذه القوة إلى صداع.
في هذه المقالة، سنشرح سير عمل Git الأمثل لمشاريع TypeScript - من إعداد الفروع إلى التحقق التلقائي من الأنواع عند كل commit. لا ماء، فقط ما يعمل حقًا في الميدان.
\n\nلماذا يتطلب TypeScript نهجًا خاصًا لـ Git؟
\n\nTypeScript ليس مجرد "JavaScript مع أنواع". إنها لغة حيث يمكن لكل تغيير أن يؤثر على عشرات الملفات من خلال interface و type والأجناس العامة. تعديل خاطئ واحد في نوع أساسي - وسيتوقف المشروع بأكمله عن التجميع.
لذلك، يجب أن يتضمن سير عمل git القياسي لـ TypeScript ما يلي:
\n\n- \n
- التحقق الإلزامي من الأنواع قبل الـ commit \n
- مدقق لغوي يمنع commit الكود غير المنسق \n
- استراتيجية تفرع واضحة، بحيث لا يكسر تعارض الدمج الأنواع \n
- CI/CD يعيد التحقق من كل شيء على الخادم \n
دعنا نشرح كل نقطة بالترتيب.
\n\n1. اختر استراتيجية التفرع: Git Flow أم Trunk-based؟
\n\nلمشاريع TypeScript، أوصي بـ Trunk-based development مع فروع قصيرة العمر. لماذا؟ لأن كود TypeScript هو، في جوهره، كود "خام" يحتاج إلى فحص ونشر سريع. الفروع الطويلة تؤدي إلى "تباعد" الأنواع.
\n\nالهيكل الأساسي للفروع
\n\nmain — نسخة مستقرة، جاهزة دائمًا للنشر\ndevelop — فرع التطوير الرئيسي\nfeature/* — ميزات جديدة (تعيش 1-2 يوم)\nfix/* — إصلاحات الأخطاء\nrelease/* — تحضير الإصدار (اختياري)\n\n\nمثال لمشروع TypeScript:
\n\ngit checkout -b feature/add-user-validation\n# نعمل...\ngit commit -m "feat: add email validation for User type"\ngit push origin feature/add-user-validation\n# ننشئ PR → دمج في develop\n\n\nهام: لا تقم أبدًا بعمل rebase على main إذا كان المشروع يحتوي على أنواع مشتركة. استخدم merge - فهو يحافظ على التاريخ ولا يكسر التبعيات.
\n\n2. خطافات Git: حماية من الأحمق (ومن نفسك)
\n\nالسيناريو الأكثر شيوعًا: تنسى تشغيل tsc، تقوم بـ commit، تدفع، ويسقط CI. لتجنب ذلك، نقوم بإعداد pre-commit hooks.
تثبيت Husky + lint-staged
\n\nHusky هي أداة لإدارة خطافات Git. lint-staged - تشغل الأوامر فقط على الملفات المعدلة.
\n\nnpm install --save-dev husky lint-staged\nnpx husky init\n\n\nننشئ ملف .husky/pre-commit:
#!/usr/bin/env sh\n. "$(dirname -- "$0")/_/husky.sh"\n\nnpx lint-staged\n\n\nفي package.json نضيف:
{\n "lint-staged": {\n "*.ts": [\n "eslint --fix",\n "prettier --write",\n "tsc --noEmit"\n ]\n }\n}\n\n\nالآن قبل كل commit:
\n- \n
- يتم تشغيل ESLint مع الإصلاح التلقائي \n
- يتم تنسيق الكود عبر Prettier \n
- يتم التحقق من بناء TypeScript (
tsc --noEmit) \n
إذا فشلت أي خطوة - لن يتم الـ commit. قاسٍ، لكنه فعال.
\n\n3. رسائل commit صحيحة: conventional commits
\n\nتستفيد مشاريع TypeScript من conventional commits، لأن:
\n- \n
- يتم إنشاء سجل التغييرات تلقائيًا \n
- من السهل فهم التغييرات التي تكسر الأنواع \n
- يمكن تشغيل CI فقط على commits معينة \n
أمثلة:
\n\nfeat: add UserRole enum and validation\nfix: c