سؤال

هل يعرف أحد كيفية التراجع بسهولة عن إعادة قاعدة git؟

الطريقة الوحيدة التي تتبادر إلى ذهنك هي القيام بذلك يدويًا:

  • git checkout الأصل الملتزم بكلا الفرعين
  • ثم قم بإنشاء فرع مؤقت من هناك
  • اختر الكرز جميع الالتزامات يدويًا
  • استبدل الفرع الذي قمت بإعادة تأسيسه بالفرع الذي تم إنشاؤه يدويًا

في وضعي الحالي، سيعمل هذا لأنه يمكنني بسهولة اكتشاف الالتزامات من كلا الفرعين (أحدهما كان أشيائي والآخر كان أشياء زميلي).

ومع ذلك، يبدو لي أن النهج الذي أتبعه هو دون المستوى الأمثل وعرضة للخطأ (لنفترض أنني قمت للتو بإعادة تأسيس فرعين من فروعي الخاصة).

أيه أفكار؟

إيضاح:أنا أتحدث عن إعادة قاعدة تم خلالها إعادة تشغيل مجموعة من الالتزامات.ليست واحدة فقط.

هل كانت مفيدة؟

المحلول

أسهل طريقة هي العثور على الالتزام الرئيسي للفرع كما كان قبل بدء عملية إعادة الأساس مباشرة في ملف إعادة التسجيل...

git reflog

وإعادة تعيين الفرع الحالي إليه (مع التحذيرات المعتادة حول التأكد تمامًا قبل إعادة التعيين باستخدام --hard خيار).

لنفترض أن الالتزام القديم كان HEAD@{5} في سجل المرجع:

git reset --hard HEAD@{5}

في نظام التشغيل Windows، قد تحتاج إلى ذكر المرجع:

git reset --hard "HEAD@{5}"

يمكنك التحقق من تاريخ الرأس القديم للمرشح بمجرد القيام بذلك git log HEAD@{5} (شبابيك: git log "HEAD@{5}").

إذا لم تقم بتعطيل عمليات إعادة التسجيل لكل فرع، فيجب أن تكون قادرًا على القيام بذلك ببساطة git reflog branchname@{1} حيث تقوم إعادة القاعدة بفصل رأس الفرع قبل إعادة توصيله بالرأس النهائي.أود التحقق من ذلك مرة أخرى، على الرغم من أنني لم أتحقق من ذلك مؤخرًا.

افتراضيًا، يتم تنشيط جميع عمليات إعادة التسجيل للمستودعات غير العارية:

[core]
    logAllRefUpdates = true

نصائح أخرى

في الواقع، rebase يحفظ نقطة البداية الخاصة بك إلى ORIG_HEAD لذلك عادة ما يكون هذا بسيطًا مثل:

git reset --hard ORIG_HEAD

ومع ذلك، reset, rebase و merge جميع حفظ الأصلي الخاص بك HEAD المؤشر في ORIG_HEAD لذا، إذا قمت بتنفيذ أي من هذه الأوامر منذ إعادة التعيين الذي تحاول التراجع عنه، فسيتعين عليك استخدام إعادة التسجيل.

تعمل إجابة تشارلز، ولكن قد ترغب في القيام بذلك:

git rebase --abort

لتنظيف بعد reset.

وإلا فقد تصلك الرسالة "Interactive rebase already started”.

git reflog سيعرض لك جميع التغييرات قبل وبعد إعادة التعيين، ويتيح لك العثور على التغيير المناسب لإعادة التعيين إليه.لكنني مندهش من عدم ذكر أحد لهذه الطريقة البسيطة الأخرى هنا حتى الآن:

Rebase يترك الحالة القديمة كما ORIG_HEAD, ، حتى تتمكن من إعادة آخر عملية إعادة إنشاء عن طريق تشغيل:

git reset --hard ORIG_HEAD

إن إعادة تعيين الفرع إلى كائن الالتزام المتدلي لطرفه القديم هو الحل الأفضل بالطبع، لأنه يستعيد الحالة السابقة دون بذل أي جهد.ولكن إذا فقدت تلك الالتزامات (f.ex.نظرًا لأنك قمت بجمع البيانات المهملة لمستودعك في هذه الأثناء، أو أن هذه نسخة جديدة)، يمكنك دائمًا إعادة إنشاء الفرع مرة أخرى.المفتاح لهذا هو --onto يُحوّل.

لنفترض أن لديك فرع موضوع يسمى بشكل خيالي topic, ، التي تشعبت master عندما غيض من master كان 0deadbeef يقترف.في مرحلة ما أثناء وجودك على topic فرع، فعلتم git rebase master.الآن تريد التراجع عن هذا.إليك الطريقة:

git rebase --onto 0deadbeef master topic

سيستغرق هذا جميع الالتزامات topic التي ليست قيد التشغيل master واعادتها على رأس 0deadbeef.

مع --onto, ، يمكنك إعادة ترتيب سجلك إلى حد كبير بأي شكل كان.

استمتع.:-)

لقد قمت بالفعل بوضع علامة احتياطية على الفرع قبل أن أقوم بأي عملية غير تافهة (معظم عمليات إعادة الأساس تافهة، لكنني سأفعل ذلك إذا بدت معقدة في أي مكان).

ومن ثم، فإن عملية الاستعادة تكون بنفس السهولة git reset --hard BACKUP.

في حال لقد دفعت فرعك إلى المستودع البعيد (عادةً ما يكون الأصل) ثم قمت بإجراء إعادة صياغة ناجحة (بدون دمج) (git rebase --abort يعطي "لا يوجد rebase قيد التقدم") يمكنك ذلك بسهولة إعادة تعيين فرع باستخدام الأمر:

إعادة تعيين بوابة --hard Origin/{branchName}

مثال:

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is ahead of 'origin/{branchName}' by 135 commits.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

$ ~/work/projects/{ProjectName} $ git reset --hard origin/{branchName}
HEAD is now at 6df5719 "Commit message".

$ ~/work/projects/{ProjectName} $ git status
On branch {branchName}
Your branch is up-to-date with 'origin/{branchName}.

nothing to commit, working directory clean

في حالة عدم إكمال عملية إعادة الأساس وفي منتصفها، يعمل ما يلي:

git rebase --abort

استخدام reflog لم يعمل بالنسبة لي.

ما نجح بالنسبة لي كان مشابهًا لما هو موضح هنا.افتح الملف في .git/logs/refs المسمى على اسم الفرع الذي تم إعادة تأسيسه وابحث عن السطر الذي يحتوي على "rebase finsihed"، مثل:

5fce6b51 88552c8f Kris Leech <me@example.com> 1329744625 +0000  rebase finished: refs/heads/integrate onto 9e460878

قم بالخروج من الالتزام الثاني المدرج على السطر.

git checkout 88552c8f

بمجرد التأكد من أن هذا يحتوي على التغييرات المفقودة، تفرعت وتنفست الصعداء.

git log
git checkout -b lost_changes

بالنسبة للالتزامات المتعددة، تذكر أن أي التزام يشير إلى السجل بأكمله الذي سبق هذا الالتزام.لذا، في إجابة تشارلز، اقرأ "الالتزام القديم" على أنه "الأحدث بين الالتزامات القديمة".إذا قمت بإعادة التعيين على هذا الالتزام، فسيظهر كل السجل الذي سبق هذا الالتزام مرة أخرى.هذا يجب أن يفعل ما تريد.

بعد حل @Allan و@Zearin، أتمنى أن أتمكن من التعليق ببساطة، لكني لا أتمتع بالسمعة الكافية، لذلك استخدمت الأمر التالي:

بدلا من القيام git rebase -i --abort (لاحظ ال -أنا) كان علي أن أفعل ذلك ببساطة git rebase --abort (بدون ال -أنا).

باستخدام كليهما -i و --abort في نفس الوقت يجعل Git يعرض لي قائمة الاستخدام/الخيارات.

لذا فإن حالة فرعي السابقة والحالية مع هذا الحل هي:

matbhz@myPc /my/project/environment (branch-123|REBASE-i)
$ git rebase --abort

matbhz@myPc /my/project/environment (branch-123)
$

إذا نجحت في إعادة الاعتماد على الفرع البعيد ولم تتمكن من ذلك git rebase --abort لا يزال بإمكانك القيام ببعض الحيل لحفظ عملك وليس لديك دفعات قسرية.لنفترض أن فرعك الحالي الذي تم إعادة تأسيسه عن طريق الخطأ يسمى your-branch ويتم تتبع origin/your-branch

  • git branch -m your-branch-rebased # إعادة تسمية الفرع الحالي
  • git checkout origin/your-branch # الخروج إلى أحدث حالة معروفة للمنشأ
  • git checkout -b your-branch
  • يفحص git log your-branch-rebased, ، قارن ب git log your-branch وتحديد الالتزامات المفقودة من your-branch
  • git cherry-pick COMMIT_HASH لكل التزام في your-branch-rebased
  • دفع التغييرات الخاصة بك.يرجى العلم أن هناك فرعين محليين مرتبطين بهما remote/your-branch ويجب عليك أن تدفع فقط your-branch

لنفترض أنني قمت بإعادة إنشاء قاعدة رئيسية إلى فرع الميزات الخاص بي وحصلت على 30 التزامًا جديدًا يؤدي إلى كسر شيء ما.لقد وجدت أنه غالبًا ما يكون من الأسهل إزالة الالتزامات السيئة.

git rebase -i HEAD~31

إعادة قاعدة تفاعلية لآخر 31 التزامًا (لن يضر إذا اخترت عددًا كبيرًا جدًا).

ما عليك سوى تنفيذ الالتزامات التي تريد التخلص منها ووضع علامة "d" عليها بدلاً من "pick".يتم الآن حذف الالتزامات بشكل فعال مما يؤدي إلى التراجع عن إعادة التأسيس (إذا قمت بإزالة الالتزامات التي حصلت عليها للتو عند إعادة التأسيس فقط).

إذا كنت في فرع يمكنك استخدام:

git reset --hard @{1}

لا يوجد سجل مرجعي فقط لـ HEAD (تم الحصول عليه بواسطة git reflog)، هناك أيضًا عمليات إعادة تسجيل لكل فرع (تم الحصول عليها بواسطة git reflog <branch>).لذلك، إذا كنت على master ثم git reflog master سوف يسرد كافة التغييرات على هذا الفرع.يمكنك الرجوع إلى تلك التغييرات من خلال master@{1}, master@{2}, ، إلخ.

git rebase عادةً ما يتم تغيير HEAD عدة مرات ولكن سيتم تحديث الفرع الحالي مرة واحدة فقط.

@{1} هو ببساطة أ اختصار للفرع الحالي, ، فهو يساوي master@{1} إذا كنت على master.

git reset --hard ORIG_HEAD لن تعمل إذا كنت تستخدم git reset خلال تفاعلية rebase.

بالنسبة للمبتدئين/أي شخص خائف جدًا من إجراء إعادة التعيين الثابت، يمكنك التحقق من الالتزام من إعادة التسجيل، ثم حفظه كفرع جديد.

git reflog

ابحث عن الالتزام قبل البدء في إعادة التأسيس مباشرةً.قد تحتاج إلى التمرير لأسفل للعثور عليه (اضغط على Enter أو PageDown).لاحظ رقم الرأس واستبدل 57:

git checkout HEAD@{57}

قم بمراجعة الفرع/الالتزامات، إذا كان يبدو جيدًا، قم بإنشاء فرع جديد باستخدام هذا الرأس:

git checkout -b new_branch_name

إعادة تعيين بوابة --hard Origin/{branchName}

هو الحل الصحيح لإعادة ضبط جميع التغييرات المحلية التي تم إجراؤها بواسطة rebase.

ما أفعله عادة هوgit reset #commit_hash

إلى الالتزام الأخير حيث أعتقد أن rebase لم يكن له أي تأثير.

ثم git pull

الآن يجب أن يتطابق فرعك تمامًا مع الالتزامات الرئيسية ويجب ألا يكون موجودًا فيه.

الآن يمكن للمرء فقط اختيار الالتزامات في هذا الفرع.

إذا أفسدت شيئًا ما داخل git rebase، على سبيل المثال. git rebase --abort, ، بينما لديك ملفات غير ملتزم بها، سيتم فقدها و git reflog لن يساعد.لقد حدث هذا معي وسوف تحتاج إلى التفكير خارج الصندوق هنا.إذا كنت محظوظًا مثلي واستخدمت IntelliJ Webstorm، فيمكنك ذلك right-click->local history ويمكنه العودة إلى الحالة السابقة لملفاتك/مجلداتك بغض النظر عن الأخطاء التي ارتكبتها في إصدار البرامج.من الجيد دائمًا تشغيل آخر آمن من الفشل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top