Поєднайте перші два комітети сховища Git?


197

Припустимо, у вас є історія, що містить три комірки A, B і C :

A-B-C

Я хотів би об'єднати два комірки A і B в один прихильний AB :

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

Є спосіб чи це просто неможливо?



Відповіді:


169

Використання git rebase -i --root з версії Git 1.7.12 .

В інтерактивному файлі бази даних змініть другий рядок фіксування B на сквош і залиште інші рядки на вибір :

pick f4202da A
squash bea708e B
pick a8c6abc C

Це об'єднає два комітети A і B на один AB .

Знайдено у цій відповіді .


126

Ви пробували:

git rebase -i A

Почати так можна, якщо ви продовжите, editа не squash:

edit e97a17b B
pick asd314f C

потім біжи

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

Зроблено.


4
Якщо ви робите це, щоб непомітно виправити суть github, вам доведеться додати -m "початковий" до комітів. ;-)
Бруно Броноський

1
git rebase --abortпочати все спочатку і зробити це правильно (не скосивши першої комісії в редакторі)
ома

66

A був початковим зобов’язанням, але тепер ви хочете B бути початковою. git commits - це цілі дерева, не відрізняються, навіть якщо їх зазвичай описують і розглядають через розріз, який вони вводять.

Цей рецепт працює навіть у тому випадку, якщо між 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

1
це запускає масову інтерактивну базу даних, коли я роблюgit rebase --onto tmp <sha1_for_B>
Олексій

З огляду на те, що у мене було абсолютно нове репо з лише двома комісіями (що я хотів згорнути в одну), це для мене прекрасно працювало. Дякую @CB Bailey
RominRonin

10

У випадку інтерактивної бази даних, ви повинні зробити це перед A, щоб список був:

pick A
pick B
pick C

ставати:

pick A
squash B
pick C

Якщо A є початковим комітом, перед тим, як А. Git подумає про відмінності, ви повинні мати інший початковий комітет, він буде працювати на різниці між (A і B) і (B і C). Отже, сквош не працює у вашому прикладі.


9

У випадку, якщо у вас є сотні чи тисячі комісій , використовуючи відповідь kostmo від

git rebase -i --root

може бути непрактичним і повільним, лише через велику кількість комісій, які сценарій перезавантаження повинен обробити двічі повторної бази даних , один раз для створення списку інтерактивних редакторів ребаз (де ви вибираєте, яку дію робити для кожної комісії) та одного разу фактично виконати повторне застосування комітетів.

Ось альтернативне рішення, яке дозволить уникнути витрат часу на генерування списку редакторів інтерактивних баз даних, в першу чергу не використовуючи інтерактивну ребазу . Таким чином це схоже на рішення Чарльза Бейлі . Ви просто створите гілку-сироту з другого комітету, а потім перезавантажте всі нащадки, що виконуються поверх нього:

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

Документація


1

У спорідненому питанні мені вдалося придумати інший підхід до необхідності сквашування проти першого вчинку, який, мабуть, зробити його другим.

Якщо вас цікавить: git: як вставити комітку як першу, перемістивши всі інші?


Чи було б краще, якби відповідь була повторена і тут? Я не впевнений.

0

Команда Git для загону: git rebase -i HEAD ~ [кількість комірок]

Скажімо, у вас є історія фіксації git нижче:


вибрати 5152061 подвиг: Додана підтримка для збереження зображення. (A)
вибрати 39c5a04 Виправлення: виправлення помилок. (B)
виберіть виправлення 839c6b3: конфлікт вирішено. (C)

Тепер ви хочете скосити A і B на AB, виконайте нижче кроки:


вибрати 5152061 подвиг: Додана підтримка для збереження зображення. (A)
s 39c5a04 Виправлення: виправлення помилок. (B)
виберіть виправлення 839c6b3: конфлікт вирішено. (C)

Примітка: для фіксації сквош можемо використовувати сквош або с. Кінцевим результатом буде:
вибрати 5152061 подвиг: Додана підтримка для збереження зображення. (AB)
вибрати виправити 839c6b3: конфлікт вирішено. (C)


-1

Ви повинні виконати трохи магії командного рядка.

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

Це повинно залишити вас філією, у якій AB і C є комітетами.


Оскільки старі та нові початкові зобов’язання не мають спільного предка, у вас можуть виникнути непотрібні конфлікти, оскільки git намагається застосувати всю історію майстра до а, хоча вони мають спільне дерево. Використовуючи опцію --onto для git rebase, ви можете сказати git правильне місце для початку застосування.
CB Bailey
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.