Перебазирование фиксации слияния Git
возьмем следующий случай:
у меня есть работа в ветке темы, и теперь я готов объединиться обратно в master:
* eb3b733 3 [master] [origin/master]
| * b62cae6 2 [topic]
|/
* 38abeae 1
Я выполняю слияние с master, разрешаю конфликты и теперь у меня есть:
* 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 ответов:
есть два варианта.
один из них-сделать интерактивную перебазировку и отредактировать фиксацию слияния, повторить слияние вручную и продолжить перебазирование.
другое-используйте на
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
учитывая, что я только что потерял день, пытаясь понять это, и на самом деле нашел решение с помощью коллеги, я подумал, что должен вмешаться.
у нас есть большая база кода, и нам приходится иметь дело с 2 ветвями, которые сильно изменяются одновременно. Существует основная ветвь и вторичная ветвь, если вы что.
в то время как я объединяю вторичную ветвь в основную ветвь, работа продолжается в основной ветви, и к тому времени, когда я закончу, я не могу нажать мои изменения, потому что они несовместимы.
поэтому мне нужно " перебазировать "мое"слияние".
вот как мы наконец это сделали:
1) Обратите внимание на SHA. бывший.: c4a924d458ea0629c0d694f1b9e9576a3ecf506b
git log -12) создайте правильную историю, но это нарушит слияние.
git rebase -s ours --preserve-merges origin/master3) Обратите внимание на SHA. бывший.: 29dd8101d78
git log -14) Теперь сбросьте туда, где вы были раньше
git reset c4a924d458ea0629c0d694f1b9e9576a3ecf506b --hard5) Теперь объединить текущий мастер в вашу рабочую ветку
git merge origin/master git mergetool git commit -m"correct files6) Теперь, когда у вас есть правильные файлы, но неправильная история, получить право история на вершине вашего изменения с :
git reset 29dd8101d78 --soft7) и затем --изменить результаты в исходном слиянии commit
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Это даст вам то, что вы хотите.