Перебазирование комита Git Merge - PullRequest
149 голосов
/ 24 января 2011

Возьмите следующий случай:

У меня есть работа в ветке тем, и теперь я готов вернуться к мастеру:

* 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 ]

105 голосов
/ 24 января 2011

Здесь есть два варианта.

Один из них - интерактивная перебазировка и редактирование коммита слияния, повторное слияние вручную и продолжение перебазировки.

Другой вариант - использовать параметр -p на git rebase, который описан в руководстве следующим образом: «Вместо игнорирования слияний попробуйте воссоздать их».Этот вопрос дополнительно объясняет это: Что именно делает git «rebase --preserve-merges» (и почему?)

21 голосов
/ 14 декабря 2017

Хорошо, это старый вопрос, и он уже принял ответ на @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
    
3 голосов
/ 14 декабря 2017

Учитывая, что я просто потерял день, пытаясь выяснить это, и на самом деле нашел решение с помощью коллеги, я подумал, что мне следует вмешаться.

У нас большая база кода, и мы должныиметь дело с 2 ветками, которые сильно изменяются одновременно.Существует основная ветвь и вторичная ветвь, если вы, что.

Пока я объединяю вторичную ветвь с основной ветвью, работа продолжается в основной ветке, и к тому времени, как я это сделаю, я не могу нажатьмои изменения, потому что они несовместимы.

Поэтому мне нужно «перебазировать» мое «слияние».

Вот как мы наконец сделали это:

1) запишитеША.Пример: 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

Вуаля!

1 голос
/ 24 января 2011

Похоже, что вы хотите сделать, это удалить ваше первое слияние. Вы можете выполнить следующую процедуру:

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

Это даст вам то, что вы хотите.

0 голосов
/ 30 ноября 2017
  • Из вашего коммита слияния
  • Вишни - выбери новое изменение, которое должно быть легким
  • Скопируйте ваши вещи
  • повторить слияние и разрешить конфликты, просто скопировав файлы из локальной копии;)
...