كيف يمكنني التعافي/إعادة التزامن بعد أن يدفع شخص ما إلى إعادة ضبط أو إعادة تعيين إلى فرع منشور؟

StackOverflow https://stackoverflow.com/questions/4084868

سؤال

لقد سمعنا جميعًا أنه لا ينبغي لأحد أن ينشر العمل ، وأنه خطير ، وما إلى ذلك. ومع ذلك ، لم أر أي وصفات منشورة لكيفية التعامل مع الموقف في حالة Rebase هو نشرت.

الآن ، لاحظ أن هذا أمر ممكن حقًا إذا لم يتم استنساخ المستودع إلا من قبل مجموعة معروفة (ويفضل أن تكون صغيرة) من الأشخاص ، بحيث يمكن لأي شخص يدفع Rebase أو إعادة تعيينه إخطار الجميع بأنهم سيحتاجون إلى الاهتمام في المرة القادمة أحضر(!).

سيعمل أحد الحلول الواضحة التي رأيتها إذا لم يكن لديك أي علاقة محلية foo ويتم تربيتها:

git fetch
git checkout foo
git reset --hard origin/foo

هذا سوف يرمي ببساطة الحالة المحلية foo لصالح تاريخها حسب المستودع البعيد.

ولكن كيف يمكن للمرء أن يتعامل مع الموقف إذا ارتكب المرء تغييرات محلية كبيرة على هذا الفرع؟

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

المحلول

العودة إلى التزامن بعد دفع Rebase ليس معقدًا في معظم الحالات.

git checkout foo
git branch old-foo origin/foo # BEFORE fetching!!
git fetch
git rebase --onto origin/foo old-foo foo
git branch -D old-foo

بمعنى آخر. أولاً ، قمت بإعداد إشارة مرجعية للمكان الذي كان فيه الفرع البعيد في الأصل ، ثم يمكنك استخدام ذلك لإعادة تشغيل الالتزامات المحلية الخاصة بك من تلك النقطة فصاعدًا على الفرع البعيد المُعاد للبرد.

إن إعادة التثبيت مثل العنف: إذا لم يحل مشكلتك ، فأنت بحاجة فقط إلى المزيد منها. ☺

يمكنك القيام بذلك دون إشارة مرجعية بالطبع ، إذا بحثت عن إعادة البيئة قبل origin/foo ارتكب معرف ، واستخدم ذلك.

هذه هي أيضًا الطريقة التي تتعامل بها مع الموقف الذي نسيت أن تصنع إشارة مرجعية قبل جلب. لا شيء ضائع - تحتاج فقط إلى التحقق

git reflog show origin/foo | awk '
    PRINT_NEXT==1 { print $1; exit }
    /fetch: forced-update/ { PRINT_NEXT=1 }'

هذا سيطبع معرف الالتزام الذي origin/foo أشارت قبل الجلب الأخير الذي غير تاريخها.

يمكنك بعد ذلك ببساطة

git rebase --onto origin/foo ارتكاب $ foo

نصائح أخرى

أود أن أقول التعافي من Rebase في المنبع يغطي قسم من صفحة Git-Rebase Man إلى حد كبير كل هذا.

لا يختلف الأمر حقًا عن التعافي من Rebase الخاص بك - أنت تحرك فرعًا واحدًا ، و Rebase جميع الفروع التي كانت في تاريخها في موقعها الجديد.

بدءًا من GIT 1.9/2.0 Q1 2014 ، لن تضطر إلى وضع علامة على أصل فرعك السابق قبل إعادة صياغته على فرع المنبع المعاد كتابته ، كما هو موضح في أرسطو Pagaltzisإجابه:
نرى الالتزام 07d406b و ارتكاب D96855F :

بعد العمل على topic فرع تم إنشاؤه مع git checkout -b topic origin/master, ، تاريخ فرع التتبع عن بُعد origin/master ربما تم إعادة بناء وإعادة بنائها ، مما يؤدي إلى تاريخ من هذا الشكل:

                   o---B1
                  /
  ---o---o---B2--o---o---o---B (origin/master)
          \
           B3
            \
             Derived (topic)

أين origin/master تستخدم للإشارة في الالتزامات B3, B2, B1 والآن يشير في B, ، وخاصتك topic بدأ الفرع فوقه عندما origin/master كان في B3.

يستخدم هذا الوضع مجموعة من origin/master لايجاد B3 كنقطة شوكة ، بحيث topic يمكن أن يتم تربيتها فوق التحديث origin/master بواسطة:

$ fork_point=$(git merge-base --fork-point origin/master topic)
$ git rebase --onto origin/master $fork_point topic

لهذا السبب git merge-base الأوامر له خيار جديد:

--fork-point::

ابحث عن النقطة التي يؤدي فيها الفرع (أو أي تاريخ يؤدي إلى <commit>) متشوق من فرع آخر (أو أي مرجع) <ref>.
هذا لا يبحث فقط عن الجد المشترك بين الاثنين ، ولكن يأخذ أيضا في الاعتبار ريبوج <ref> لمعرفة ما إذا كان التاريخ يؤدي إلى <commit> متشوق من تجسد سابق للفرع <ref>.


ال "git pull --rebase"يحسب الأمر نقطة الشوكة للفرع الذي يتم إعادة إدخاله باستخدام إدخالات lefg of the"base"فرع (عادةً فرع تتبع عن بُعد) ، كان عمل الفرع يعتمد على ، من أجل التعامل مع الحالة التي تم فيها إعادة بناء فرع" القاعدة "وإعادة بنائها.

على سبيل المثال ، إذا كان التاريخ يبدو وكأنه:

  • الطرف الحالي من "base"الفرع في B, ، لكن الجلب في وقت سابق لاحظ أن طرفه كان يستخدم B3 وثم B2 وثم B1قبل الوصول إلى الالتزام الحالي ، و
  • يعتمد الفرع الذي يجري تربيته فوق أحدث "قاعدة" على الالتزام B3,

يحاول أن يجد B3 عن طريق المرور من خلال إخراج ""git rev-list --reflog base" (بمعنى آخر B, B1, B2, B3) حتى يجد التزامًا يمثل سلف النصيحة الحالية "Derived (topic)".

داخليا لدينا get_merge_bases_many() يمكن أن يحسب هذا مع واحد.
نريد قاعدة دمج بين Derived ودمج وهمية من شأنه أن ينتج عنه دمج جميع النصائح التاريخية لـ "base (origin/master)".
عند وجود مثل هذا الالتزام ، يجب أن نحصل على نتيجة واحدة ، والتي تتطابق تمامًا مع أحد إدخالات القبيحة ""base".


ستضيف GIT 2.1 (Q3 2014) جعل هذه الميزة أكثر قوة لذلك: انظر ارتكاب 1E0DACD بواسطة جون حفظ (johnkeeping)

تعامل بشكل صحيح مع السيناريو حيث لدينا الطوبولوجيا التالية:

    C --- D --- E  <- dev
   /
  B  <- master@{1}
 /
o --- B' --- C* --- D*  <- master

أين:

  • B' هو نسخة ثابتة من B هذا ليس متطرفًا مع B;
  • C* و D* هي patch-pantical ل C و D على التوالي والصراع للنصوص إذا تم تطبيقه بالترتيب الخاطئ ؛
  • E يعتمد على النص D.

النتيجة الصحيحة ل git rebase master dev هل هذا B تم تحديده على أنه نقطة شوكة dev و master, ، لهذا السبب C, D, E هي الالتزامات التي يجب إعادة تشغيلها master; ؛ لكن C و D تصحيح مع C* و D* وهكذا يمكن إسقاطها ، بحيث تكون النتيجة النهائية هي:

o --- B' --- C* --- D* --- E  <- dev

إذا لم يتم تحديد نقطة الشوكة ، فعند اختيار B على فرع يحتوي B' ينتج عنه تعارض وإذا لم يتم تحديد الالتزامات المتطورة بشكل صحيح ثم الاختيار C على فرع يحتوي D (أو مكافئ D*) النتائج في الصراع.

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