التراجع عن إعادة قاعدة git
-
02-07-2019 - |
سؤال
هل يعرف أحد كيفية التراجع بسهولة عن إعادة قاعدة 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
ويمكنه العودة إلى الحالة السابقة لملفاتك/مجلداتك بغض النظر عن الأخطاء التي ارتكبتها في إصدار البرامج.من الجيد دائمًا تشغيل آخر آمن من الفشل.