الجلب والسحب
الجلب والسحب هما عمليتان أساسيتان للحفاظ على مستودعك المحلي متزامناً مع المستودعات البعيدة. في هذا الدرس، سنستكشف الفروق بين fetch و pull، ونتعلم متى نستخدم كل أمر.
فهم Fetch مقابل Pull
الفرق الرئيسي بين fetch و pull:
git fetch:
- يقوم بتنزيل الالتزامات والملفات والمراجع من المستودع البعيد
- يحدث فروع التتبع البعيدة (origin/main)
- لا يعدل دليل العمل الخاص بك
- لا يدمج التغييرات في فرعك الحالي
- آمن للتشغيل في أي وقت
git pull:
- يؤدي git fetch
- يدمج التغييرات فوراً في الفرع الحالي
- يحدث كلاً من فروع التتبع البعيدة ودليل العمل
- يعادل: git fetch + git merge
- يمكن أن يسبب تعارضات دمج
مفهوم أساسي: Fetch مثل التحقق من بريدك - ترى ما هو جديد لكن لا تفتحه. Pull مثل التحقق من بريدك وقراءة كل شيء على الفور.
أمر Fetch الأساسي
الصيغة الأساسية للجلب:
# الجلب من المستودع البعيد الافتراضي (origin)
git fetch
# الجلب من مستودع بعيد محدد
git fetch origin
# الجلب من جميع المستودعات البعيدة
git fetch --all
# جلب فرع محدد
git fetch origin main
ما يحدث أثناء Fetch
عند الجلب، يقوم Git بـ:
1. الاتصال بالمستودع البعيد
2. تنزيل الالتزامات والملفات الجديدة
3. تحديث فروع التتبع البعيدة (origin/main, origin/develop)
4. عرض ما تم جلبه
5. لا يعدل ملفات العمل الخاصة بك
6. لا يعدل فروعك المحلية
# مثال على المخرجات:
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 5 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (5/5), done.
From https://github.com/user/repo
abc1234..def5678 main -> origin/main
عرض التغييرات المجلوبة
بعد الجلب، يمكنك فحص التغييرات قبل الدمج:
# جلب التغييرات
git fetch origin
# عرض الالتزامات التي تم جلبها
git log HEAD..origin/main --oneline
# رؤية التغييرات التفصيلية
git diff HEAD..origin/main
# عرض جميع الفروع البعيدة
git branch -r
# التحقق من الحالة
git status
# المخرجات: Your branch is behind 'origin/main' by 3 commits
نصيحة: اجلب أولاً، راجع التغييرات، ثم قرر ما إذا كنت ستدمج أو تعيد التأسيس. هذا يمنحك السيطرة على متى وكيف تدمج التغييرات.
أمر Pull الأساسي
الصيغة الأساسية للسحب:
# السحب من المستودع البعيد والفرع الافتراضي
git pull
# السحب من مستودع بعيد وفرع محدد
git pull origin main
# السحب من upstream
git pull upstream main
# مثال على سير العمل:
git checkout main
git pull origin main
Pull مع Rebase
بدلاً من الدمج، يمكنك إعادة التأسيس عند السحب:
# السحب وإعادة التأسيس بدلاً من الدمج
git pull --rebase origin main
# تعيين rebase كافتراضي لـ pull
git config --global pull.rebase true
# السحب مع rebase للفرع الحالي فقط
git config branch.main.rebase true
# التحقق من التكوين
git config --get pull.rebase
الفرق:
- git pull - ينشئ التزام دمج
- git pull --rebase - يعيد تشغيل التزاماتك فوق الالتزامات المجلوبة (سجل أنظف)
Fetch و Prune
إزالة المراجع لفروع بعيدة لم تعد موجودة:
# الجلب وإزالة فروع التتبع البعيدة القديمة
git fetch --prune origin
# أو
git fetch -p origin
# تعيين prune كافتراضي
git config --global fetch.prune true
# التقليم بدون جلب
git remote prune origin
# رؤية ما سيتم تقليمه
git remote prune origin --dry-run
نصيحة: استخدم --prune بانتظام للحفاظ على فروع التتبع البعيدة نظيفة. الفروع البعيدة المحذوفة لن تختفي تلقائياً من فروع التتبع المحلية بدون التقليم.
عمليات Pull ذات التقدم السريع فقط
التأكد من نجاح pull فقط إذا كان يمكنه التقدم السريع:
# السحب فقط إذا كان التقدم السريع ممكناً
git pull --ff-only origin main
# تعيين التقدم السريع فقط كافتراضي
git config --global pull.ff only
# إذا لم يكن التقدم السريع ممكناً، سيفشل pull:
fatal: Not possible to fast-forward, aborting.
# ثم يمكنك أن تقرر الدمج أو إعادة التأسيس يدوياً
git merge origin/main
# أو
git rebase origin/main
التعامل مع تعارضات Pull
عندما يتسبب pull في تعارضات، إليك كيفية التعامل معها:
# محاولة السحب
git pull origin main
# إذا حدثت تعارضات:
Auto-merging file.txt
CONFLICT (content): Merge conflict in file.txt
Automatic merge failed; fix conflicts and then commit the result.
# 1. التحقق من الملفات التي بها تعارضات
git status
# 2. فتح الملفات المتعارضة وحلها
# ابحث عن علامات التعارض:
<<<<<<< HEAD
تغييراتك
=======
التغييرات البعيدة
>>>>>>> origin/main
# 3. بعد الحل، قم بتجهيز الملفات
git add file.txt
# 4. إكمال الدمج
git commit -m "Merge branch 'main' of origin/main"
# أو إذا كنت تستخدم pull --rebase:
git add file.txt
git rebase --continue
مهم: إذا أنشأ pull تعارضات وتريد الإحباط، استخدم:
- للدمج: git merge --abort
- لإعادة التأسيس: git rebase --abort
جلب فروع محددة
يمكنك جلب فروع أو مراجع محددة:
# جلب فرع محدد
git fetch origin feature-branch
# جلب فروع متعددة
git fetch origin main develop
# جلب جميع الفروع من المستودع البعيد
git fetch origin 'refs/heads/*:refs/remotes/origin/*'
# جلب الوسوم فقط
git fetch --tags origin
# الجلب بدون وسوم
git fetch --no-tags origin
مزامنة المستودعات المتشعبة
سير عمل شائع للحفاظ على النسخ المتشعبة محدثة:
# 1. إضافة المستودع البعيد upstream (المستودع الأصلي)
git remote add upstream https://github.com/original/repo.git
# 2. الجلب من upstream
git fetch upstream
# 3. الانتقال إلى فرع main الخاص بك
git checkout main
# 4. دمج تغييرات upstream
git merge upstream/main
# 5. الدفع إلى نسختك المتشعبة
git push origin main
# بديل: إعادة التأسيس بدلاً من الدمج
git rebase upstream/main
git push --force-with-lease origin main
سير عمل Fork: المزامنة المنتظمة تحافظ على نسختك المتشعبة محدثة مع المستودع الأصلي، مما يسهل المساهمة ويتجنب التعارضات الكبيرة.
عمق Fetch والنسخ الضحلة
التحكم في مقدار السجل الذي سيتم جلبه:
# جلب الالتزامات الحديثة فقط (جلب ضحل)
git fetch --depth=1 origin main
# جلب المزيد من السجل في النسخة الضحلة
git fetch --deepen=50
# تحويل النسخة الضحلة إلى نسخة كاملة
git fetch --unshallow
# التحقق مما إذا كان المستودع ضحلاً
git rev-parse --is-shallow-repository
استراتيجيات Pull
استراتيجيات مختلفة لسحب التغييرات:
الاستراتيجية 1: الدمج الافتراضي
git pull origin main
# ينشئ التزام دمج إذا لزم الأمر
الاستراتيجية 2: Rebase
git pull --rebase origin main
# يعيد تشغيل التزاماتك في الأعلى
الاستراتيجية 3: التقدم السريع فقط
git pull --ff-only origin main
# يفشل إذا كان التزام الدمج مطلوباً
الاستراتيجية 4: Fetch + الدمج اليدوي
git fetch origin
git log HEAD..origin/main # مراجعة التغييرات
git merge origin/main # الدمج عند الاستعداد
Pull التلقائي عند Checkout
تكوين الفروع لسحب تلقائي عند checkout:
# إعداد الفرع لتتبع المستودع البعيد
git branch --set-upstream-to=origin/main main
# تكوين السحب التلقائي (استخدم بحذر)
git config branch.main.mergeoptions "--ff-only"
# عرض تكوين التتبع
git branch -vv
تحذير: عمليات السحب التلقائية يمكن أن تتسبب في تغييرات غير متوقعة. من الأفضل عموماً الجلب والسحب بشكل صريح عند الحاجة.
Fetch مقابل Pull: متى تستخدم كل منهما
استخدم FETCH عندما:
✓ تريد أن ترى ما تغير على المستودع البعيد
✓ أنت في منتصف العمل وتريد التحقق من التحديثات
✓ تريد مراجعة التغييرات قبل الدمج
✓ تعمل على كود تجريبي
✓ تريد مقارنة الفروع
استخدم PULL عندما:
✓ أنت مستعد لدمج التغييرات البعيدة فوراً
✓ تبدأ عملاً جديداً وتريد أحدث كود
✓ تثق في الفرع البعيد تماماً
✓ أنت على فرع مستقر مثل main
✓ تريد المزامنة بسرعة مع المستودع البعيد
جلب مستودعات بعيدة متعددة
العمل مع مستودعات بعيدة متعددة:
# الجلب من جميع المستودعات البعيدة
git fetch --all
# الجلب من مستودعات بعيدة محددة
git fetch origin
git fetch upstream
# مقارنة الفروع من مستودعات بعيدة مختلفة
git diff origin/main..upstream/main
# الدمج من upstream
git merge upstream/main
تمرين عملي:
سير عمل الجلب والمراجعة والسحب:
# 1. التحقق من الحالة الحالية
git status
git branch -vv
# 2. الجلب من المستودع البعيد
git fetch origin
# 3. رؤية ما تم جلبه
git log HEAD..origin/main --oneline
git log --graph --all --oneline
# 4. مراجعة التغييرات بالتفصيل
git diff HEAD..origin/main
# 5. التحقق من التعارضات قبل السحب
git merge-base HEAD origin/main
# 6. السحب مع rebase
git pull --rebase origin main
# 7. التحقق من أن كل شيء محدث
git status
# 8. التدرب مع upstream (إذا كان لديك)
git fetch upstream
git log HEAD..upstream/main --oneline
git merge upstream/main
# 9. التدرب على التقليم
git fetch --prune origin
git branch -r # عرض الفروع البعيدة المتبقية
استكشاف مشاكل Fetch و Pull وإصلاحها
المشكلة: "Your branch is behind by N commits"
الحل:
git pull origin main
المشكلة: "divergent branches"
الحل:
git fetch origin
git rebase origin/main
# أو
git merge origin/main
المشكلة: "refusing to merge unrelated histories"
الحل:
git pull origin main --allow-unrelated-histories
المشكلة: فروع التتبع البعيدة القديمة
الحل:
git fetch --prune origin
git remote prune origin
المشكلة: تعارضات Pull
الحل:
# حل التعارضات، ثم:
git add .
git commit
# أو إحباط:
git merge --abort
أفضل الممارسات
✓ اجلب بانتظام لتبقى على علم بالتغييرات البعيدة
✓ استخدم fetch قبل pull لمراجعة التغييرات
✓ قم بالتقليم بانتظام لتنظيف الفروع القديمة
✓ كوّن pull.rebase لسجل أنظف
✓ استخدم --ff-only على الفروع المهمة للأمان
✓ التزم أو خزن التغييرات المحلية قبل السحب
✓ تواصل مع الفريق قبل الدفع القسري بعد rebase
✗ لا تسحب إلى دليل عمل متسخ
✗ لا تستخدم pull إذا كان لديك تغييرات مهمة غير ملتزمة
✗ تجنب السحب دون مراجعة التغييرات أولاً
تكوين Fetch و Pull
# تعيين المستودع البعيد الافتراضي لـ fetch/pull
git config branch.main.remote origin
# تعيين فرع الدمج الافتراضي
git config branch.main.merge refs/heads/main
# التقليم دائماً عند الجلب
git config --global fetch.prune true
# استخدام rebase عند السحب
git config --global pull.rebase true
# عرض جميع التكوينات المتعلقة بـ fetch/pull
git config --get-regexp "branch|fetch|pull"
الملخص
في هذا الدرس، تعلمت:
- git fetch يقوم بتنزيل التغييرات دون تعديل دليل العمل
- git pull يجلب ويدمج التغييرات فوراً
- Fetch أكثر أماناً - راجع التغييرات قبل الدمج
- استخدم خيار --rebase لسجل التزامات أنظف
- استخدم --prune لتنظيف الفروع البعيدة المحذوفة
- --ff-only يمنع التزامات الدمج العرضية
- تعامل مع التعارضات بالحل والالتزام أو الإحباط
- قم بمزامنة النسخ المتشعبة بانتظام مع مستودعات upstream
التالي: في الدرس التالي، سنتعلم عن استنساخ المستودعات وخيارات الاستنساخ المختلفة!