Перебазирование комита 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 коммитов впереди, мастер, поэтому вишневый пик не сработает.

  1. Прежде всего, давайте создадим правильную историю, которую мы хотим:

    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
    
  2. Давайте получим правильный индекс сейчас.

    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
    
  3. Последний этап - объединить нашу ветку с правильной историей и ветку с правильным индексом.

    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-выбрать новое изменение, которое должно быть легко
  • копируй свои вещи
  • повторить слияние и разрешить конфликты, просто скопировав файлы из локальной копии;)
Другие вопросы по тегам