الخلاصة: شغّل git fetch upstream && git merge upstream/main && git push origin main وسيلحق fork بالتطورات. هذا هو كامل مسار “مزامنة fork مع upstream” في سطر واحد — اسحب تغييرات المشروع الذي فرشعت منه، ثم ادفعها إلى نسختك. وإذا فضلت التاريخ الخطي، فاستبدل merge بـ git rebase upstream/main وادفع قسرًا. وإذا لم تربط remote الـ upstream أصلًا، فابدأ بالخطوة 1 أدناه، لأن ذلك الـ remote الغائب هو السبب الأول لأن يقول أحدهم “fork لا يريد المزامنة”. كل ما عدا ذلك — الـ rebase وزر مزامنة GitHub والفروع المتباعدة التي ترفض الدفع — تفاصيل فوق هذه الأوامر الثلاثة.
ماذا يعني مزامنة fork مع upstream؟
الـ fork هو نسختك من مستودع شخص آخر على GitHub. الأصل هو upstream، ونسختك هي origin. فروع GitHub لا تُحدَّث ذاتيًا — حين يدمج المشرفون طلب سحب، تبقى نسختك على كود الأمس. مزامنة الـ fork تعني سحب commits الجديدة من upstream إلى نسختك حتى يطابق فرعك الحالة الراهنة للمشروع أو يحتويها على الأقل.
هذا مهم لسببين. أولًا المساهمات: كل طلب سحب تفتحه من fork قديم يحمل ضجيجًا زائدًا، وسيرحب المشرفون بتحديثه قبل الدمج. وثانيًا الاستضافة الذاتية أو الدراسة: إن كنت تشغّل fork في الإنتاج أو تقرأ كوده فحسب، فfork عمره شهر يعني شهرًا من إصلاحات الأخطاء لا تملكها.
كيف أمزام الـ fork مع upstream من سطر الأوامر؟
ثلاث خطوات: عرّف الـ upstream مرة واحدة، اسحب منه، ثم ادمج وادفع. التوصيل دائم — الخطوتان 2 و3 هما كل ما تكتبه لاحقًا.
الخطوة 1 — أضف remote الـ upstream (مرة واحدة لكل استنساخ).
# داخل نسختك المحلية من الـ fork
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
git remote -v # تأكد: origin -> الـ fork الخاص بك، upstream -> الأصل اعثر على العنوان الصحيح من صفحة المستودع الأصلي: زر Code الأخضر. والخطأ الشائع أن تشير remotes الاثنين إلى الـ fork الخاص بك — عندها “المزامنة” تفعل شيئًا بصمت، لأنك سحبت من نسخة قديمة مثل نسختك تمامًا.
الخطوة 2 — اسحب وادمج فرع الـ upstream.
git checkout main
git fetch upstream
git merge upstream/main
git push origin main هذا هو الجواب القياسي لسؤال “أمر مزامنة fork مع upstream في سطر الأوامر”. النتيجة الاعتيادية fast-forward — main في الـ fork لم يكن فيه جديد، فينزلق ببساطة إلى upstream/main بلا merge commit جديد.
الخطوة 3 — كرّرها عند الحاجة. لا شيء يحفظه سوى git fetch upstream && git merge upstream/main && git push origin main. ولمعرفة مدى تخلفك قبل الدمج، شغّل git rev-list --count main..upstream/main بعد الـ fetch.
أختار rebase أم merge عند مزامنة الـ fork؟
كلاهما يهبط بالكود نفسه إلى الـ fork؛ الفرق في التاريخ الذي يتركانه. اختر سياسة واحدة لكل مستودع والتزم بها:
| الطريقة | الأمر | نتيجة التاريخ | الأفضل لـ |
|---|---|---|---|
| Merge | git merge upstream/main | merge commit إضافي عند تباعد الفروع | فروع الميزات ذات طلبات السحب المفتوحة — لا يعيد كتابة شيء أبدًا |
| Rebase | git rebase upstream/main | commits تعاد فوق القمة بتاريخ خطي | إبقاء main في الـ fork نظيفًا؛ والفروع المتباعدة التي تريد تصفيرها |
| واجهة GitHub | زر Sync branch أو دمج PR | مثل merge | لحاق سريع بلا استنساخ مفتوح |
نسخة الـ rebase من المزامنة:
git fetch upstream
git rebase upstream/main
git push --force-with-lease origin main الدفع القسري مطلوب لأن الـ rebase يعيد كتابة معرفات الـ commits — فرع الـ fork البعيد لم يعد سليلًا لفرعك المحلي. وفضّل دائمًا --force-with-lease على --force: فهي ترفض الكتابة فوق البعيد إذا دفع أحدهم (أو جهاز آخر لك) في الأثناء، وهذا يجعل الأمر الخطير آمنًا افتراضيًا.
وقاعدة تستحق الوشم على الرسغ: لا تعِد أبدًا rebase لفرع عليه طلب سحب مفتوح ما لم تكن تعرف ما تفعل — الـ rebase يغير معرفات الـ commits وقد يفصل طلبًا مفتوحًا عن commits التابعة له. زامن main بالدمج (أو أعد تنظيمه قبل بدء عمل جديد)، وأبقِ فروع طلبات السحب خارج الموضوع.
لماذا لا يتزامن fork الخاص بي مع upstream؟
المشتبه بهم الأربعة المعتادون، بترتيب ظهورهم في الطرفيات الحقيقية:
- لا يوجد remote باسم
upstream— يعرضgit remote -vخطoriginفقط. العرَض: يفشلgit fetch upstreamبرسالة'upstream' does not appear to be a git repository. الإصلاح: الخطوة 1 أعلاه. - سحبت ولم تدمج — الـ fetch يحدّث
upstream/mainفي مستودعك المحلي لكنه لا يلمس أي فرع عمل. العرَض: يبدوgit logقديمًا بعد fetch ناجح. الإصلاح:git merge upstream/main. - تاريخ متباعد — commitت على
mainفي الـ fork، وتحرك upstream أيضًا. يشتكيgit pullحينها من تواريخ غير مترابطة أو يفرض دمجًا. الإصلاح، إذا أردت انتصار upstream:git reset --hard upstream/main(يرمي commits التي خاصت بـ main المحلي فقط — راجعgit stash listأو خذ نسخة على فرع أولًا؛ وإذا وقع reset سيئ فعلًا فمسار الاسترداد نفسه في التراجع عن آخر commit: الـgit reflogما يزال يعرف القمة القديمة). - رفض الدفع كغير fast-forward بعد rebase — أعدت التنظيم ثم دفعت بشكل عادي. الإصلاح:
git push --force-with-lease origin main.
وحالة خامسة نادرة: المستودع الأصلي أعيدت تسميته أو حُذف، فيُرجع عنوان الخطوة 1 نفسها 404. يحوّل GitHub تسمية المستودعات، فالفشل الصلب يعني عادة حذفًا أو إغلاقًا — ولا شيء للمزامنة معه.
هل يمكن مزامنة الـ fork من موقع GitHub؟
نعم. في صفحة الـ fork، يظهر زر Sync fork في قائمة الفروع كلما تخلف فرعك؛ بنقرة واحدة يدخل upstream. وأسفل الصفحة، يعمل الشيء نفسه كطلب سحب: افتح PR من upstream/main إلى main في الـ fork وادمجه.
حدود الزر تشرح متى تعود إلى سطر الأوامر: لا يفعل سوى fast-forward أو دمج — لا يعيد التنظيم، ويرفض رفضًا قاطعًا إذا تباعدت الفروع، قائلًا لك أن تتخلص من commits أو تستخدم سطر الأوامر. كما أنه يزامن الفرع الافتراضي فقط. وكل ما عدى اللحاق البسيط، فالأوامر الثلاثة أعلاه هي الأداة.
كم مرة تزامن الـ fork؟
قبل كل عمل جديد هو الجواب الصادق: اشتق فرعًا من main طازج، فلا يبدأ أي طلب سحب تفتحه بعبارة “هذا مبني على نسخة عمرها ثلاثة أسابيع”. وللفروع التي تساهم فيها بنشاط، مزامنة يومية أو لكل جلسة لـ main تكلف ثوانٍ. وfork تقرأه أو تنشره فقط، زامنه حين يطلق upstream شيئًا تريده — اشترك في موجز الإصدارات للمستودع الأصلي وزامن عند كل إصدار. المزامنة رخيصة بالضبط لأنها روتينية؛ والـ fork المتخلف ستة أشهر يحتاج غالبًا جراحة لا دمجًا، وهكذا يتحول “زامن fork الخاص بي” إلى بعد غداء كامل.
ورقة أوامر
# إعداد لمرة واحدة
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
# مزامنة روتينية (سياسة الدمج)
git fetch upstream && git merge upstream/main && git push origin main
# مزامنة روتينية (سياسة rebase، تاريخ خطي)
git fetch upstream && git rebase upstream/main && git push --force-with-lease origin main
# كم أنا متأخر؟
git fetch upstream && git rev-list --count main..upstream/main
# تباعد فاقد للإصلاح — اجعل main مطابقًا لـ upstream (مدمّر)
git fetch upstream && git reset --hard upstream/main && git push --force-with-lease origin main احفظ السطرين الروتينيين في ذاكرتك العضلية وسيبقى الـ fork المتباعد حكاية تقرأها لا مشكلة تصلحها. وإذا امتد تنظيم Git عندك إلى الخوادم، فتغطي ورقة أوامر journalctl النصف الآخر من إبقاء تاريخ الجهاز مقروءًا.
— mrsaynothing
— mrsaynothing
ملاحظات ميدانية في الذكاء الاصطناعي وLinux والاستضافة الذاتية.
ناقش هذا المقال على dev.to dev.to ↗
احصل على الشرح التطبيقي التالي بالبريد
رسالة واحدة لكل مقال. أصلح المشكلة وامضِ.
ما هذا؟ss مقابل netstat: أي أمر منافذ تستخدم في لينكس
أعجبتك هذه الكتابات؟ بناء مثل هذا هو عملي. وظّفني