آليات Git الداخلية واستكشاف الأخطاء وإصلاحها
في هذا الدرس، سنتعمق في الآليات الداخلية لـ Git، ونستكشف أوامر السباكة (plumbing)، ونتعلم كيفية استكشاف الأخطاء والإصلاح من مشاكل Git الشائعة. فهم آليات Git الداخلية سيساعدك على تصحيح المشاكل والتعافي من حالات تبدو كارثية.
فهم أوامر السباكة في Git
لدى Git نوعان من الأوامر: البورسلين (porcelain - سهلة الاستخدام) والسباكة (plumbing - منخفضة المستوى). أوامر السباكة تتيح لك فحص ومعالجة هياكل Git الداخلية مباشرة.
# عرض نوع كائن Git
git cat-file -t <hash>
# عرض محتوى كائن Git
git cat-file -p <hash>
# سرد جميع الكائنات في المستودع
git rev-list --objects --all
# عرض محتوى الفهرس
git ls-files -s
نصيحة: نادراً ما تكون أوامر السباكة مطلوبة للعمل اليومي، لكنها لا تُقدر بثمن لفهم كيفية عمل Git وتصحيح المشاكل المعقدة.
فحص نظام الملفات Git
أمر git fsck يتحقق من سلامة مستودع Git الخاص بك ويمكن أن يساعد في اكتشاف الفساد:
# فحص سلامة المستودع
git fsck
# فحص مع مخرجات مفصلة
git fsck --full --verbose
# العثور على كائنات لا يمكن الوصول إليها (غير مشار إليها من أي فرع)
git fsck --unreachable
# العثور على كائنات معلقة (كائنات بدون مراجع)
git fsck --dangling
أنواع المخرجات الشائعة:
dangling commit: التزام لا يمكن الوصول إليه من أي فرع
dangling blob: محتوى ملف ليس جزءاً من أي التزام
dangling tree: هيكل دليل ليس جزءاً من أي التزام
unreachable: كائنات لا يمكن الوصول إليها من أي مرجع
مهم: الكائنات المعلقة طبيعية بعد إعادة الأساس أو تعديل الالتزامات. سيتم تنظيفها تلقائياً بواسطة جامع القمامة في Git.
استرداد الفروع المحذوفة
هل حذفت فرعاً بالخطأ؟ لا داعي للذعر! نادراً ما يفقد Git البيانات على الفور. استخدم git reflog للاسترداد:
# عرض reflog (سجل حركات HEAD)
git reflog
# العثور على الالتزام حيث كان فرعك
git reflog show --all
# إعادة إنشاء الفرع المحذوف
git branch recovered-branch <commit-hash>
# أو الانتقال مباشرة إلى ذلك الالتزام
git checkout -b recovered-branch <commit-hash>
مثال على سيناريو الاسترداد:
# لقد حذفت feature-branch عن طريق الخطأ
git branch -D feature-branch
# عرض reflog للعثور على طرف الفرع
git reflog
# المخرجات: a1b2c3d HEAD@{2}: commit: Add new feature
# استرداد الفرع
git branch feature-branch a1b2c3d
# التحقق من الاسترداد
git log feature-branch
تحذير: تنتهي صلاحية إدخالات reflog بعد 90 يوماً افتراضياً (30 يوماً للالتزامات التي لا يمكن الوصول إليها). لا تنتظر طويلاً لاسترداد الفروع المحذوفة!
التعامل مع المستودعات التالفة
فساد المستودع نادر لكنه يمكن أن يحدث بسبب أخطاء القرص أو انقطاع التيار أو عمليات غير مكتملة. إليك كيفية التعامل معه:
# الخطوة 1: التحقق من الفساد
git fsck --full
# الخطوة 2: إذا تم العثور على فساد، حاول الاسترداد
# الاستنساخ من البعيد (الخيار الأكثر أماناً)
git clone <remote-url> recovered-repo
# الخطوة 3: إذا لم يكن هناك بعيد، حاول استرداد الكائنات المفكوكة
cd .git
git unpack-objects < ../corrupted-pack-file
# الخطوة 4: إعادة بناء الفهرس
rm index
git reset
# الخطوة 5: تنظيف وإعادة ضغط
git gc --aggressive --prune=now
أفضل ممارسة: احتفظ دائماً بنسخ احتياطية بعيدة. يمكن استبدال مستودع محلي تالف بسهولة عن طريق الاستنساخ من GitHub أو بعيد آخر.
التعامل مع الملفات الكبيرة
Git محسّن للملفات النصية، وليس للملفات الثنائية الكبيرة. إليك كيفية التعامل مع الملفات الكبيرة بفعالية:
# التحقق من حجم المستودع
git count-objects -vH
# العثور على ملفات كبيرة في التاريخ
git rev-list --objects --all |
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' |
sed -n 's/^blob //p' |
sort --numeric-sort --key=2 |
tail -20
# إزالة ملف كبير من التاريخ (خطر!)
git filter-branch --tree-filter 'rm -f large-file.zip' HEAD
# أفضل: استخدام BFG Repo-Cleaner
bfg --delete-files large-file.zip
git reflog expire --expire=now --all
git gc --prune=now --aggressive
حرج: إزالة الملفات من التاريخ تعيد كتابة الالتزامات وتتطلب دفع قسري. قم بالتنسيق مع فريقك قبل القيام بذلك!
منع مشاكل الملفات الكبيرة باستخدام Git LFS:
# تثبيت Git LFS
git lfs install
# تتبع الملفات الكبيرة
git lfs track "*.psd"
git lfs track "*.mp4"
# التحقق من ما يتم تتبعه
git lfs ls-files
# عرض حالة LFS
git lfs status
صيانة المستودع
الصيانة المنتظمة تحافظ على مستودعك صحياً وعالي الأداء:
# تشغيل جمع القمامة
git gc
# جمع قمامة عدواني (أبطأ، أكثر شمولاً)
git gc --aggressive --prune=now
# تحسين المستودع
git repack -a -d --depth=250 --window=250
# إزالة الكائنات غير المشار إليها الأقدم من أسبوعين
git prune --expire 2.weeks.ago
# تنظيف reflog
git reflog expire --expire=30.days --all
ماذا يفعل جمع القمامة؟
✓ ضغط الكائنات المفكوكة في ملفات حزم
✓ إزالة الكائنات التي لا يمكن الوصول إليها
✓ تحسين ملفات الحزم للكفاءة
✓ تنظيف المراجع القديمة
✓ تقليل حجم المستودع
✓ تحسين الأداء
GC التلقائي: يقوم Git تلقائياً بتشغيل جمع القمامة بشكل دوري. GC اليدوي مطلوب فقط للصيانة أو بعد إعادة كتابة التاريخ الرئيسية.
تصحيح الأخطاء باستخدام GIT_TRACE
قم بتمكين التتبع لرؤية ما يفعله Git من تحت الغطاء. هذا لا يقدر بثمن لتصحيح مشاكل الأداء أو الاتصال:
# تتبع أوامر Git الأساسية
GIT_TRACE=1 git status
# تتبع الأداء (معلومات التوقيت)
GIT_TRACE_PERFORMANCE=1 git log
# تتبع عمليات ملف الحزمة
GIT_TRACE_PACK_ACCESS=1 git fetch
# تتبع جميع عمليات الشبكة
GIT_TRACE_CURL=1 git push
# تتبع الإعداد (قراءة التكوين، اكتشاف المستودع)
GIT_TRACE_SETUP=1 git status
# دمج تتبعات متعددة
GIT_TRACE=1 GIT_TRACE_PERFORMANCE=1 GIT_CURL_VERBOSE=1 git clone <url>
مثال: تصحيح عمليات الجلب البطيئة:
GIT_TRACE_PERFORMANCE=1 GIT_TRACE_PACK_ACCESS=1 git fetch origin
# المخرجات تظهر التوقيت لكل عملية:
# 0.001234 pack-objects.c:2345 performance: ... spent ...
# يساعد في تحديد الاختناقات
سيناريوهات استكشاف الأخطاء الشائعة
المشكلة 1: "fatal: bad object HEAD"
# الحل: استعادة مرجع HEAD
cat .git/refs/heads/main > .git/HEAD
# أو تحرير .git/HEAD يدوياً إلى: ref: refs/heads/main
المشكلة 2: حالة HEAD منفصلة
# أنت في HEAD منفصل، تريد الاحتفاظ بالتغييرات
git branch temp-branch
git checkout main
git merge temp-branch
# أو إنشاء فرع مباشرة والتبديل
git checkout -b new-branch
المشكلة 3: "fatal: refusing to merge unrelated histories"
# السماح بدمج تواريخ غير مرتبطة
git pull origin main --allow-unrelated-histories
# أو أثناء إعادة الأساس
git rebase origin/main --allow-unrelated-histories
المشكلة 4: ملف قفل الفهرس موجود
# عملية Git أخرى تعطلت، تاركة ملف قفل
rm .git/index.lock
# ثم أعد محاولة العملية
git add .
تحذير: قم بإزالة index.lock فقط إذا كنت متأكداً من عدم تشغيل عملية Git أخرى. إزالته أثناء عملية نشطة يمكن أن يسبب فساداً.
تقنيات الاسترداد المتقدمة
عندما تفشل طرق الاسترداد القياسية، جرب هذه التقنيات المتقدمة:
# العثور على الالتزامات المفقودة من خلال البحث في reflog لجميع المراجع
git fsck --lost-found
# ينشئ .git/lost-found/ مع الكائنات المعلقة
# مراجعة الالتزامات:
cd .git/lost-found/commit/
for commit in *; do
echo "Commit: $commit"
git show $commit
done
# استعادة التزام مفقود
git merge <commit-hash>
# أو إنشاء فرع منه
git branch recovered <commit-hash>
قائمة تحقق صحة المستودع
قم بتشغيل هذه الأوامر بشكل دوري لضمان صحة المستودع:
# 1. التحقق من الفساد
git fsck --full
# 2. التحقق من اتصال البعيد
git remote -v
git ls-remote origin
# 3. التحقق من حجم المستودع
git count-objects -vH
# 4. التحقق من التكوين
git config --list
# 5. التحقق من استخدام القرص
du -sh .git
# 6. تشغيل الصيانة
git gc --auto
# 7. التحقق من تتبع الفرع
git branch -vv
تمرين تطبيقي:
السيناريو: تدرب على استرداد وصيانة المستودع
- أنشئ فرع اختبار وقم ببعض الالتزامات
- احذف الفرع واستعده باستخدام reflog
- قم بتشغيل git fsck للتحقق من صحة المستودع
- قم بتمكين GIT_TRACE لتصحيح أمر git status
- قم بتشغيل git gc لتحسين مستودعك
- تحقق من حجم المستودع قبل وبعد gc
الملخص
في هذا الدرس، تعلمت:
- أوامر السباكة في Git لفحص المستودع منخفض المستوى
- استخدام git fsck للتحقق من سلامة المستودع
- استرداد الفروع المحذوفة باستخدام git reflog
- التعامل مع المستودعات التالفة وتقنيات الاسترداد
- إدارة الملفات الكبيرة واستخدام Git LFS
- صيانة المستودع باستخدام git gc والتحسين
- تصحيح عمليات Git باستخدام متغيرات GIT_TRACE
- سيناريوهات استكشاف الأخطاء الشائعة والحلول
التالي: في الدرس التالي، سنستكشف أفضل ممارسات Git للحفاظ على مستودعات نظيفة وآمنة وفعالة!