Git Cherry-pick против Merge Workflow


302

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

  1. Я cherry-pickкаждый фиксирую с пульта (по порядку). В этом случае git записывает коммит как не связанный с удаленной веткой.
  2. Я mergeветвился, вытягивая все изменения и добавляя новый «конфликтный» коммит (при необходимости).
  3. Я mergeкаждая фиксация с удаленным филиала в отдельности (опять - таки в порядке), что позволяет конфликты должны быть записаны для каждого коммита, а не сгруппированы вместе как единое целое.
  4. Для полноты вы можете сделать rebase(то же самое, что cherry-pickопция?), Однако, насколько я понимаю, это может привести к путанице для участника. Может быть, это исключает вариант 1.

В обоих случаях 2 и 3 git записывает историю ветвлений коммитов, в отличие от 1.

Каковы плюсы и минусы между использованием одного cherry-pickили mergeописанных методов? Насколько я понимаю, метод 2 является нормой, но я чувствую, что разрешение большого коммита с помощью одного «конфликтного» слияния - не самое чистое решение.

Ответы:


297

Оба rebasecherry-pick) и mergeимеют свои преимущества и недостатки. Я спорю mergeздесь, но стоит понять и то и другое. (Ищите здесь альтернативный, аргументированный ответ, перечисляющий случаи, когда rebaseэто предпочтительнее.)

mergeпредпочтительнее cherry-pickи rebaseпо нескольким причинам.

  1. Надёжность . Идентификатор SHA1 коммита идентифицирует его не только сам по себе, но и по отношению ко всем другим коммитам, которые ему предшествуют. Это дает вам гарантию того, что состояние хранилища в данном SHA1 одинаково для всех клонов. (Теоретически) нет никаких шансов, что кто-то сделал то же самое, что и похоже, но на самом деле испортил или похитил ваш репозиторий. Вы можете выбрать отдельные изменения, и они, вероятно, совпадают, но у вас нет гарантии. (В качестве незначительной вторичной проблемы новые выбранные вишневые коммиты займут дополнительное пространство, если кто-то еще выберет вишню в том же коммите снова, поскольку они оба будут присутствовать в истории, даже если ваши рабочие копии окажутся идентичными.)
  2. Простота использования . Люди склонны понимать mergeрабочий процесс довольно легко. rebaseкак правило, считается более продвинутым. Лучше понять и то, и другое, но людям, которые не хотят быть экспертами в области контроля версий (что, по моему опыту, включает в себя многих коллег, которые чертовски хороши в том, что они делают, но не хотят тратить дополнительное время), легче время просто сливается.

Даже с интенсивным рабочим процессом слияния rebaseи cherry-pickвсе еще полезны для особых случаев:

  1. Одним из недостатков mergeявляется загроможденная история. rebaseпредотвращает рассеяние длинных серий коммитов в вашей истории, как если бы вы периодически сливались с изменениями других. Это на самом деле его основная цель, как я его использую. Что вы хотите быть очень осторожным, так это никогда не rebaseкодировать то, что вы делитесь с другими репозиториями. После того, как зафиксирован коммит, pushкто-то другой мог совершить его поверх него, и перебазирование в лучшем случае вызовет дублирование, обсуждавшееся выше. В худшем случае вы можете получить очень запутанный репозиторий и незначительные ошибки, на которые у вас уйдет много времени.
  2. cherry-pick полезен для отбора небольшого подмножества изменений из ветки тем, которые вы в основном решили отменить, но поняли, что есть пара полезных частей.

Что касается предпочтения слияния множества изменений над одним: это намного проще. Объединение отдельных наборов изменений может быть очень утомительным, если у вас их много. Разрешение слияния в git (и в Mercurial, и в Bazaar) очень и очень хорошее. Вы не столкнетесь с серьезными проблемами при слиянии даже длинных веток большую часть времени. Обычно я объединяю все сразу, и только если я получаю большое количество конфликтов, я делаю резервную копию и заново запускаю фрагмент слияния. Даже тогда я делаю это большими кусками. В качестве очень реального примера у меня был коллега, у которого были изменения за 3 месяца для слияния, и я получил около 9000 конфликтов в 250000 строк кода. Что мы сделали, чтобы это исправить, так это сделать слияние за месяц: конфликты не накапливаются линейно, а выполнение этого по частям приводит к далекоменее 9000 конфликтов. Это было все еще много работы, но не так много, как попытка сделать это по одному коммиту за раз.


1
На самом деле, теоретически, есть вероятность, что Мэллори может испортить ваш репозиторий, создав коммиты с тем же SHA1, но с другим содержимым, что, вероятно, никогда не случится на практике. :)
Бомба

1
Ха :) Я имел в виду, что "в теории шансы настолько малы, что вы не можете полагаться на то, что этого не произойдет", но вы правы в том, что в нем говорится о перевороте.
кварк

Что вы думаете о «слиянии - сквош»?
cmcginty

@Bombe Если Мэллори хочет добиться успеха, ей придется специально создать оригинальный коммит и второй коммит с тем же SHA1. Таким образом, другой вопрос может быть: каковы шансы появления двух (несколько) поддельных коммитов, а вы не замечаете? ;)
Жоао Портела

64
9000 конфликтов? Я бросил бы свою работу и стал бы пчеловодом.
Себастьян Паттен

95

По моему мнению, сбор вишни должен быть зарезервирован для редких ситуаций, когда это необходимо, например, если вы сделали какое-то исправление непосредственно в ветке 'master' (ствол, основная ветка разработки), а затем поняли, что его следует применять также к 'maint ». Вы должны основывать рабочий процесс либо на слиянии, либо на rebase (или "git pull --rebase").

Пожалуйста, помните, что выбранный или перебазированный коммит отличается с точки зрения Git (имеет другой идентификатор SHA-1), чем оригинал, поэтому он отличается от коммита в удаленном репозитории. (Обычно Rebase может справиться с этим, так как он проверяет идентификатор патча, т.е. изменения, а не идентификатор фиксации).

Также в git вы можете объединить много веток одновременно: так называемое объединение осьминога . Обратите внимание, что слияние осьминога должно быть успешным без конфликтов. Тем не менее это может быть полезно.

НТН.


19
+1 за то, что rebase / cherry-picking фактически «копируют» коммиты и поэтому теряют связь с оригинальным коммитом.
Studgeek

1
Таким образом мы используем cherry-pick исключительно для перемещения коммитов для исправления ошибок (возможно, ОЧЕНЬ МАЛЕНЬКИХ функций) в существующую ветку релиза для подготовки патча. Функции, охватывающие несколько коммитов, обычно требуют перехода в ветку релиза, основанную на master.
Фокстрот

3
@foxxtrot: Другое решение состоит в том, чтобы создать отдельную ветку для исправления, основанную на самом старом коммите, который демонстрирует эту ошибку, и объединить его с «maint» и «master» ... хотя в этом случае вам нужно знать, что это исправление относится к обеим веткам.
Якуб Наребски

4
@Jakub Две команды, которые необходимы для создания и объединения ветки git blameс исправлениями ошибок : найти коммит, который привел к ошибке, и git branch --containsопределить, где объединить ветку. Более подробно описано в этом посте
gcbenison

-10

Rebase и Cherry-pick - единственный способ сохранить чистую историю коммитов. Избегайте использования слияния и избегайте возникновения конфликта слияния. Если вы используете gerrit, установите один проект на Merge, если необходимо, и один проект в режиме cherry-pick и попробуйте сами.


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

1
Тот факт, что ваша история будет выглядеть прямо, не означает, что ее будет легче понять.
nicolimo86

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

Этот парень прямо здесь заслуживает медали. Он знает, что будет продолжать голосовать за него, но это правильный ответ. Престижность.
PW Kad

Извините, я не видел эти комментарии до сих пор, пожалуйста, попробуйте его в вашей тестовой среде, прежде чем завершить и делать то, что работает для вас! У меня около 600 разработчиков, участвующих в нескольких ветвях продуктов, мне все равно, что делают разработчики в локальной рабочей области, когда изменение передается для интеграции, оно должно быть в состоянии выбрать вишню для ветки разработки или иногда выпуска или ветки с исправлением ошибок. К вашему сведению ... Я использую Геррит.
Нагарадж Магадум
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.