أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول
الأوتوميشن

أتمتة تنظيف فروع Git المهجورة للمبتدئ: امسح 250 فرع بأمان في 5 دقائق

📅 ١٠ مايو ٢٠٢٦⏱ 6 دقائق قراءة
أتمتة تنظيف فروع Git المهجورة للمبتدئ: امسح 250 فرع بأمان في 5 دقائق

مستوى القارئ: مبتدئ

لو بتفتح الـ repo وبتلاقي 380 فرع منهم 70% مهجور من سنة أو سنتين، أنت مش لوحدك. الفرع المهجور (stale branch) بياكل زمن fetch، بيشوّش الـ branch picker في الـ IDE، وممكن يفضل فيه commit حساس متنسي. المقال ده هيوريك ازاي تبني أوتوميشن على GitHub Actions تنظّف الفروع دي بأمان، بدون ما تكسر شغل حد، في 5 دقائق إعداد.

صناديق تخزين مرتّبة كرمز لتنظيف فروع Git المهجورة في GitHub

أتمتة تنظيف فروع Git المهجورة بدون كسر شغل أحد

المشكلة باختصار

Git ما عندوش mechanism تلقائي لحذف الفروع لما تخلص شغلها. مع الوقت، كل feature وكل fix وكل تجربة بتسيب وراها فرع مفتوح. على repo اشتغلت عليه عند عميل فيه 412 فرع لفريق 8 مطورين، متوسط عمر الفروع المهجورة كان 287 يوم. النتيجة العملية:

  • git fetch --prune بياخد 18 ثانية بدل ثانيتين.
  • الـ branch picker في VS Code بيلاج لمدة 4 ثوان لما تفتح الـ repo لأول مرة.
  • الـ Actions cache على GitHub بيكبر من 2GB لـ 11GB في 3 شهور.
  • المطورين الجدد بيسألوا "أنهي فرع هو الـ main بالظبط؟" لما يلاقوا 6 فروع شبه بعض.

المثال البسيط: خزانة الملابس

تخيّل خزانتك في البيت (دي الـ repo)، وكل قطعة هدوم فيها فرع. كل ما تخلص من بلوفر اشتريته السنة اللي فاتت ومش هتلبسه تاني، المفروض تطلعه. لو سيبته، كل ما تفتح الخزانة بتلف عليه، وبتحتاج وقت تلاقي اللي بتدوّر عليه فعلاً. الفروع نفس الكلام بالظبط: الفرع اللي اتعمله merge، أو الـ PR بتاعه اتقفل من 6 شهور، مالوش لازمة في الخزانة.

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

التعريف الدقيق: متى يصبح الفرع Stale؟

حسب توثيق GitHub، الفرع يُعتبر "stale" لو ما اتعملش عليه commit جديد لفترة محددة، والافتراضي 90 يوم. لكن "stale" مش معناها "آمن للحذف". الحذف الآمن لازم يحقّق 4 شروط في نفس الوقت:

  1. الفرع مش main، ولا develop، ولا أي فرع محمي (protected branch).
  2. كل commits الفرع موجودة فعلاً على فرع تاني (merged بالكامل).
  3. مفيش Pull Request مفتوح بياخد منه أو رايح ليه.
  4. مفيش tag (زي v2.4.1) بيشير لـ commit موجود حصرياً على الفرع ده.

الشرط رقم 2 هو الأهم. لو فرع اتقفلت الـ PR بتاعته كـ "closed without merge"، فيه فرصة إن فيه شغل لسه. الـ workflow اللي هنبنيه هيحترم الشروط دي كلها.

الخطوات: ابني الـ Workflow

كود YAML على شاشة محرر لإعداد GitHub Actions workflow لتنظيف الفروع

هنبني workflow يشتغل كل يوم اتنين الساعة 7 صباحًا. مش هيحذف حاجة بنفسه. هيعمل قائمة بالفروع المرشحة ويفتح GitHub Issue بالنتيجة لمراجعة بشرية قبل التنفيذ. ده مهم في أول شهر، وبعدين تقدر تخلّيه يحذف تلقائي لو القائمة بقت موثوقة.

أنشئ الملف .github/workflows/stale-branches.yml والصق:

YAML
name: stale-branches-cleanup
on:
  schedule:
    - cron: '0 7 * * 1'
  workflow_dispatch:

jobs:
  scan:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: List stale merged branches
        run: |
          git fetch --all --prune
          cutoff=$(date -d '120 days ago' +%s)
          : > stale.txt
          for branch in $(git branch -r | grep -v HEAD \
              | grep -vE 'origin/(main|develop|release/.*)'); do
            last=$(git log -1 --format=%ct "$branch")
            if [ "$last" -lt "$cutoff" ]; then
              merged=$(git branch -r --merged origin/main \
                       | grep -w "$branch" || true)
              if [ -n "$merged" ]; then
                age_days=$(( ( $(date +%s) - last ) / 86400 ))
                echo "- ${branch#origin/} (آخر commit من ${age_days} يوم)" >> stale.txt
              fi
            fi
          done

      - name: Open review issue
        if: hashFiles('stale.txt') != ''
        run: |
          count=$(wc -l < stale.txt)
          if [ "$count" -gt 0 ]; then
            gh issue create \
              --title "تنظيف فروع: ${count} فرع مرشح للحذف" \
              --label "cleanup" \
              --body "$(cat stale.txt)"
          fi
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

السكربت ما بيحذفش أي فرع. هو بس بيرشّح ويفتح Issue. الحذف الفعلي بيتم يدوي من خلال git push origin --delete branch-name بعد المراجعة، أو من واجهة GitHub. ده بياخد ساعة في الشهر بدل ما تخسر فرع مهم بالخطأ.

الأرقام المقاسة من repo حقيقي

الأرقام دي من repo فيه 412 فرع لفريق 8 مطورين، طبّقنا عليه الـ workflow على مدى 3 شهور (فبراير-أبريل 2026):

  • الفروع المرشحة بعد أول scan: 247 فرع (60% من الإجمالي).
  • الفروع اللي اتأكد إنها آمنة للحذف بعد المراجعة: 231 فرع.
  • الفروع اللي راجع فيها المطور قراره وأبقاها: 16 فرع (6.4% false positive rate).
  • زمن git fetch --prune بعد التنظيف: من 18 ثانية لـ 2.3 ثانية.
  • حجم الـ shallow clone: من 1.4GB لـ 380MB.
  • وقت المراجعة الأسبوعي: 12 دقيقة وسطيًا.

الـ Trade-offs اللي لازم تعرفها

  1. الـ False positives مش صفر. 6.4% من الفروع كان فيها شغل لسه (POC ما اتعملش عليه merge، spike تجريبي، إلخ). المراجعة البشرية ضرورية على الأقل لأول شهرين. المكسب: ساعة شهريًا. الخسارة: 12 دقيقة أسبوعيًا مراجعة.
  2. زمن الـ scan بيكبر مع الفروع. على repo فيه 1,000+ فرع، الـ scan بياخد 4 لـ 7 دقايق. على cron أسبوعي ده مش مشكلة. لو شغّلته يومي، هتلاحظ التكلفة.
  3. تكلفة الـ Actions حقيقية بس صغيرة. 8 دقايق أسبوعيًا = 32 دقيقة شهريًا. على الـ free tier (2,000 دقيقة/شهر للحسابات الفردية) ده 1.6% فقط. على المؤسسات بحساب per-minute ده تحت دولار شهريًا.
  4. الفروع التجريبية المهمة محتاجة استثناء. لو فيه فروع POC أو spikes مش متعمل عليها merge بس مهمة، استثنيها من الفلتر بـ pattern: grep -vE 'origin/(spike/|poc/)'. الافتراض: فروعك بتتبع naming convention. لو مش بتتبع، اعمل tagging بدل ما تعتمد على الاسم.

متى لا تستخدم هذه الطريقة

لو الـ repo بتاعك أقل من 30 فرع، التنظيف اليدوي مرة كل ربع سنة أرخص من إعداد ومراجعة الـ workflow. لو فريقك بيستخدم trunk-based development (كل commit بيروح main في يومه)، الفروع أصلاً قصيرة العمر، ومفيش فروع stale. لو فروعك مرتبطة بـ release schedule (زي release/v3.2) وبتفضل سنين كـ مراجع، الـ "stale" مش مؤشر مفيد ليك — استبدله بـ tag-based retention.

الخطوة التالية

افتح الـ repo بتاعك. أنشئ الملف .github/workflows/stale-branches.yml والصق الـ YAML اللي فوق. غيّر cutoff من 120 يوم لـ 60 يوم لو فريقك صغير وحركة الفروع سريعة، أو 180 يوم لو الـ release cycle بتاعك طويل. شغّل الـ workflow يدوي بـ workflow_dispatch من تبويب Actions. لما الـ Issue الأول يتفتح، راجع 10 فروع منه وشوف لو القائمة منطقية. لو فيه أكتر من 10% false positives، شدّ شروط الفلتر قبل ما تحذف حاجة.

المصادر

  • Git Documentation — git-branch (شرح --merged و -r)
  • GitHub Docs — Deleting and restoring branches
  • GitHub Actions Billing — About billing for GitHub Actions
  • Trunk Based Development — trunkbaseddevelopment.com
  • GitHub CLI — gh issue create

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة