تخطَّ إلى المحتوى

١١ يوليو ٢٠٢٦

حل خطأ failed to push some refs في Git بالعربي

شارك المقال:

تدفع عملك بثقة فيصدّك Git:

! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:user/repo.git'
hint: Updates were rejected because the remote contains work that you
hint: do not have locally.

الرسالة مخيفة الشكل، لكن معناها جملة واحدة: الفرع على الريموت تقدّم خطوة ليست عندك — والرفض حمايةٌ لتلك الخطوة من الضياع، لا عقوبة لك.

ماذا حدث بالضبط؟

تاريخ الفرع سلسلة commits. عندما تدفع، يشترط Git أن يكون تاريخك امتدادًا مباشرًا لتاريخ الريموت (fast-forward). اللحظة التي يحتوي فيها الريموت commit ليس في سلسلتك — زميل دفع قبلك، أو تعديل من واجهة GitHub — يصبح دفعك «تفرعًا موازيًا» يرفضه Git حتى تدمج.

السيناريوالعلامةالحل
زميل دفع قبلكعمل جماعي على نفس الفرعgit pull ثم push
أنشأت الريبو بـ README من GitHubأول push بالمشروعgit pull --rebase origin main
عدّلت ملفًا من موقع GitHubتذكر تعديلًا سريعًا بالمتصفحgit pull ثم push
عملت rebase/amend لفرع مدفوعغيّرت تاريخًا منشورًا--force-with-lease (فرعك فقط!)

الحل الآمن — يصلح في 95% من الحالات

git pull            # ينزّل عمل الريموت ويدمجه مع عملك
# إن ظهرت تعارضات: حلّها ثم git add و git commit
git push            # ✅ الآن تاريخك امتداد للريموت

تفضّل تاريخًا مستقيمًا بلا commit دمج إضافي؟

git pull --rebase   # يعيد وضع عملك «فوق» عمل الريموت
git push

💡 التعارضات إن ظهرت أثناء الدمج ليست كارثة — دليلنا الكامل: حل Merge Conflict خطوة بخطوة.

حالة «أول دفع» الشهيرة

أنشأت المستودع على GitHub مع README، وبدأت محليًا بـ git init؟ التاريخان منفصلان تمامًا ولا يعرفان بعضهما، فيرفض Git ربطهما:

git pull origin main --allow-unrelated-histories
git push -u origin main

(والوقاية بسيطة: عند ربط مشروع محلي موجود، أنشئ الريبو على GitHub فارغًا بلا README ولا رخصة.)

القوة — متى ولماذا وبأي صيغة

أحيانًا التاريخ المحلي هو الصحيح فعلًا — بعد rebase أو commit --amend لفرعك الشخصي المدفوع سابقًا. هنا فقط:

# ✅ الصيغة الآمنة: تفشل لو دفع أحد شيئًا لم تره
git push --force-with-lease

# ❌ تجنّبها: تمحو أي شيء على الريموت بشكل أعمى
git push --force

القاعدة الحمراء: لا قوة على فرع يعمل عليه غيرك أبدًا — ستمحو عملهم وتكسب عداوتهم في نفس الأمر 😅. القوة لفروعك الشخصية حصرًا.

قائمة تحقّق سريعة

  • git pull ثم push — الحل الافتراضي دائمًا.
  • تاريخ أنظف؟ git pull --rebase.
  • أول دفع لريبو أُنشئ بـ README؟ → --allow-unrelated-histories.
  • بعد rebase لفرعك الشخصي فقط: --force-with-lease وليس --force.
  • فرع مشترك = ممنوع القوة، مهما كانت الظروف.

الخلاصة

failed to push some refs ليس عطلًا بل بوابة أمان: الريموت يحمل عملًا ليس عندك، وGit يطلب أن تدمجه محليًا قبل النشر. pull ثم push يحلها دائمًا تقريبًا — والقوة استثناء ضيق لفرعك وحدك بصيغة --force-with-lease.

أتقن الفروع والريموت في مسار Git بالعربي، وأكمل السلسلة مع حل خطأ fatal: not a git repository و حل Merge Conflict.

📚 مصادر رسمية للتعمّق: التوثيق الرسمي لـ Git

الأسئلة الشائعة

لماذا يرفض Git الدفع أصلًا بدل أن يدمج تلقائيًا؟

حماية لعمل الآخرين: لو قبل دفعك كما هو لضاعت commits الموجودة على الريموت وليست عندك. الرفض رسالة تقول «نزّل عمل زملائك أولًا، ادمجه محليًا حيث تستطيع حل أي تعارض، ثم ادفع الكل».

ما الفرق بين --force و --force-with-lease؟

كلاهما يستبدل تاريخ الريموت بتاريخك، لكن --force يفعلها بشكل أعمى حتى لو دفع أحدهم عملًا جديدًا قبل ثانية، بينما --force-with-lease يرفض إن تغيّر الريموت عمّا تعرفه — فيمنع محو عمل لم تره. إن اضطررت للقوة يومًا فالصيغة الثانية دائمًا.

متى يظهر هذا الخطأ رغم أني أعمل وحدي؟

أشهر حالة: أنشأت المستودع على GitHub مع ملف README أو رخصة، ثم حاولت أول دفع من مشروع محلي — الريموت عنده commit البداية وأنت لا. حلها git pull --rebase ثم push. أو عدّلت ملفًا من واجهة GitHub مباشرة ونسيت.

اقرأ أيضًا

تصفّح كل المقالات في المدوّنة، أو ابدأ التعلّم من المسارات و خرائط الطريق.