هل يؤدي دفع مستودع Git الحالي إلى Github إلى إرسال حوالي نصف الالتزامات فقط؟
-
04-07-2019 - |
سؤال
لدي مستودع Git محلي قمت بتطويره منذ بضعة أيام:لديها ثمانية عشر التزامًا حتى الآن.الليلة، أنشأت مستودعًا خاصًا على Github وكنت أتمنى نقله إليه؛ومع ذلك، عندما فعلت ذلك، انتهى الأمر فقط بدفع ثمانية من الالتزامات الثمانية عشر إلى Github.لقد قمت بحذف Github repo وأعدت المحاولة، وكانت النتيجة نفسها.
هل هناك أي أفكار حول سبب حدوث ذلك؟لقد قمت بهذا الإجراء من قبل دون نجاح عدة مرات، لذا فأنا في حيرة من أمري.
تحديث:لا يوجد، وكان دائمًا، سوى الفرع الرئيسي في هذا الريبو.فقط لمعالجة بعض الإجابات المنشورة ...
المحلول
لقد ألقيت نظرة على المستودع المعني وإليك ما كان يحدث:
- في مرحلة ما، كان أداء rpj
git checkout [commit id]
.أدى هذا إلى توجيه HEAD إلى التزام فضفاض بدلاً من فرع معترف به.أعتقد أن هذه هي مشكلة "الرأس المتدلي" التي يشير إليها سيزار بي. - ولم يدرك هذه المشكلة، فقد استمر في إجراء التغييرات والالتزام بها، الأمر الذي كان يصدم رأسه في كل مرة.ومع ذلك، كان HEAD يشير فقط إلى سلسلة متدلية من الالتزامات، وليس إلى فرع معروف.
- عندما ذهب لدفع تغييراته، دفع git كل شيء إلى قمة master، والتي كانت في منتصف الشجرة الحالية التي كان عليها.
- تلا ذلك الارتباك
يجب أن يوضح هذا الرسم البياني أكثر:
-- D -- E -- F
/ ^
A -- B -- C - |
^ ^ HEAD
| |
remote master
عندما حاول دفع تغييراته، فقط A
خلال C
تم دفعهم و remote
انتقل إلى C
.لم يتمكن من الحصول على الالتزامات D
خلال F
للدفع لأنه لم تتم الإشارة إليها بواسطة فرع معروف.
إليك ما تراه عندما تكون في هذه الحالة:
$ git branch
* (no branch)
master
الحل هو التحرك master
يصل إلى F
في سلسلة الالتزامات المتدلية.وإليك كيف فعلت ذلك.
إنشاء فرع شرعي للحالة الحالية:
git checkout -b tmp
- ال
tmp
يشير الفرع الآن إلى الالتزامF
في الرسم البياني أعلاه
- ال
سريع إلى الأمام
master
لtmp
git checkout master
git merge tmp
master
يشير الآن إلى الالتزامF
.
تخلص من فرعك المؤقت
git branch -d tmp
يمكنك بكل سرور الدفع إلى المستودع البعيد ويجب أن يرسل جميع تغييراتك.
نصائح أخرى
ومن بوابة 1.7.3 فصاعدا، يمكنك القيام بذلك مع أمر واحد بسيط:
git checkout -B master
والتبديل -b
يعني "إنشاء فرع هنا قبل التدقيق بها" و-B
هي النسخة غير المشروط من ذلك، "حتى لو كان فرع موجود بالفعل - في هذه الحالة، نقله هنا قبل التدقيق بها".
ونهج بسيط جدا لتحديد هذا النوع من المشكلة هو مجرد حذف فرع master
وإعادة إنشائها. بعد كل شيء، فروع في بوابة هي مجرد أسماء ليرتكب وفرع master
شيء خاص.
وحتى على افتراض أن التيار ارتكاب هو واحد كنت تريد أن تكون master
، يمكنك ببساطة القيام به
git branch -D master
لحذف فرع master
القائمة، ثم القيام
git checkout -b master
لأ) إنشاء فرع جديد يسمى master
الذي يشير إلى التيار ارتكابها وب) تحديث HEAD
للإشارة إلى فرع master
. بعد ذلك، سوف تعلق HEAD
إلى master
وبالتالي master
سوف تتحرك إلى الأمام كلما يرتكبها.
تحقق مما إذا كنت تدفع الفروع الصحيحة، وأن الفروع لديها بالفعل ما تعتقد أنها تمتلكه.على وجه الخصوص، تحقق مما إذا لم يكن لديك رأس منفصل، الأمر الذي قد يكون مربكًا للغاية إذا لم يتم ذلك عن قصد.
أسهل طريقة للتحقق هي الاستخدام gitk --all
, ، والذي يُظهر بيانيًا جميع الفروع والرأس والمزيد.
وأعتقد أن أول شيء أود أن تفعل يكون لتشغيل git fsck
على مستودع المحلي الخاص بك للتأكد من أن كل ذلك هو في حالة جيدة.
وأنا لم أر قط هذه المشكلة من قبل، وأنا لا أستطيع التفكير في ما قد يكون خطأ.
وليس لدي سمعة التعليق مباشرة على الجواب CesarB في وقت سابق، ولكن gitk --all
لا يعمل في هذه الحالة لأنه يسرد فقط من الفروع معروفة.
وgitk HEAD
يظهر هذه المشكلة، ولكنها ليست واضحة تماما. بندقية التدخين هو أن master
يظهر أسفل شجرة ارتكاب وليس في آخرها ارتكاب.
وبذلك يتبين أن كلاً من:كانت تجزئة الالتزام في .git/refs/heads/master صحيحة وكانت المعلومات الموجودة في .git/logs/refs/heads/master غير كاملة؛أعني أنه تم رفعه فقط إلى تجزئة الالتزام المحددة في .git/refs/heads/master وتضمينها.
بمجرد إصلاح هذه الملفات (يدويًا)، وإعادتها إلى Github، أصبح كل شيء على ما يرام مرة أخرى.ما زلت أمتلك لا يوجد فكرة ما الذي حدث حتى وصلت الأمور إلى هذه الحالة، ولكنني سعيد لأنني على الأقل اكتشفت الحل.
وفي حال تساءل أحد:لإصلاح .git/refs/heads/master، قمت للتو باستبدال محتوى هذا الملف بأحدث تجزئة التزام (HEAD)، ولإصلاح .git/logs/refs/heads/master، قمت ببساطة بنسخ محتويات .git /logs/HEAD إلى .git/logs/refs/heads/master.سهل جدا...لا.
ولقد كان هذا نفس المشكلة مرتين، وبرزت أخيرا ما كنت أفعله الذي يسبب ذلك. في عملية تحرير ارتكاب القديم مع git rebase -i
، بدلا من استدعاء git commit --amend
، وكنت تدعو git commit -a
بالقوة العادة، تليها مباشرة git rebase --continue
، بطبيعة الحال. شخص آخر قد تكون قادرة على شرح ما يجري وراء الكواليس، ولكن يبدو أن النتيجة هي المشكلة رأس منفصلة.