Как сделать частичное слияние в git?

Этот вопрос вдохновлен следующим отличным сообщением: https://blogs.msdn.microsoft.com/oldnewthing/20180312-00/?p=98215 https://blogs.msdn.microsoft.com/oldnewthing/20180313-00/?p=98225 https://blogs.msdn.microsoft.com/oldnewthing/20180314-00/?p=98235

Этот пост объясняет, почему сбор вишни является злом и как его можно заменить частичным слиянием. Вот картинка:

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

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

Что делать то? Как слить только это изменение с мастером? Нет вишни, пожалуйста.

2 ответа

Решение

(Как отмечали несколько человек, в Git нет частичного слияния.)

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

Если вы заранее знаете, что некоторые изменения должны быть применены к нескольким веткам (и используете Git), вы можете вернуться к самой ранней фиксации, при которой изменение может быть сделано - которое, по нашему определению, "будет применено", будет до того, как другие ветви разветвляются из этого коммита, и создаст новую ветку с этой точки. Затем вы можете внести изменения и зафиксировать. Это производит patch ветвь (см. диаграмму, которую мистер Чен показывает в третьем посте, что вы скопировали в вопрос).

Затем вы можете объединить эту новую ветку со всеми другими ветками, как показано здесь (и там).

Но это подразумевает, что мы заранее знаем, что изменение также должно быть в мастере.

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

В посте не объясняется, что делать, если изменение первоначально было зарегистрировано в ветви функций, и только позже мы обнаруживаем, что оно также должно быть в [другой] ветви.

Нет идеального решения для этого, но есть достаточно хорошее. Это нарушает вашу жалобу, хотя:

Что делать то? Как объединить только это изменение с [другой веткой]? Нет вишни, пожалуйста.

То, как мы это делаем, заключается в том, чтобы идентифицировать этот предковый коммит - где бы он ни был - и сбор вишни. (Извините!) Cherry-pick создает один новый коммит, который находится исключительно в ветке патча. Затем мы объединяем ветвь патча в обе ветви, как если бы мы сделали правильную вещь в первый раз. Это производит следующее:

(apple)   (berry)
  M1---------M2     <-- master
 /          /
A----------P'     <-- patch
 \          \
  F1------P--F2     <-- feature
(apple)   (berry)

Обратите внимание, что слияние patch в feature не влияет на исходное дерево в коммите F2 на feature: исходное дерево в F2 соответствует этому в оригинальном патче P, Это верно, даже если есть коммиты на feature после P Например:

  M1---------M2     <-- master
 /          /
A----------P'     <-- patch
 \          \
  F1--P--Q---F2     <-- feature

При необходимости мы можем сделать слияние в feature с -s ours чтобы избежать "отмены" каких-либо изменений или получения какого-либо конфликта слияния. Смысл этого слияния в feature , чтобы заставить Git осознать тот факт, что общий предок master а также feature сейчас совершить P' , совершить P' должен существовать, даже если мы должны создать его только для этой цели. Самый простой способ создать это - использовать git cherry-pick,

Сбор вишни - это инструмент, а не решение. В сообщении г-на Чена говорится, что люди плохо используют инструмент. Это не значит, что сам инструмент плохой!

Другие вопросы по тегам