git push
تحديث المراجع البعيدة مع الكائنات المرتبطة بها
يرفع الأمر 'git push' محتوى المستودع المحلي إلى مستودع بعيد. ينقل الـ commits وتحديثات الفروع (والوسوم حين تطلبها بـ --tags أو --follow-tags) من مستودعك المحلي إلى مستودع بعيد، فتصبح تغييراتك متاحة للآخرين. الدفع هو طريقتك في مشاركة العمل - بعد الحفظ محليًا، تدفع لتتزامن مع فريقك. افتراضيًا (push.default=simple)، لا يحدّث git push إلا فرع الـ upstream للفرع الحالي، الذي يجب أن يكون موجودًا وبالاسم نفسه، وفقط إن كان التحديث fast-forward (أي أن الفرع البعيد سلف لفرعك المحلي).
الصيغة
git push [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [-f | --force] [-d | --delete] [--prune] [-q | --quiet] [-v | --verbose] [-u | --set-upstream] [-o <string>] [--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]] [--no-verify] [<repository> [<refspec>...]]الخيارات
اختيار الخيار المناسب
سلّم أمان الدفع بالإجبار
حين تحتاج إلى الكتابة فوق التاريخ البعيد، اختر أكثر خيار آمن يناسب حالتك
| الأمر | مستوى الخطر | يتحقق من البعيد | متى يفشل | حالة الاستخدام |
|---|---|---|---|---|
git push | آمن | ✓ fast-forward فقط | إن كانت في البعيد commits جديدة | سير العمل اليومي المعتاد |
git push --force-with-lease --force-if-includes | أكثر الإجبار أمانًا | ✓ رأس البعيد ضمن التاريخ المحلي | إن لم تكن دمجت التغييرات البعيدة | بعد rebase حين يكون آخرون قد دفعوا |
git push --force-with-lease | إجبار أكثر أمانًا | ✓ البعيد لم يتغيّر منذ fetch | إن تغيّر البعيد منذ آخر fetch | بعد rebase على فرع شخصي |
git push --force | خطير | ✗ يكتب فوق البعيد دون تحقق | أبدًا (إلا إن رفضه الخادم) | فقط حين تكون متأكدًا، أو على فرع لك وحدك |
ما الذي يُدفع
التحكم في نطاق ما ترسله إلى المستودع البعيد
| الأمر | يدفع | يشمل الوسوم | الاستخدام المعتاد |
|---|---|---|---|
git push origin main | فرع واحد | ✗ | دفع فرع محدد |
git push -u origin branch | فرع واحد + يضبط التتبّع | ✗ | أول دفع لفرع جديد |
git push --all | كل الفروع | ✗ | مزامنة كل الفروع المحلية |
git push --tags | الوسوم فقط (دون فروع) | ✓ كل الوسوم | دفع وسوم الإصدارات |
git push --follow-tags | الفرع الحالي | ✓ المشروحة القابلة للوصول فقط | الدفع مع وسوم الإصدار المعنية |
git push --mirror | كل شيء | ✓ الكل | نسخة مطابقة على البعيد (يحذف المراجع الموجودة على البعيد فقط) |
المخرجات والإفادة
التحكم في مستوى التفصيل وتنسيق المخرجات حسب حاجتك
| الأمر | مستوى المخرجات | يُظهر التقدّم | قابل للتحليل آليًا | الأنسب لـ |
|---|---|---|---|---|
git push | عادي | في الطرفية فقط | ✗ | الاستخدام التفاعلي المعتاد |
git push --verbose | مفصّل | ✓ | ✗ | تصحيح مشكلات الدفع |
git push --quiet | الأخطاء فقط | ✗ | ✗ | السكربتات، خطوط CI |
git push --progress | عادي + تقدّم إجباري | ✓ دائمًا | ✗ | سكربتات تحتاج إلى التقدّم في السجلات |
git push --porcelain | منظّم | ✗ | ✓ مفصول بعلامات جدولة | تحليل نتائج الدفع في السكربتات |
الأمان والتحقق
فحوص ما قبل الدفع وخيارات التحقق
| الأمر | يشغّل الـ hooks | يتحقق | ينشئ commit | متى تستخدمه |
|---|---|---|---|---|
git push | ✓ pre-push | البعيد يقبل | N/A | سير العمل المعتاد |
git push --dry-run | ✓ pre-push | ما الذي سيحدث | ✗ معاينة فقط | قبل الدفعات المهمة |
git push --atomic | ✓ | كل المراجع أو لا شيء | الكل أو لا شيء | دفع عدة فروع معًا |
git push --no-verify | ✗ يتخطّى pre-push المحلي (hooks الخادم ما زالت تعمل) | البعيد يقبل | N/A | حالة طارئة حين تمنعك الـ hooks |
git push --signed | ✓ | توقيع GPG | موقّع تشفيريًا | مستودعات عالية الأمان، إثبات الهوية |
إدارة المستودعات البعيدة والفروع
خيارات لإدارة المراجع البعيدة وعلاقات الفروع
| الأمر | الإجراء | يؤثر في البعيد | حالة الاستخدام |
|---|---|---|---|
git push -u origin branch | دفع + تعيين الـ upstream | يضيف فرعًا | أول دفع، يضبط التتبّع |
git push origin --delete branch | حذف فرع بعيد | يزيل الفرع | تنظيف الفروع المدموجة |
git push --prune | احذف الفروع البعيدة التي حذفتها محليًا (يحتاج إلى --all أو refspec فيه حرف بدل) | يزيل فروعًا | مزامنة الحذف مع البعيد |
git push --repo=<url> | الدفع إلى مستودع بعيد محدد | المستودع البعيد الهدف | الدفع إلى عنوان URL بعيد بديل |
أمثلة على سير العمل
git remote add origin https://github.com/user/repo.gitأضف عنوان المستودع البعيد
git push -u origin mainادفع الفرع main واجعله يتتبّع origin/main
git statusتحقّق أنك على الفرع الصحيح وأن لديك commits للدفع
git pushادفع إلى فرع الـ upstream المتتبَّع
git checkout featureانتقل إلى فرع ميزتك
git rebase mainأعد التأسيس على main (يعيد كتابة تاريخ الـ commits)
git push --force-with-leaseادفع بالإجبار بأمان - يفشل إن دفع شخص آخر
git checkout -b feature/new-loginأنشئ الفرع الجديد وانتقل إليه
git add . && git commit -m "Add new login"أجرِ تغييراتك واحفظها في commit
git push -u origin feature/new-loginادفع واضبط تتبّع الـ upstream
git push origin --delete feature/old-branchاحذف الفرع البعيد
git branch -d feature/old-branchاحذف الفرع المحلي أيضًا
git push --all originادفع كل الفروع تحت refs/heads/
git push --tags originادفع كل الوسوم أيضًا إن شئت
حل المشكلات
! [rejected] main -> main (fetch first) / (non-fast-forward)
السبب: في الفرع البعيد commits ليست في فرعك المحلي. دفع شخص آخر تغييرات، أو نفّذت rebase/amend على commits مدفوعة أصلًا.
اسحب التغييرات البعيدة أولًا بـ 'git pull --rebase' أو 'git pull --no-rebase'، وحلّ أي تعارضات، ثم ادفع من جديد. لا تدفع بالإجبار (ويُفضّل '--force-with-lease') إلا إن كنت متأكدًا أن لا أحد غيرك يستخدم الفرع.
git pull --rebase && git pushgit@github.com: Permission denied (publickey)
السبب: فشلت مصادقة SSH: لا مفتاح محمَّل، أو مفتاحك العام غير مضاف إلى حسابك. (نقص صلاحية الكتابة يُظهر خطأً مختلفًا هو «Permission to ... denied».)
تأكد أن مفتاح SSH مضاف إلى حسابك على GitHub/GitLab. تحقّق بـ 'ssh -T git@github.com'. ومع HTTPS تأكد أنك تستخدم بيانات الاعتماد الصحيحة.
ssh -T git@github.comfatal: No configured push destination
السبب: لا يوجد في المستودع أي مستودع بعيد مضبوط. (إن وُجد مستودع بعيد لكن الفرع بلا upstream، تظهر بدلًا من ذلك رسالة «The current branch ... has no upstream branch».)
أضف مستودعًا بعيدًا بـ 'git remote add origin <url>'، ثم ادفع مع تعيين الـ upstream بـ 'git push -u origin <branch>'.
git push -u origin mainYour branch is behind 'origin/main'
السبب: في الفرع البعيد commits أحدث من فرعك المحلي. تحتاج إلى دمج هذه التغييرات قبل الدفع.
اجلب التغييرات البعيدة وادمجها أو أعد التأسيس عليها في فرعك المحلي قبل الدفع.
git pull origin main && git pushrefusing to update checked out branch
السبب: تحاول الدفع إلى مستودع غير bare يكون ذلك الفرع مسحوبًا فيه حاليًا. قد يجعل هذا مجلد عمله غير متّسق.
ادفع إلى مستودع bare، أو اطلب من المستقبِل سحب فرع آخر أولًا. يحدث هذا عادةً مع الخوادم الشخصية، لا مع GitHub/GitLab.
git config receive.denyCurrentBranch updateInsteaderror: failed to push some refs to '<remote-url>'
السبب: خطأ عام له أسباب متعددة: تحديثات non-fast-forward، أو فشل hooks، أو مشكلات صلاحيات. راجع رسالة الخطأ المفصّلة فوق هذا السطر.
اقرأ مخرجات الخطأ كاملة. غالبًا تكون مشكلة non-fast-forward (اسحب أولًا) أو فشل hook الـ pre-push (أصلح ما يبلغ عنه).
git pull --rebase && git pushفشل hook الـ pre-push
السبب: وجد hook الـ pre-push (تشغيل الاختبارات، فحص الشيفرة، إلخ) مشكلات ومنع الدفع.
أصلح المشكلات التي أبلغ عنها الـ hook. ولا تتجاوزه بـ '--no-verify' إلا عند الضرورة القصوى ومع فهم العواقب.
git push --no-verifyremote: Repository not found
السبب: عنوان المستودع خاطئ، أو حُذف المستودع أو أُعيدت تسميته، أو ليست لديك صلاحية الوصول إليه.
تحقّق من عنوان المستودع بـ 'git remote -v'. تأكد أن المستودع موجود وأن لديك صلاحية الوصول. حدّث العنوان إن لزم.
git remote set-url origin https://github.com/user/correct-repo.gitنصائح وأخطاء شائعة
أفضل الممارسات
- ✓اسحب دائمًا قبل الدفع: شغّل 'git pull' (أو 'git fetch' يليه merge أو rebase) قبل الدفع لتحصل على أحدث التغييرات البعيدة وتتجنّب رفض الدفع.
- ✓استخدم --force-with-lease بدل --force: إن اضطررت إلى الدفع بالإجبار، فإن --force-with-lease أكثر أمانًا لأنه يفشل إن دفع شخص آخر إلى المستودع البعيد منذ آخر fetch لك (أضف --force-if-includes لأمان إضافي).
- ✓عيّن الـ upstream عند أول دفع: استخدم 'git push -u origin branch-name' عند دفع فرع جديد لضبط التتبّع. بعدها يكفي 'git push' وحده.
- ✓لا تدفع بالإجبار أبدًا إلى الفروع المشتركة: الدفع بالإجبار إلى main أو master أو develop قد يدمّر عمل الآخرين. استخدم commits من نوع revert بدل إعادة كتابة التاريخ.
- ✓استخدم قواعد حماية الفروع: اضبط مستودعك لمنع الدفع بالإجبار إلى الفروع المهمة وفرض مراجعة طلبات الدمج.
- ✓ادفع كثيرًا لحفظ نسخة من عملك: الدفع المنتظم لفروع الميزات يعمل كنسخة احتياطية ويتيح للآخرين رؤية تقدّمك.
- ✓تحقّق قبل الدفع: استخدم 'git push --dry-run' لترى ما سيُدفع دون دفعه فعلًا. ممتاز للتحقق المزدوج.
- ✓نظّف الفروع البعيدة: احذف فروع الميزات المدموجة بـ 'git push origin --delete branch-name' ليبقى المستودع البعيد مرتّبًا.
- ✓استخدم الدفع الذرّي للتغييرات المترابطة: عند دفع عدة فروع يعتمد بعضها على بعض، استخدم '--atomic' لضمان نجاحها كلها أو فشلها كلها.
- ✓وقّع الدفعات المهمة: في المستودعات الحساسة أمنيًا، استخدم '--signed' لتوقيع طلبات الدفع بـ GPG للتحقق منها (يجب أن يدعم الخادم الدفع الموقّع، وإلا فشل الدفع).
أخطاء متكررة
- ✗الدفع دون سحب أولًا: إن كانت في المستودع البعيد commits جديدة فسيُرفض دفعك. نفّذ دائمًا 'git pull' (أو fetch ثم merge/rebase) أولًا لضمّ التغييرات البعيدة.
- ✗استخدام --force على الفروع المشتركة: الدفع بالإجبار يعيد كتابة التاريخ وقد يدمّر عمل الآخرين. استخدم --force-with-lease بدلًا منه، أو الأفضل تجنّب الدفع بالإجبار إلى الفروع المشتركة كليًا.
- ✗نسيان تعيين الـ upstream بـ -u: عند أول دفع لفرع جديد، استخدم 'git push -u origin branch-name' لضبط التتبّع. وإلا فستحتاج إلى تحديد المستودع البعيد والفرع في كل مرة.
- ✗الدفع إلى الفرع الخطأ: تحقّق من فرعك الحالي بـ 'git branch' قبل الدفع. استخدم صيغة صريحة مثل 'git push origin feature:feature' للاطمئنان.
- ✗عدم فهم رفض الدفع: أخطاء 'non-fast-forward' تعني أن في المستودع البعيد commits ليست لديك محليًا. اسحب وادمج/أعد التأسيس قبل الدفع، ولا تدفع بالإجبار ببساطة.
الأسئلة الشائعة
'git push' يرفع commits المحلية إلى مستودع بعيد، فتصبح تغييراتك متاحة للآخرين. و'git pull' ينزّل commits من مستودع بعيد ويدمجها في فرعك المحلي. الدفع يرسل البيانات إلى الخارج؛ والسحب يجلبها إلى الداخل.
لا يمكنك «التراجع» فعلًا عن دفع لأنه صار تاريخًا مشتركًا. للعكس الآمن، استخدم 'git revert HEAD' لإنشاء commit جديد يلغي التغييرات، ثم ادفع من جديد. تجنّب 'git reset' + الدفع بالإجبار على الفروع المشتركة لأنه يعيد كتابة تاريخ ربما سحبه آخرون.
ينشئ الخيار -u علاقة تتبّع بين فرعك المحلي والفرع البعيد. بعد 'git push -u origin feature' يمكنك استخدام 'git push' و'git pull' ببساطة دون تحديد المستودع البعيد والفرع في كل مرة.
لا يُستخدم الدفع بالإجبار (--force) إلا على فروع تساهم فيها وحدك، مثل فروع الميزات الشخصية بعد rebase. لا تدفع بالإجبار أبدًا إلى فروع مشتركة مثل main أو develop. وإن اضطررت، فاستخدم --force-with-lease للأمان.
استخدم صيغة refspec: 'git push origin local-branch:remote-branch'. مثلًا، 'git push origin feature:experiment' يدفع فرعك المحلي 'feature' إلى فرع بعيد اسمه 'experiment'.
عادةً لأن في المستودع البعيد commits ليست لديك محليًا (non-fast-forward). شغّل 'git pull' لجلب تلك التغييرات ودمجها، وحلّ أي تعارضات، ثم ادفع من جديد. لا تدفع بالإجبار إلا إن كنت متأكدًا أنه آمن.
استخدم 'git push --all origin' لدفع كل الفروع المحلية إلى المستودع البعيد. تحتاج الوسوم إلى أمر منفصل لأن '--all' و'--tags' لا يجتمعان: 'git push --tags origin'.
'--force' يكتب فوق الفرع البعيد دون تحقق أيًّا كانت حالته. أما '--force-with-lease' فلا يكتب فوقه إلا إن لم يتغيّر البعيد منذ آخر fetch لك - ويفشل إن دفع شخص آخر، فيحمي عمله. تنبيه: أي fetch (حتى الـ fetch الخلفي في بيئة التطوير) يجدّد ذلك الفحص، فأضف --force-if-includes لتشترط أيضًا أنك دمجت ما جلبته.
استخدم 'git push origin --delete branch-name' أو الصيغة المختصرة 'git push origin :branch-name'. كلاهما يزيل الفرع من المستودع البعيد.
'git push' وحده لا يعمل إلا إن كان للفرع الحالي فرع upstream مضبوط. للفروع الجديدة تحتاج أولًا إلى 'git push -u origin branch-name'. تحقّق من علاقات التتبّع بـ 'git branch -vv'.