Как воспроизвести историю, используя rebase вместо слияния, чтобы очистить пулл-запрос? - PullRequest
0 голосов
/ 20 ноября 2019

Коллега - новичок в Git. Он работал над какой-то веткой функций в течение довольно долгого времени и сейчас создал PR (AzOv DevOps, если это имеет значение).

К сожалению, он не знал о git rebase и поэтому все время использовал git pull origin master для синхронизации, что привело к довольно большим коммитам слияния. (в его ветви функций есть 20 «настоящих» коммитов и 9 коммитов слияния)

Теперь это было бы хорошо, но в результате в разных видах PR не только отображаются его изменения, но и вседругие изменения, которые были применены к мастеру за это время. В принципе, сейчас невозможно сделать правильный анализ кода, потому что его изменения неотличимы от всех других изменений.

Теперь я планирую каким-то образом воспроизвести все его изменения, но всякий раз, когда он произвел слияние, я буду делатьперебазировать вместо. Всякий раз, когда возникает конфликт во время перебазирования, смешивание изменений соответствующего коммита слияния должно полностью разрешить это (теоретически). Большинство слияний довольно сложны, поэтому нельзя вручную их переделывать, так как эта работа уже выполнена.

Какой лучший способ добиться этого?

  1. Я пытался git rebase master, но это не включает коммиты слияния, поэтому их придется делать вручную.

  2. Я также пытался git rebase --preserve-merges master, но по какой-то причинеэто будет делать перебазирование только до последнего коммита слияния (см. ниже).

Если нет лучшего варианта, мне придется сделать 20 + 9 вишневых пиков ...


Говоря в картинках, ситуация такова:

A---B---C- ... --D---E---F         master
 \   \      ...   \         
  G---m---H- ... --m---I---J       feature

И я хочу это:

A---B---C- ... --D---E---F                                   master
                          \                          
                           G'--m'--H' ... --m'--I'--J'       feature

Вариант 1. только даст мне это,но я хочу получить m s (не обязательно как коммиты, но я хочу, чтобы эти разрешенные конфликты были как-то):

A---B---C- ... --D---E---F                                   master
                          \                          
                           G'------H' ... ------I'--J'       feature

Вариант 2. только даст мне это, не сильно помогая:

A---B---C- ... --D---E---F                 master
 \   \      ...   \       \         
  G---m---H- ... --m-------m'--I'--J'      feature

Ответы [ 2 ]

2 голосов
/ 20 ноября 2019

Ребаз не может этого сделать. Он либо полностью сбрасывает слияния, либо повторно выполняет слияния . Если он повторно выполняет слияния, полученные коммиты слияния являются фактическими коммитами слияния. В вашем случае вы хотите получить эквивалент вишни с -m. (Я думаю, что вы хотите -m 1, но убедитесь, особенно перед использованием ниже.)

Если нет лучшего варианта, мне придется сделать 20 + 9 черриков ...

Это путь. Используйте git rev-list или аналогичный, чтобы перечислить все коммиты, которые будут скопированы. Запишите, какие из них являются слияниями. Затем напишите небольшой скрипт-let:

git cherry-pick <hash-of-G>
git cherry-pick -m 1 <hash-of-merge#1>    # or maybe -m 2?
git cherry-pick <hash-of-H>

и так далее. Выполняйте каждую команду по одному, чтобы знать, где вы находитесь, если и когда произойдет сбой, или если вы достаточно уверены в обработке ошибок, запустите ее как сценарий с установленным -e, чтобы сбой вишневого пика остановилОстальная часть комплектации.

1 голос
/ 21 ноября 2019

Я нашел решение, которое работало довольно гладко:

  1. Получить себя в том же состоянии, в котором он находился, когда начинал работу над функцией

    git checkout -b replay_feature <hash-of-A>  
    
  2. Повторяйте в точности то, что он делал, пока он не произвел слияние:

    git cherry-pick <hash-of-G>       # redo his non-merge commit(s)
    
  3. Теперь он сделал git merge master, поэтому я вместо этого git rebase master:

    git rebase <hash-of-B>            # back then, B was HEAD of master
    
  4. Сейчас я нахожусь в процессе перебазирования, сталкиваюсь с точно такими же конфликтами, с которыми он столкнулся и которые он разрешил с помощью m. Итак, чтобы разрешить его точно так же, как он, я просто проверяю все конфликтующие файлы из его коммита слияния.

    git checkout <hash-of-merge> -- file-in-conflict.cpp    # do this for all conflicts 
    # make sure everything compiles
    git add .
    git rebase --continue                                  
    
  5. повторяйте шаг 4. до перезагрузкисделано

Повторяйте шаги 2–5 до тех пор, пока вся его работа не будет воспроизведена, заменяя все слияния перебазами и применяя его разрешения конфликтов. В конце сравните ветки replay_feature и feature. Если все прошло нормально, все файлы должны быть идентичны.

git diff replay_feature feature    # should not show anything
...