Перебазирование фиксации слияния 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 133

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

  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
    

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

у нас есть большая база кода, и нам приходится иметь дело с 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

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

  • из вашего слияния commit
  • Cherry-выберите новое изменение, которое должно быть легко
  • копировать ваши вещи
  • повторите слияние и разрешите конфликты, просто скопировав файлы из локальной копии ;)