Перебазирование комита Git Merge
Возьмите следующий случай:
У меня есть работа в ветке тем, и теперь я готов вернуться к мастеру:
* eb3b733 3 [master] [origin/master]
| * b62cae6 2 [topic]
|/
* 38abeae 1
Я выполняю слияние с мастером, разрешаю конфликты и теперь у меня есть:
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | eb3b733 3 [origin/master]
|/
* 38abeae 1
Теперь слияние заняло у меня некоторое время, поэтому я сделал еще одну выборку и заметил, что в удаленной главной ветке появились новые изменения:
* 8101fe3 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
| | * e7affba 4 [origin/master]
| |/
|/|
* | eb3b733 3
|/
* 38abeae 1
Если я пытаюсь "git rebase origin / master" от master, я вынужден снова разрешать все конфликты и также теряю коммит слияния:
* d4de423 2 [master]
* e7affba 4 [origin/master]
* eb3b733 3
| * b62cae6 2 [topic]
|/
* 38abeae 1
Есть ли чистый способ перебазировать коммит слияния, чтобы я получил историю, подобную той, что я показываю ниже?
* 51984c7 Merge branch 'topic' [master]
|\
| * b62cae6 2 [topic]
* | e7affba 4 [origin/master]
* | eb3b733 3
|/
* 38abeae 1
5 ответов
Здесь есть два варианта.
Одним из них является интерактивная перебазировка и редактирование коммита слияния, повторное слияние вручную и продолжение перебазирования.
Другой заключается в использовании -p
вариант на git rebase
, который описывается в руководстве следующим образом: "Вместо игнорирования слияний попробуйте воссоздать их". Этот вопрос дополнительно объясняет это: что именно делает git "rebase --preserve-merges" (и почему?)
Хорошо, это старый вопрос, и он уже принял ответ @siride
, но этого ответа было недостаточно в моем случае, так как --preserve-merges
заставляет вас разрешить все конфликты во второй раз. Мое решение основано на идее @Tobi B
но с точными пошаговыми командами
Итак, мы начнем с такого состояния на основе примера в вопросе:
* 8101fe3 Merge branch 'topic' [HEAD -> master]
|\
| * b62cae6 2 [topic]
| |
| | * f5a7ca8 5 [origin/master]
| | * e7affba 4
| |/
|/|
* | eb3b733 3
|/
* 38abeae 1
Обратите внимание, что у нас есть 2 коммитов впереди, мастер, поэтому вишневый пик не сработает.
Прежде всего, давайте создадим правильную историю, которую мы хотим:
git checkout -b correct-history # create new branch to save master for future git rebase -s ours -p origin/master
-p
средства--preserve-merges
мы используем его, чтобы сохранить коммит слияния в истории-s ours
средства--strategy=ours
мы используем его для игнорирования всех конфликтов слияния, так как нам не важно, какое содержимое будет в этом коммите слияния, нам нужна только хорошая история.История будет выглядеть так (без учета мастера):
* 51984c7 Merge branch 'topic' [HEAD -> correct-history] |\ | * b62cae6 2 [topic] * | f5a7ca8 5 [origin/master] * | e7affba 4 * | eb3b733 3 |/ * 38abeae 1
Давайте получим правильный индекс сейчас.
git checkout master # return to our master branch git merge origin/master # merge origin/master on top of our master
Мы можем получить некоторые дополнительные конфликты слияния здесь, но это будет только конфликты из файлов, измененных между
8101fe3
а такжеf5a7ca8
, но не включает уже разрешенные конфликты изtopic
История будет выглядеть так (без учета правильной истории):
* 94f1484 Merge branch 'origin/master' [HEAD -> master] |\ * | f5a7ca8 5 [origin/master] * | e7affba 4 | * 8101fe3 Merge branch 'topic' | |\ | | * b62cae6 2 [topic] |/ / * / eb3b733 3 |/ * 38abeae 1
Последний этап - объединить нашу ветку с правильной историей и ветку с правильным индексом.
git reset --soft correct-history git commit --amend
Мы используем
reset --soft
чтобы сбросить нашу ветку (и историю) в правильную историю, но оставить индекс и рабочее дерево как есть. Тогда мы используемcommit --amend
переписать наш коммит слияния, который раньше имел неправильный индекс, с нашим хорошим индексом от master.В конце у нас будет такое состояние (обратите внимание на другой идентификатор top commit):
* 13e6d03 Merge branch 'topic' [HEAD -> master] |\ | * b62cae6 2 [topic] * | f5a7ca8 5 [origin/master] * | e7affba 4 * | eb3b733 3 |/ * 38abeae 1
Учитывая, что я просто потерял день, пытаясь это выяснить, и на самом деле нашел решение с помощью коллеги, я подумал, что должен вмешаться.
У нас большая база кода, и нам приходится иметь дело с двумя ветвями, которые сильно изменяются одновременно. Существует основной филиал и дополнительный филиал, если вы, который.
Пока я объединяю вторичную ветвь с основной ветвью, работа в основной ветке продолжается, и к тому времени, когда я это сделаю, я не могу сдвинуть свои изменения, потому что они несовместимы.
Поэтому мне нужно "перебазировать" мое "слияние".
Вот как мы наконец сделали это:
1) запишите SHA. Пример: c4a924d458ea0629c0d694f1b9e9576a3ecf506b
git log -1
2) Создайте правильную историю, но это нарушит слияние.
git rebase -s ours --preserve-merges origin/master
3) запишите SHA. пример: 29dd8101d78
git log -1
4) Теперь вернитесь туда, где вы были раньше
git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard
5) Теперь объедините текущий мастер в вашу рабочую ветку
git merge origin/master
git mergetool
git commit -m"correct files
6) Теперь, когда у вас есть правильные файлы, но неправильная история, добавьте правильную историю поверх ваших изменений с помощью:
git reset 29dd8101d78 --soft
7) А затем - изменить результаты в исходном коммите слияния
git commit --amend
Вуаля!
Похоже, что вы хотите сделать, это удалить ваше первое слияние. Вы можете выполнить следующую процедуру:
git checkout master # Let's make sure we are on master branch
git reset --hard master~ # Let's get back to master before the merge
git pull # or git merge remote/master
git merge topic
Это даст вам то, что вы хотите.
- От вашего слияния совершить
- Cherry-выбрать новое изменение, которое должно быть легко
- копируй свои вещи
- повторить слияние и разрешить конфликты, просто скопировав файлы из локальной копии;)