Перебазирование фиксации слияния 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 -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) и затем --изменить результаты в исходном слиянии 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
Это даст вам то, что вы хотите.