سؤال

لنفترض أن لديك سجلًا يحتوي على الالتزامات الثلاثة أ، ب و ج:

A-B-C

أود الجمع بين الالتزامين أ و ب لارتكاب واحد أ.ب:

AB-C

حاولت

git rebase -i A

الذي يفتح المحرر الخاص بي بالمحتويات التالية:

pick e97a17b B
pick asd314f C

أغير هذا إلى

squash e97a17b B
pick asd314f C

ثم يقول Git 1.6.0.4:

Cannot 'squash' without a previous commit

هل هناك طريقة أم أن هذا مستحيل؟

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

المحلول

استخدم git rebase -i --root اعتبارا من بوابة النسخة 1.7.12 .

في الملف rebase التفاعلي، وتغيير السطر الثاني من ارتكاب <م> B إلى <م> الاسكواش وترك خطوط أخرى في <م> اختيار :

pick f4202da A
squash bea708e B
pick a8c6abc C

وهذا سوف تجمع بين اثنين من يرتكب <م> A و <م> B إلى واحدة ارتكاب <م> AB .

وجدت في هذه الإجابة .

نصائح أخرى

ولقد حاولت:

git rebase -i A

ومن الممكن أن تبدأ من هذا القبيل إذا كنت لا تزال مع edit بدلا من squash:

edit e97a17b B
pick asd314f C

ثم تشغيل

git reset --soft HEAD^
git commit --amend
git rebase --continue

تم.

وكان A الأولي ارتكابها، ولكن الآن تريد B لتكون الأولي يرتكبها. يرتكب بوابة أشجار كلها، وليس بيانات الاختلاف حتى لو تم وصفها أنها عادة وينظر من حيث فرق أن تستحدث.

وهذه الوصفة تعمل حتى لو كانت هناك يرتكب متعددة بين A و B، و B و C.

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp

في حالة rebase التفاعلية، عليك أن تفعل ذلك قبل A بحيث القائمة ستكون:

pick A
pick B
pick C

ولتصبح:

pick A
squash B
pick C

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

في حالة وجود مئات أو آلاف الالتزامات، استخدم إجابة كوستمو ل

git rebase -i --root

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

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

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

توثيق

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

إذا كنت مهتما: <لأ href = "https://stackoverflow.com/questions/645450/git-how-to-insert-a-commit-as-the-first-shifting-all-the- الآخرين "> بوابة: كيفية إدراج ارتكاب كأول، يتحول كل الآخرين

الأمر جيت للفرقة: بوابة rebase رأس -i ~ [عدد يرتكب]

ودعونا نقول لديك أقل من بوابة ارتكاب التاريخ:

و
اختيار 5152061 الفذ: واضاف لدعم توفير صورة. (أ)
اختيار 39c5a04 فيكس: علة الحلول. (ب)
اختيار 839c6b3 الإصلاح: حل الصراع. (C)

والآن تريد الاسكواش A و B لAB، نفذ الخطوات أدناه:

و
اختيار 5152061 الفذ: واضاف لدعم توفير صورة. (أ)
الصورة 39c5a04 فيكس: علة الحلول. (ب)
اختيار 839c6b3 الإصلاح: حل الصراع. (C)

ملحوظة: لسحق ارتكاب يمكننا استخدام الاسكواش أو الصورة. سوف تكون النتيجة النهائية:
اختيار 5152061 الفذ: واضاف لدعم توفير صورة. (AB)
اختيار 839c6b3 الإصلاح: حل الصراع. (C)

لديك لأداء قليلا من السحر سطر الأوامر.

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

وهذا يجب أن أترككم مع فرع لها AB و C كما تلزم.

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