Как сделать частичное слияние в 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
,
Сбор вишни - это инструмент, а не решение. В сообщении г-на Чена говорится, что люди плохо используют инструмент. Это не значит, что сам инструмент плохой!
Отличный пост из трех частей теперь находится по адресу