Git Cherry-pick vs Merge Workflow

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

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

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

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

3 ответов


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

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

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

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

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

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


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

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

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

HTH.


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