Что означает «выбор вишни» с помощью Git?

2340

Недавно меня попросили cherry-pickсовершить коммит.

Так что же означает выбор вишни в git? Как ты делаешь это?

Рахул
источник
13
Вместо слияния с вишневым сбором повторная фиксация от ветви к целевой ветви (например, master) проще.
Левент Дивилиоглу

Ответы:

2859

Выбор вишни в Git означает выбрать коммит из одной ветви и применить его к другой.

Это контрастирует с другими способами, такими как mergeи rebaseкоторые обычно применяют много коммитов к другой ветви.

  1. Убедитесь, что вы находитесь в той ветке, к которой хотите применить коммит.

    git checkout master
    
  2. Выполните следующее:

    git cherry-pick <commit-hash>
    

NB:

  1. Если вы выбираете вишню из публичной ветки, вы должны рассмотреть возможность использования

    git cherry-pick -x <commit-hash>
    

    Это создаст стандартизированное сообщение о коммите. Таким образом, вы (и ваши коллеги) по-прежнему можете отслеживать происхождение фиксации и избежать конфликтов слияния в будущем.

  2. Если у вас есть примечания, прикрепленные к коммиту, они не следуют за вишней. Чтобы их перенести, вы должны использовать:

    git notes copy <from> <to>
    

Дополнительные ссылки:

Филип Фурье
источник
247
Если вы выбираете вишню из публичной ветки, вам стоит подумать об использовании git cherry-pick -x <commit-hash>. Это создаст стандартизированное сообщение о коммите. Таким образом, вы (и ваши коллеги) по-прежнему можете отслеживать происхождение фиксации и избежать конфликтов слияния в будущем.
MBober
2
Сбор вишни действительно необходим? Разве смешанный сброс или мягкий сброс не сделают подобную работу?
Нав
10
Обратите внимание, что если у вас есть примечания, прикрепленные к коммиту, они не следуют за вишней. Вы должны использовать, git notes copy <from> <to>чтобы привести их также.
Цитрак
5
git push - это последний шаг для внесения изменений в мастер
чувствую себя хорошо и программирую
58
FYI: коммит семантический содержит все файлы рабочего дерева этого момента (и совершать хэш из предыдущего коммита), так что вы не подаете в целом совершить другое обязательство, но изменения фиксации сделали на предыдущей фиксации "cherry-pick commit applies the changes introduced by the named commit on the current branch"Большинства PPL склонны думать о коммите как об изменениях (как svn был iirc), но это не так, каждый коммит ссылается на полное рабочее дерево. Хотя в этом случае это не имеет значения, оно может помочь понять, почему git работает так, как работает.
Эмиль Врейдагс
315

Эта цитата взята из; Контроль версий с помощью Git (Действительно отличная книга, я рекомендую вам купить ее, если вы заинтересованы в git)

Изменить: Поскольку этот ответ все еще производит впечатление, я хотел бы добавить очень хороший в действии видеоурок об этом:

Youtube: Введение в Git cherry-pick

Использование git cherry-pick Команда git cherry-pick commit применяет изменения, внесенные именованным коммитом в текущую ветку. Это введет новый, отличный коммит. Строго говоря, использование git cherry-pick не меняет существующую историю в репозитории; вместо этого это добавляет к истории. Как и в случае с другими операциями Git, которые вносят изменения через процесс применения diff, вам может потребоваться разрешить конфликты, чтобы полностью применить изменения из данного коммита . Команда git cherry-pick обычно используется для введения определенных коммитов из одной ветки в хранилище в другую ветку. Обычно используется пересылка или резервирование коммитов из ветви обслуживания в ветку разработки.

$ git checkout rel_2.3
$ git cherry-pick dev~2 # commit F, above

перед: перед

после: после

Теоман Шипахи
источник
12
когда вишневые коммиты берутся на какую-то ветку (b1) и позже доставляются мастеру. И если ветка b1 (из которой изначально были выбраны коммиты) также пытается быть доставлена ​​мастеру. Как насчет конфликтов? Об этом позаботились или как это работает?
parasrish,
3
@parasrish Да, они уже позаботились о ваших предыдущих слияниях. Итак, вы сделали изменения a, b, c, d из ветви (b1). Ты вишню выбрал только "с". Затем в будущем, как только вы перейдете от (b1) к мастеру, так как изменения «c» одинаковы, он объединит только a, b, d и оставит изменения «c». Но если вы откатите свое слияние, то вы вернетесь к изменениям с "c" в нем. Вам нужно будет свернуть их отдельно.
Теоман Шипахи
12
Следует подчеркнуть: в приведенном примере к Z применяется только разность (F - E). Это узкий случай. Cherry-pick может использоваться для применения различий нескольких коммитов, скажем, всех различий между двумя несмежными коммитами. Например, следуя сверху, (F-E), (E-D), (D-C) и (C-B). Это эквивалентно применению разницы (F - B).
Томас Битонти
2
Кроме того, что произойдет, если выбранный Commit (в примере F) имеет более одного непосредственного предшественника?
Томас Битонти
2
@ j2emanue, другими словами, cherry-pick будет принимать только изменения последнего коммита. Если вы делаете 3 разных раза, и если вы выбираете последний, то изменения не будут приняты при первом и втором коммите. Команда Merge примет все ваши изменения и будет применена к вашей целевой (основной) ветке.
Теоман Шипахи
157

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

Чтобы его использовать, вам просто нужно git cherry-pick hash, где hashнаходится хеш коммита из другой ветки.

Для полной процедуры см .: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html

Tadeck
источник
96

Краткий пример ситуации, когда вам нужно вишня выбрать

Рассмотрим следующий сценарий. У вас есть две ветви.

а) релиз1 - эта ветка отправляется вашему клиенту, но все еще есть ошибки, которые нужно исправить.

б) master - классическая мастер-ветка, где вы можете, например, добавить функциональность для release2.

СЕЙЧАС : Вы исправляете что-то в release1 . Конечно, вам нужно это исправить также в мастере . И это типичный случай для сбора вишни. Таким образом, выбор вишни в этом сценарии означает, что вы берете коммит из ветки release1 и включаете его в основную ветку.

Даниэль Перник
источник
3
Вам может просто понадобиться другой путь. Вы исправили ошибку в master, и вам нужно выбрать ее до релиза1. Также они могут быть репозиториями, а не ветвями
canbax
1
Почему бы не использовать слияние для этого?
FreeLightman
Я хотел бы: создать ветку вне выпуска, исправить это в ветке, объединить ветку в выпуске, объединить релиз в master.
Джаспер-М
57

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

  1. оформить (переключиться на) целевую ветку.
  2. git cherry-pick <commit id>
    

    Здесь commit id - это идентификатор активности другой ветви. Например.

    git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
    
  3. нажать на целевую ветку

Посетите https://git-scm.com/docs/git-cherry-pick

Виджай С.Б.
источник
44

Я подготовил пошаговые иллюстрации того, что делает cherry-pick - и анимацию этих иллюстраций (ближе к концу).

  1. Перед сборкой вишни
    (мы собираемся сделать вишневый коммит Lиз ветки feature): введите описание изображения здесь

  1. Запуск команды git cherry-pick feature~2
    ( feature~2это 2- й коммит до
    feature, т.е. коммит L): введите описание изображения здесь

  1. После выполнения команды ( git cherry-pick feature~2): введите описание изображения здесь

То же анимация: введите описание изображения здесь


Замечания:

Фиксация L'- это с точки зрения пользователя (commit = snapshot) точная копия коммита L.

Технически (внутренне), это новый, другой коммит (потому что, например, Lсодержит указатель на K(как его родитель), в то время как L'содержит указатель на E).

MarianD
источник
Означает ли это, что L 'будет N -> M -> L на ветке master? или это принесет исключительно коммит L на главной ветке
Priyank Thakkar
1
@PriyankThakkar, да, исключительно L , больше ничего (как вы можете видеть из картинок / анимации).
MarianD
22

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

A rebaseпринимает коммит, у которого есть родительский X, и регенерирует коммит, как если бы у него был родительский Y, и это именно то, чтоcherry-pick делает .

Cherry pick - больше о том, как вы выбираете коммиты. С помощью pull(rebase) git неявно регенерирует ваши локальные коммиты поверх того, что тянется к вашей ветке, но сcherry-pick вами явно выбирают некоторые и неявно регенерируют их (их) поверх вашей текущей ветки.

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

Хью
источник
1
Я считаю, что это довольно полезный взгляд на вещи. Это подразумевает, почему cherry-pickведет себя так, как это происходит, когда целевая ветвь позже сливается обратно с исходной ветвью. Спасибо, сэр.
Алуан Хаддад
3
я хотел бы использовать вишневый выбор вместо мерзавец слияния после завершения функции. каждый всегда делает git merge feature_branch, когда они завершают функцию. почему бы не использовать команду cherry-pick? есть ли у вас какие-либо мысли? зачем беспокоиться, если я могу выбрать вишню
j2emanue
11

Это как Копировать (откуда-то) и Вставить (куда-то), но для конкретных коммитов.

Например, если вы хотите сделать оперативное исправление, вы можете использовать эту cherry-pickфункцию.

Делайте cherry-pickэто в ветке разработки, а затем mergeфиксируйте ветку релиза. Аналогично, сделайте переход cherry-pickот ветки релиза к мастеру. Вуаля

Аджит Шарма
источник
11

Когда вы работаете с командой разработчиков над проектом, управление изменениями между несколькими ветками git может стать сложной задачей. Иногда вы не хотите объединять целую ветку в другую, и вам нужно только выбрать один или два конкретных коммита. Этот процесс называется «сбор вишни».

Нашел отличную статью о сборке вишни, за подробностями обращайтесь к ней : https://www.previousnext.com.au/blog/intro-cherry-picking-git

Wolfack
источник
7

Если вы хотите объединить без коммитов, вы можете использовать эту команду

git cherry-pick master~2 master~0

Приведенная выше команда объединит последние три коммита мастера с 1 по 3

Если вы хотите сделать это для одного коммита, просто удалите последний вариант

git cherry-pick master~2

Таким образом, вы объедините 3-й коммит с конца мастера.

банкноты
источник
Это смущает. Я думаю, что здесь вы находитесь на ветке, кроме хозяина, верно? И когда вы упомянули два коммита, вы ссылаетесь на коммиты <from> и <to>, чтобы определить диапазон, который вы хотите выбрать. Правильный? Было бы очень полезно, если сценарий описан. Хорошее дополнение, хотя. Спасибо.
Саураб Патил
6

Он будет применять определенный коммит к вашей текущей ветке.

Это означает :

  • все файлы, добавленные этим коммитом, будут добавлены
  • все файлы, удаленные этим коммитом, будут удалены
  • все файлы, измененные этим коммитом, будут объединены. Это означает, что весь файл из коммита, а не только изменения из этого коммита!

Пример: рассмотрим коммит А

added newFileA
modified main:
+ import './newFileA'

совершить B

added newFileB
modified main:
+ import './newFileB'

Если вы выберете коммит B на другой ветке, вы получите:

/newFileB
/main :
   import './newFileA'
   import './newFileB'

Так как commit B содержит newFileB и main , но не newFileA , что приводит к ошибке, поэтому используйте с осторожностью.

mandelf
источник
0

Выдержка из официальных документов:

Учитывая один или несколько существующих коммитов, примените изменения, которые вносит каждый из них, записав новый коммит для каждого. Это требует, чтобы ваше рабочее дерево было чистым (без изменений из коммита HEAD).

Когда не очевидно, как применить изменение, происходит следующее:

  1. Текущая ветка и указатель HEAD остаются на последнем успешно выполненном коммите.

  2. Ссылка CHERRY_PICK_HEAD указывает на коммит, который внес изменение, которое трудно применить.

  3. Пути, в которых корректно применены изменения, обновляются как в файле индекса, так и в вашем рабочем дереве.

  4. Для конфликтующих путей индексный файл записывает до трех версий, как описано в разделе «TRUE MERGE» в git-merge. Файлы рабочего дерева будут содержать описание конфликта, заключенного в скобки с помощью обычных маркеров конфликта <<<<<<< и >>>>>>>.

Никаких других изменений не сделано.

Читать далее...

Saikat
источник