Git Cherry-pick против Merge Workflow
Предполагая, что я являюсь сопровождающим репозитория и хочу получить изменения от участника, существует несколько возможных рабочих процессов:
- я
cherry-pick
каждый коммит с пульта (по порядку). В этом случае git записывает коммит как не связанный с удаленной веткой. - я
merge
ветвь, извлекающая все изменения и добавляющая новую "конфликтную" фиксацию (при необходимости). - я
merge
каждый коммит из удаленной ветки индивидуально (снова по порядку), позволяя записывать конфликты для каждого коммита, а не группировать все вместе как один. - Для полноты можно сделать
rebase
(такой же какcherry-pick
вариант?), однако я понимаю, что это может вызвать путаницу для автора. Может быть, это исключает вариант 1.
В обоих случаях 2 и 3 git записывает историю ветвлений коммитов, в отличие от 1.
Какие плюсы и минусы между использованием cherry-pick
или же merge
методы описаны? Насколько я понимаю, метод 2 является нормой, но я чувствую, что разрешение большого коммита с помощью одного "конфликтного" слияния - не самое чистое решение.
3 ответа
И то и другое rebase
(а также cherry-pick
) а также merge
имеют свои преимущества и недостатки. Я спорю за merge
здесь, но стоит понять и то и другое. (Ищите здесь альтернативный, аргументированный ответ, перечисляющий случаи, когда rebase
является предпочтительным.)
merge
предпочтительнее cherry-pick
а также rebase
по нескольким причинам.
- Надежность Идентификатор SHA1 коммита идентифицирует его не только сам по себе, но и по отношению ко всем другим коммитам, которые ему предшествуют. Это дает вам гарантию того, что состояние хранилища в данном SHA1 одинаково для всех клонов. (Теоретически) нет никаких шансов, что кто-то сделал то же самое, что и похоже, но на самом деле испортил или похитил ваш репозиторий. Вы можете выбрать отдельные изменения, и они, вероятно, совпадают, но у вас нет гарантии. (В качестве незначительной вторичной проблемы новые выбранные вишневые коммиты займут дополнительное пространство, если кто-то еще выберет вишню в том же коммите снова, поскольку они оба будут присутствовать в истории, даже если ваши рабочие копии окажутся идентичными.)
- Простота использования. Люди склонны понимать
merge
Рабочий процесс довольно легко.rebase
как правило, считается более продвинутым. Лучше понять и то, и другое, но людям, которые не хотят быть экспертами в управлении версиями (что, по моему опыту, включает в себя многих коллег, которые чертовски хороши в том, что они делают, но не хотят тратить дополнительное время), легче время просто сливается.
Даже с интенсивным рабочим процессом rebase
а также cherry-pick
все еще полезны для особых случаев:
- Один недостаток
merge
это загроможденная история.rebase
предотвращает разброс длинных серий коммитов в вашей истории, как если бы вы периодически сливались с изменениями других. Это на самом деле его основная цель, как я его использую. То, что вы хотите быть очень осторожным, это никогда неrebase
код, который вы поделились с другими хранилищами. Как только коммитpush
Возможно, кто-то еще совершил это, и в лучшем случае перебазирование приведет к тому типу дублирования, который обсуждался выше. В худшем случае вы можете получить очень запутанный репозиторий и незначительные ошибки, на которые у вас уйдет много времени. cherry-pick
полезен для отбора небольшого подмножества изменений из ветки темы, которую вы в основном решили отменить, но поняли, что есть пара полезных частей.
Что касается предпочтения объединения множества изменений над одним: это намного проще. Выполнение слияний отдельных наборов изменений может быть очень утомительным, если у вас их много. Разрешение слияния в git (и в Mercurial, и в Bazaar) очень и очень хорошее. Вы не столкнетесь с серьезными проблемами при слиянии даже длинных веток большую часть времени. Обычно я объединяю все сразу, и только если я получаю большое количество конфликтов, я делаю резервную копию и заново запускаю фрагмент слияния. Даже тогда я делаю это большими кусками. В качестве очень реального примера у меня был коллега, у которого были изменения за 3 месяца для слияния, и я получил около 9000 конфликтов в 250000 строк кода. Чтобы исправить это, мы выполняем слияние за месяц: конфликты не накапливаются линейно, а частичное создание приводит к гораздо меньшему, чем 9000 конфликтам. Это было все еще много работы, но не столько, сколько попытка сделать это по одному коммиту за раз.
По моему мнению, сбор вишни должен быть зарезервирован для редких ситуаций, когда это необходимо, например, если вы сделали какое-то исправление непосредственно в ветке 'master' (ствол, основная ветка разработки), а затем поняли, что его следует применять также к 'maint ". Вы должны основывать рабочий процесс либо на слиянии, либо на rebase (или "git pull --rebase").
Пожалуйста, помните, что выбранный или перебазированный коммит отличается от Git (имеет другой идентификатор SHA-1), чем оригинал, поэтому он отличается от коммита в удаленном репозитории. (Обычно Rebase может справиться с этим, так как он проверяет идентификатор патча, т.е. изменения, а не идентификатор фиксации).
Также в git вы можете объединить много веток одновременно: так называемое объединение осьминога. Обратите внимание, что слияние осьминога должно быть успешным без конфликтов. Тем не менее это может быть полезно.
НТН.
Rebase и Cherry-pick - единственный способ сохранить чистую историю коммитов. Избегайте использования слияния и избегайте возникновения конфликта слияния. Если вы используете gerrit, установите один проект на Merge, если необходимо, и один проект в режиме cherry-pick и попробуйте сами.