دفع التغييرات
الدفع هو عملية رفع التزامات مستودعك المحلي إلى مستودع بعيد. في هذا الدرس، سنستكشف كيفية دفع التغييرات بفعالية، والتعامل مع السيناريوهات الشائعة، وفهم خيارات الدفع المختلفة.
أمر الدفع الأساسي
الصيغة الأساسية لدفع التغييرات هي:
# الدفع إلى فرع البعيد الافتراضي
git push
# الدفع إلى مستودع بعيد وفرع محدد
git push <remote> <branch>
# مثال: الدفع إلى المستودع البعيد origin، الفرع main
git push origin main
مفهوم أساسي: الدفع يرفع التزاماتك المحلية إلى المستودع البعيد، مما يجعلها متاحة للمتعاونين الآخرين.
فهم سلوك الدفع
عند الدفع، يرفع Git جميع الالتزامات من فرعك المحلي التي لا توجد على الفرع البعيد:
# التحقق من ما سيتم دفعه (قبل الدفع)
git log origin/main..HEAD
# أو رؤية ملخص
git status
# مثال على المخرجات:
Your branch is ahead of 'origin/main' by 3 commits.
(use "git push" to publish your local commits)
دفع فرع جديد
عند دفع فرع لأول مرة، تحتاج إلى إعداد علاقة التتبع:
# إنشاء والانتقال إلى فرع جديد
git checkout -b feature-login
# إجراء بعض الالتزامات
git add .
git commit -m "Add login feature"
# الدفع وتعيين تتبع upstream
git push -u origin feature-login
# أو
git push --set-upstream origin feature-login
# الآن يمكنك استخدام "git push" فقط في المستقبل
git push
نصيحة: علامة -u (اختصار لـ --set-upstream) تقوم بإعداد علاقة التتبع، بحيث تعرف عمليات الدفع والسحب المستقبلية الفرع البعيد الذي يجب استخدامه.
التحقق من حالة الدفع
قبل الدفع، من الممارسات الجيدة التحقق من حالتك:
# التحقق من حالة الفرع الحالي
git status
# رؤية الالتزامات التي سيتم دفعها
git log origin/main..HEAD --oneline
# رؤية التغييرات التفصيلية
git diff origin/main..HEAD
# التحقق من وجود الفرع البعيد
git branch -r
سيناريوهات رفض الدفع
أحياناً سيتم رفض دفعك. إليك السيناريوهات الشائعة:
السيناريو 1: المستودع البعيد يحتوي على تغييرات ليست لديك
خطأ: Updates were rejected because the remote contains work
that you do not have locally.
الحل:
git fetch origin
git merge origin/main
# أو استخدام pull (fetch + merge)
git pull origin main
# ثم حاول الدفع مرة أخرى
git push origin main
مهم: لا تقم أبداً بالدفع القسري إلى الفروع المشتركة إلا إذا كنت تعرف تماماً ما تفعله وقد نسقت مع فريقك.
الدفع القسري
الدفع القسري يستبدل الفرع البعيد بنسختك المحلية. استخدمه بحذر شديد:
# الدفع القسري (خطير!)
git push --force origin feature-branch
# أو
git push -f origin feature-branch
# بديل أكثر أماناً: الدفع القسري مع الإيجار
git push --force-with-lease origin feature-branch
الفروق بين خيارات الدفع القسري:
--force:
- يستبدل المستودع البعيد بغض النظر عن التغييرات
- قد يفقد عمل الآخرين
- خطير جداً على الفروع المشتركة
--force-with-lease:
- يستبدل فقط إذا لم يتغير المستودع البعيد منذ آخر جلب
- بديل أكثر أماناً لـ --force
- يحمي من الاستبدال العرضي لعمل الآخرين
- موصى به عند الحاجة للدفع القسري
متى تستخدم الدفع القسري:
✓ بعد إعادة تأسيس فرع الميزة الخاص بك
✓ بعد تعديل الالتزامات على فرع الميزة الخاص بك
✓ تنظيف فرع العمل الجاري الخاص بك
✗ أبداً على الفرع main/master
✗ أبداً على الفروع التي يعمل عليها الآخرون
✗ أبداً على فروع الإصدار العامة
دفع فروع متعددة
يمكنك دفع فروع متعددة في وقت واحد:
# دفع جميع الفروع بأسماء مطابقة على المستودع البعيد
git push --all origin
# دفع جميع الوسوم
git push --tags origin
# دفع فرع محدد
git push origin feature-login
# دفع فروع محددة متعددة
git push origin main develop
حذف الفروع البعيدة
يمكنك حذف الفروع على المستودع البعيد:
# حذف فرع بعيد
git push origin --delete feature-old
# أو
git push origin :feature-old
# التحقق من حذف الفرع
git branch -r
# تنظيف مراجع التتبع المحلية
git fetch --prune
نصيحة: حذف فرع بعيد لا يحذف الفرع المحلي. تحتاج إلى حذفه بشكل منفصل باستخدام git branch -d.
دفع الوسوم
الوسوم لا يتم دفعها تلقائياً مع الالتزامات. يجب دفعها بشكل صريح:
# إنشاء وسم
git tag v1.0.0
# دفع وسم محدد
git push origin v1.0.0
# دفع جميع الوسوم
git push origin --tags
# دفع الالتزامات والوسوم معاً
git push --follow-tags origin main
تعيين افتراضيات الدفع
يمكنك تكوين سلوك الدفع الافتراضي:
# تعيين الدفع لدفع الفرع الحالي فقط
git config --global push.default current
# تعيين الدفع لدفع فقط إذا كان للفرع البعيد نفس الاسم
git config --global push.default simple
# تعيين الدفع لدفع جميع الفروع المطابقة
git config --global push.default matching
# عرض تكوين الدفع الحالي
git config --get push.default
موصى به: استخدم "simple" أو "current" كافتراضي للدفع. "matching" يمكن أن يدفع عن طريق الخطأ فروعاً لم تكن تنوي دفعها.
تشغيل تجريبي للدفع
اختبر ما سيتم دفعه دون الدفع فعلياً:
# إجراء تشغيل تجريبي
git push --dry-run origin main
# مثال على المخرجات:
To https://github.com/user/repo.git
abc1234..def5678 main -> main
# لم يتم دفع أي شيء فعلياً
مخرجات الدفع المفصلة
الحصول على معلومات مفصلة حول ما يتم دفعه:
# مخرجات دفع مفصلة
git push --verbose origin main
# أو
git push -v origin main
# رؤية بالضبط الكائنات التي يتم نقلها
خيارات الدفع مع الإيجار
حماية متقدمة للدفع القسري:
# الدفع القسري فقط إذا كان المستودع البعيد يطابق القيمة المتوقعة
git push --force-with-lease=main:abc1234 origin main
# الدفع القسري مع الإيجار على الفرع الحالي
git push --force-with-lease origin feature-branch
# يفشل هذا إذا دفع شخص آخر إلى الفرع
# منذ آخر جلب لك
الدفع إلى مستودعات بعيدة متعددة
الدفع إلى مستودعات بعيدة متعددة:
# الدفع إلى origin
git push origin main
# الدفع إلى المستودع البعيد backup
git push backup main
# إعداد مستودع بعيد للدفع إلى عناوين URL متعددة
git remote set-url --add --push origin https://github.com/user/repo.git
git remote set-url --add --push origin https://gitlab.com/user/repo.git
# الآن git push origin main يدفع إلى كليهما
git push origin main
معلومات فرع التتبع
عرض وتكوين تتبع upstream:
# عرض معلومات التتبع
git branch -vv
# المخرجات تعرض علاقة upstream:
* main abc1234 [origin/main] Latest commit
feature def5678 [origin/feature: ahead 2] Work in progress
# تعيين upstream للفرع الحالي
git branch --set-upstream-to=origin/main
# إزالة تتبع upstream
git branch --unset-upstream
خطافات الدفع
يمكن لـ Git تشغيل نصوص قبل وبعد الدفع:
# خطاف ما قبل الدفع يعمل قبل الدفع
# موجود في: .git/hooks/pre-push
# مثال على خطاف ما قبل الدفع (يمنع الدفع إلى main):
#!/bin/sh
if [ "$(git rev-parse --abbrev-ref HEAD)" = "main" ]; then
echo "Direct push to main is not allowed"
exit 1
fi
# اجعله قابلاً للتنفيذ
chmod +x .git/hooks/pre-push
ملاحظة أمنية: راجع دائماً التزاماتك قبل الدفع، خاصة إلى المستودعات العامة. لا تدفع أبداً معلومات حساسة مثل كلمات المرور أو مفاتيح API أو البيانات الخاصة.
سير عمل الدفع الشائع
سير العمل 1: تطوير الميزة الأساسي
git checkout -b feature-new
# إجراء تغييرات والالتزام
git add .
git commit -m "Implement new feature"
git push -u origin feature-new
سير العمل 2: التحديث والدفع
git fetch origin
git merge origin/main
git push origin feature-branch
سير العمل 3: إعادة التأسيس والدفع القسري
git fetch origin
git rebase origin/main
git push --force-with-lease origin feature-branch
سير العمل 4: الدفع بعد التعديل
git commit --amend
git push --force-with-lease origin feature-branch
استكشاف مشاكل الدفع وإصلاحها
المشكلة: "failed to push some refs"
السبب: المستودع البعيد يحتوي على التزامات ليست لديك
الحل:
git pull origin main
git push origin main
المشكلة: "insufficient permission"
السبب: لا يوجد وصول للكتابة إلى المستودع
الحل: تحقق من أذونات المستودع أو استخدم بيانات الاعتماد الصحيحة
المشكلة: "would clobber existing tag"
السبب: الوسم موجود بالفعل على المستودع البعيد
الحل:
git push origin :refs/tags/v1.0.0 # حذف الوسم البعيد
git push origin v1.0.0 # دفع الوسم الجديد
المشكلة: "push declined due to email privacy"
السبب: إعدادات خصوصية البريد الإلكتروني في GitHub
الحل:
git config user.email "your-github-username@users.noreply.github.com"
git commit --amend --reset-author
git push origin main
تمرين عملي:
سير عمل دفع كامل:
# 1. إنشاء مستودع اختباري
mkdir push-practice
cd push-practice
git init
# 2. إنشاء التزام أولي
echo "# Push Practice" > README.md
git add README.md
git commit -m "Initial commit"
# 3. إضافة مستودع بعيد (استخدم مستودعك الخاص)
git remote add origin https://github.com/user/repo.git
# 4. الدفع مع تتبع upstream
git push -u origin main
# 5. إنشاء ودفع فرع ميزة
git checkout -b feature-test
echo "Feature content" > feature.txt
git add feature.txt
git commit -m "Add feature"
git push -u origin feature-test
# 6. التحقق من الحالة والتتبع
git branch -vv
git status
# 7. إجراء التزام آخر والدفع (لا حاجة لـ -u الآن)
echo "More content" >> feature.txt
git commit -am "Update feature"
git push
# 8. تدرب على التشغيل التجريبي
git push --dry-run origin feature-test
أفضل ممارسات الدفع
✓ اسحب دائماً قبل الدفع لتجنب التعارضات
✓ استخدم --force-with-lease بدلاً من --force
✓ ادفع تغييرات صغيرة ومركزة بشكل متكرر
✓ اكتب رسائل التزام واضحة قبل الدفع
✓ اختبر كودك قبل الدفع إلى الفروع المشتركة
✓ استخدم فروع الميزات للعمل التجريبي
✓ قم بإعداد تتبع upstream مع -u في الدفع الأول
✗ لا تدفع أبداً بالقوة إلى main/master
✗ لا تدفع أبداً بيانات حساسة (كلمات مرور، مفاتيح)
✗ تجنب دفع ملفات ثنائية كبيرة
✗ لا تدفع كوداً معطلاً أو غير مختبر إلى الفروع المشتركة
الملخص
في هذا الدرس، تعلمت:
- git push يرفع الالتزامات المحلية إلى المستودعات البعيدة
- استخدم علامة -u عند دفع فرع جديد لإعداد التتبع
- الدفع القسري مع --force-with-lease للأمان
- لا تدفع أبداً بالقوة إلى الفروع المشتركة مثل main
- رفض الدفع يعني أن المستودع البعيد يحتوي على تغييرات تحتاج إلى سحبها أولاً
- يمكنك حذف الفروع البعيدة باستخدام git push --delete
- يجب دفع الوسوم بشكل صريح باستخدام --tags أو بشكل فردي
- كوّن افتراضيات الدفع لسلوك متسق
التالي: في الدرس التالي، سنتعلم عن جلب وسحب التغييرات من المستودعات البعيدة!