أوامر Git المتقدمة
بعيداً عن أوامر Git الأساسية، هناك أدوات متقدمة قوية يمكن أن تنقذك في المواقف الحرجة وتعزز إنتاجيتك. في هذا الدرس، سنستكشف cherry-pick و reflog و bisect و blame وأوامر Git المتقدمة الأخرى التي يجب على كل مطور محترف معرفتها.
Git Cherry-Pick: تطبيق التزامات محددة
يسمح لك Cherry-pick بتطبيق التزام محدد من فرع إلى آخر دون دمج الفرع بأكمله.
Cherry-Pick الأساسي:
# أنت على فرع main
git checkout main
# تطبيق الالتزام من فرع الميزة
git cherry-pick abc123
# الالتزام abc123 الآن على main (مع تجزئة جديدة)
حالات الاستخدام:
✓ تطبيق الإصلاح العاجل على فروع متعددة
✓ اختيار ميزات محددة من فرع تجريبي
✓ نقل الإصلاحات إلى فروع الإصدار الأقدم
✓ نقل الالتزامات إلى الفرع الصحيح بعد الخطأ
مهم: ينشئ Cherry-pick التزاماً جديداً بنفس التغييرات ولكن تجزئة مختلفة. لا ينقل الالتزام الأصلي.
أمثلة Cherry-Pick
Cherry-Pick لالتزامات متعددة:
# اختر نطاقاً من الالتزامات
git cherry-pick abc123..def456
# اختر التزامات محددة
git cherry-pick abc123 def456 ghi789
Cherry-Pick بدون التزام تلقائي:
# ترحيل التغييرات بدون الالتزام
git cherry-pick -n abc123
# أو
git cherry-pick --no-commit abc123
# راجع التغييرات، ثم التزم يدوياً
git commit -m "Cherry-picked feature from abc123"
حل تعارضات Cherry-Pick:
# إذا حدث تعارض
git cherry-pick abc123
# CONFLICT (content): Merge conflict in file.php
# أصلح التعارضات يدوياً
# ثم:
git add file.php
git cherry-pick --continue
# أو ألغِ:
git cherry-pick --abort
نصيحة احترافية: استخدم cherry-pick بحذر. إذا وجدت نفسك تختار العديد من الالتزامات انتقائياً، ففكر في الدمج أو إعادة الأساس بدلاً من ذلك.
Git Reflog: شبكة الأمان
يسجل Reflog (سجل المرجع) كل تغيير على HEAD. إنها شبكة الأمان الخاصة بك لاستعادة الالتزامات "المفقودة".
عرض Reflog:
$ git reflog
abc123 HEAD@{0}: commit: Add user authentication
def456 HEAD@{1}: checkout: moving from feature to main
ghi789 HEAD@{2}: commit: Fix payment bug
jkl012 HEAD@{3}: reset: moving to HEAD~1
mno345 HEAD@{4}: commit: Add payment feature (LOST!)
شرح Reflog:
- HEAD@{0} = موضع HEAD الحالي
- HEAD@{1} = موضع HEAD السابق
- HEAD@{2} = حركتان للوراء
- إلخ.
استعادة الالتزامات المفقودة باستخدام Reflog
السيناريو: إعادة تعيين صعبة بطريق الخطأ
# فعلت عن طريق الخطأ:
git reset --hard HEAD~3
# يا للهول! 3 التزامات ذهبت!
# الحل: استخدم reflog
git reflog
# اعثر على تجزئة الالتزام قبل إعادة التعيين
abc123 HEAD@{4}: commit: Add payment feature
# استعد إلى ذلك الالتزام
git reset --hard abc123
# التزاماتك عادت! 🎉
السيناريو: استعادة الفرع المحذوف
# حذفت فرعاً بطريق الخطأ
git branch -D feature/important-work
# اعثر على آخر التزام على ذلك الفرع
git reflog | grep "feature/important-work"
# أعد إنشاء الفرع
git branch feature/important-work abc123
git checkout feature/important-work
ملاحظة: تنتهي إدخالات Reflog بعد 90 يوماً افتراضياً. لا تنتظر طويلاً لاستعادة العمل المفقود!
Git Bisect: العثور على الأخطاء بالبحث الثنائي
يستخدم Bisect البحث الثنائي للعثور على الالتزام الذي قدم خطأ.
سير عمل Bisect الأساسي:
# ابدأ bisect
git bisect start
# ضع علامة على الالتزام الحالي كسيئ (الخطأ موجود)
git bisect bad
# ضع علامة على التزام جيد معروف (الخطأ لم يكن موجوداً)
git bisect good v1.2.0
# يفحص Git الالتزام الأوسط
# اختبر ما إذا كان الخطأ موجوداً
# إذا كان الخطأ موجوداً:
git bisect bad
# إذا لم يكن الخطأ موجوداً:
git bisect good
# كرر حتى يعثر Git على الالتزام الإشكالي
# عند الانتهاء:
git bisect reset
Bisect التلقائي مع الاختبارات
تشغيل Bisect تلقائياً:
# ابدأ bisect
git bisect start HEAD v1.2.0
# شغّل bisect مع أمر الاختبار
git bisect run php artisan test --filter=PaymentTest
# سيختبر Git تلقائياً كل التزام
# ضع علامة جيد/سيئ بناءً على رمز خروج الاختبار
# رمز الخروج 0 = جيد، غير صفري = سيئ
# سيجد Bisect الالتزام المحدد الذي كسر الاختبارات
مثال على المخرجات:
abc123 is the first bad commit
commit abc123
Author: John Doe <john@example.com>
Date: Mon Jan 15 10:30:00 2024 +0000
Refactor payment calculation
This commit introduced the bug!
حركة قوية: يمكن لـ Bisect التحقق من مئات الالتزامات في دقائق باستخدام البحث الثنائي. الاختبار اليدوي سيستغرق ساعات!
Git Blame: تتبع التغييرات حسب المؤلف
يعرض Blame من عدّل آخر مرة كل سطر من ملف ومتى.
Blame الأساسي:
$ git blame app/Http/Controllers/PaymentController.php
abc123 (John Doe 2024-01-15 10:30:00 +0000 1) <?php
abc123 (John Doe 2024-01-15 10:30:00 +0000 2)
def456 (Jane Smith 2024-02-01 14:20:00 +0000 3) public function process($order) {
def456 (Jane Smith 2024-02-01 14:20:00 +0000 4) $tax = $order->total * 0.08;
ghi789 (Bob Johnson 2024-03-10 09:15:00 +0000 5) // TODO: Fix tax calculation
def456 (Jane Smith 2024-02-01 14:20:00 +0000 6) return $order->total + $tax;
abc123 (John Doe 2024-01-15 10:30:00 +0000 7) }
خيارات Blame المفيدة:
# إظهار أرقام الأسطر ومعلومات الالتزام
git blame -L 10,20 file.php
# إظهار نطاق سطر محدد فقط
git blame -L 10,+5 file.php
# إظهار البريد الإلكتروني بدلاً من الأسماء
git blame -e file.php
# تجاهل تغييرات المسافات البيضاء
git blame -w file.php
نصيحة احترافية: استخدم blame للعثور على من كتب الكود، وليس لإلقاء اللوم عليهم! إنها لفهم السياق وطرح الأسئلة.
Git Grep: البحث في محتوى المستودع
يبحث Grep في محتويات الملفات عبر مستودع Git الخاص بك بالكامل.
Grep الأساسي:
# ابحث عن نص في جميع الملفات المتتبعة
git grep "calculateTax"
# ابحث مع أرقام الأسطر
git grep -n "calculateTax"
# بحث غير حساس لحالة الأحرف
git grep -i "calculatetax"
# إظهار عدد التطابقات لكل ملف
git grep -c "calculateTax"
# ابحث في فرع محدد
git grep "calculateTax" main
# ابحث في التزام محدد
git grep "calculateTax" abc123
Grep المتقدم:
# ابحث بـ regex
git grep "function.*calculate"
# ابحث عن كلمات كاملة فقط
git grep -w "tax"
# إظهار السياق (3 أسطر قبل/بعد)
git grep -C 3 "calculateTax"
# ابحث فقط في ملفات PHP
git grep "calculateTax" -- "*.php"
# ابحث عن أنماط متعددة (AND)
git grep -e "tax" --and -e "calculate"
Git Submodules: إدارة التبعيات
تسمح لك الوحدات الفرعية بتضمين مستودع Git آخر داخل مستودعك.
إضافة وحدة فرعية:
# إضافة وحدة فرعية
git submodule add https://github.com/vendor/library.git lib/library
# ينشئ هذا ملف .gitmodules
استنساخ مستودع مع وحدات فرعية:
# استنسخ وهيّئ الوحدات الفرعية
git clone --recurse-submodules https://github.com/user/repo.git
# أو إذا تم الاستنساخ بالفعل:
git submodule init
git submodule update
تحديث الوحدات الفرعية:
# تحديث جميع الوحدات الفرعية إلى الأحدث
git submodule update --remote
# تحديث وحدة فرعية محددة
git submodule update --remote lib/library
إزالة وحدة فرعية:
# إزالة وحدة فرعية
git submodule deinit lib/library
git rm lib/library
rm -rf .git/modules/lib/library
ملاحظة: الوحدات الفرعية معقدة ولها مشاكل. فكر في استخدام Composer (PHP) أو npm (JavaScript) لإدارة التبعية بدلاً من ذلك.
Git Worktree: أدلة عمل متعددة
يسمح لك Worktree بفحص فروع متعددة في وقت واحد في أدلة مختلفة.
حالة الاستخدام:
أنت تعمل على ميزة ولكن تحتاج إلى إصلاح خطأ إنتاج بسرعة
دون فقدان عملك الحالي.
إنشاء Worktree:
# أنشئ worktree للإصلاح العاجل
git worktree add ../hotfix-dir hotfix/urgent-bug
# الآن لديك:
# - /project (دليل العمل الرئيسي)
# - /hotfix-dir (دليل منفصل مع فرع hotfix)
# اعمل في دليل hotfix
cd ../hotfix-dir
# أجرِ تغييرات، التزم، ادفع
git add .
git commit -m "Fix urgent bug"
git push
# ارجع إلى العمل الرئيسي
cd /project
# عمل ميزتك لم يمس!
إدارة Worktrees:
# اسرد جميع worktrees
git worktree list
# أزل worktree
git worktree remove ../hotfix-dir
# تقليم worktrees المحذوفة
git worktree prune
الفائدة: تلغي Worktrees الحاجة إلى التخزين المؤقت، الالتزام بـ WIP، أو استنساخ المستودع مرة أخرى. اعمل على فروع متعددة في وقت واحد!
Git Show: فحص الالتزامات والكائنات
إظهار تفاصيل الالتزام:
# إظهار آخر التزام
git show
# إظهار التزام محدد
git show abc123
# إظهار ملف محدد من الالتزام
git show abc123:app/Models/User.php
# إظهار ملف من فرع مختلف
git show main:README.md
إظهار العلامة:
# إظهار تفاصيل العلامة المشروحة
git show v1.2.0
إظهار التخزين المؤقت:
# إظهار آخر تخزين مؤقت
git show stash@{0}
# إظهار تخزين مؤقت محدد
git show stash@{2}
Git Archive: إنشاء أرشيفات الإصدار
إنشاء أرشيف:
# إنشاء أرشيف zip لفرع main
git archive --format=zip --output=release-v1.2.0.zip main
# إنشاء أرشيف tar.gz
git archive --format=tar.gz --output=release.tar.gz main
# أرشيف علامة محددة
git archive --format=zip --output=v1.2.0.zip v1.2.0
# أرشيف مع دليل بادئة
git archive --prefix=myapp/ --format=zip --output=myapp.zip main
أرشيف ملفات محددة:
# أرشيف دليل app/ فقط
git archive --format=zip --output=app-only.zip main app/
# أرشيف باستثناء vendor/
git archive --format=zip --output=no-vendor.zip main \
$(git ls-files | grep -v "^vendor/")
Git Clean: إزالة الملفات غير المتتبعة
تنظيف الملفات غير المتتبعة:
# تشغيل جاف (إظهار ما سيتم حذفه)
git clean -n
# إزالة الملفات غير المتتبعة
git clean -f
# إزالة الملفات والأدلة غير المتتبعة
git clean -fd
# إزالة الملفات المتجاهلة أيضاً
git clean -fdx
# تنظيف تفاعلي
git clean -i
حالة استخدام شائعة:
# بعد تبديل الفروع، أزل مصنوعات البناء
git clean -fdx
# نظّف لكن احتفظ بملف .env
git clean -fdx -e .env
خطر: git clean -fdx يحذف الملفات نهائياً! شغّل دائماً git clean -n أولاً للمعاينة.
Git Shortlog: تلخيص المساهمين
عرض ملخص المساهمين:
# إظهار عدد الالتزامات حسب المؤلف
git shortlog -sn
# المخرجات:
150 John Doe
87 Jane Smith
45 Bob Johnson
# إظهار مع عناوين البريد الإلكتروني
git shortlog -sne
# إظهار لفرع محدد
git shortlog -sn main
# إظهار لنطاق تاريخ
git shortlog -sn --since="2024-01-01" --until="2024-12-31"
# إظهار رسائل الالتزام التفصيلية
git shortlog
استعلامات Git Log المتقدمة
استعلامات السجل القوية:
# التزامات بواسطة مؤلف محدد
git log --author="John Doe"
# التزامات في نطاق تاريخ
git log --since="2024-01-01" --until="2024-12-31"
# التزامات تؤثر على ملف محدد
git log -- app/Models/User.php
# ابحث في رسائل الالتزام
git log --grep="fix bug"
# ابحث في محتوى الالتزام (تغييرات الكود)
git log -S "calculateTax"
# التزامات أضافت أو أزالت نصاً محدداً
git log -G "function.*calculate"
# إظهار الملفات المتغيرة في كل التزام
git log --name-only
# إظهار الإحصائيات (الإدراجات/الحذفات)
git log --stat
# تنسيق مخصص
git log --pretty=format:"%h - %an, %ar : %s"
# التزامات على الفرع ولكن ليس على main
git log main..feature/new-feature
# التزامات الدمج فقط
git log --merges
# التزامات غير الدمج فقط
git log --no-merges
تمرين عملي:
السيناريو: تطبيق الإنتاج الخاص بك به خطأ. الخطأ لم يكن موجوداً في v1.0.0 (صدر قبل 3 أشهر)، ولكنه موجود الآن. تحتاج إلى العثور على الالتزام الذي قدمه.
المهام:
- استخدم git bisect للعثور على الالتزام الإشكالي
- استخدم git blame لرؤية من كتب السطر الخاطئ
- استخدم git show لفحص تفاصيل الالتزام
- استخدم git log لفهم السياق
الحل:
# 1. ابدأ bisect
git bisect start
git bisect bad # الإصدار الحالي به خطأ
git bisect good v1.0.0 # v1.0.0 كان يعمل
# يفحص Git الالتزام الأوسط
# اختبر التطبيق...
# الخطأ موجود:
git bisect bad
# استمر حتى يعثر Git على الالتزام:
# abc123 is the first bad commit
# 2. استخدم blame للعثور على من كتب الكود الخاطئ
git blame app/Services/PaymentService.php
# المخرجات تظهر أن السطر 45 تم تعديله في الالتزام abc123
# 3. إظهار تفاصيل الالتزام
git show abc123
# اطلع على الفرق الكامل ورسالة الالتزام
# 4. احصل على السياق مع السجل
git log abc123~5..abc123
# اطلع على الالتزامات حول الإشكالية
# 5. اختر الإصلاح انتقائياً لفرع hotfix
git checkout -b hotfix/payment-bug
git cherry-pick def456 # الالتزام الذي يصلحه
# 6. انتهيت!
git bisect reset
الملخص
في هذا الدرس، تعلمت:
- git cherry-pick: تطبيق التزامات محددة على فرع آخر
- git reflog: استعادة الالتزامات والفروع "المفقودة"
- git bisect: العثور على الالتزامات التي تقدم أخطاء بالبحث الثنائي
- git blame: تتبع من عدّل كل سطر من الكود
- git grep: البحث في محتوى المستودع بكفاءة
- git worktree: العمل على فروع متعددة في وقت واحد
- git clean: إزالة الملفات غير المتتبعة بأمان
- git log المتقدم: استعلامات سجل الالتزامات القوية
تهانينا! لقد أكملت دروس Git و GitHub. لديك الآن المهارات لاستخدام Git بثقة للتحكم في الإصدارات، والتعاون مع الفرق على GitHub، والتعامل مع السيناريوهات المتقدمة. استمر في الممارسة، وستتقن Git في وقت قصير!