Cherry-pick: Выборочное применение коммитов¶
git cherry-pick позволяет применить изменения из конкретного коммита (или нескольких) из одной ветки в другую, без слияния целой ветки.
Зачем использовать Cherry-pick?¶
- Нужно перенести только одно исправление (например, багфикс) из фич-ветки в
main. - Хотим взять конкретную фичу из другой ветки, не сливая всё остальное.
- Нужно применить коммит из чужой ветки или даже из другого репозитория.
Базовое использование¶
Применение одного коммита¶
# Находясь в целевой ветке
git checkout main
git cherry-pick <хеш-коммита>
Пример:
git cherry-pick a1b2c3d
Git применит изменения из указанного коммита к текущей ветке и создаст новый коммит.
Применение нескольких коммитов¶
git cherry-pick <хеш1> <хеш2> <хеш3>
Применение диапазона коммитов¶
git cherry-pick <начальный-хеш>^..<конечный-хеш>
Важно: Символ ^ включает начальный коммит в диапазон. Без него диапазон будет от следующего коммита после начального.
Пример:
git cherry-pick a1b2c3d^..e4f5g6h
Применит все коммиты от a1b2c3d до e4f5g6h включительно.
Опции Cherry-pick¶
Без создания коммита¶
Если хотите применить изменения, но сделать коммит позже (например, чтобы объединить несколько cherry-pick в один коммит):
git cherry-pick --no-commit <хеш>
# или кратко
git cherry-pick -n <хеш>
После применения всех нужных коммитов:
git commit -m "Применить исправления из ветки feature"
Изменение сообщения коммита¶
По умолчанию сообщение коммита копируется из оригинального. Можно изменить:
git cherry-pick --edit <хеш>
Откроется редактор для изменения сообщения перед коммитом.
Продолжение после конфликта¶
Если возник конфликт, разрешите его вручную, затем:
git add <разрешенные-файлы>
git cherry-pick --continue
Отмена cherry-pick¶
Если поняли, что пошли не туда:
git cherry-pick --abort
Что происходит с хешем коммита?¶
При cherry-pick Git создает новый коммит с новыми изменениями, поэтому хеш коммита будет отличаться от оригинального, даже если изменения идентичны.
До:
A---B---C (feature)
\
D---E (main)
После git cherry-pick B (в main):
A---B---C (feature)
\
D---E---B' (main)
Где B' — новый коммит с теми же изменениями, что и B, но с другим хешем.
Частые сценарии¶
Сценарий 1: Срочный багфикс¶
Разработчик работает в ветке feature и исправил критический баг. Нужно срочно применить исправление в main, не дожидаясь завершения всей фичи.
# В ветке feature найдите хеш коммита с исправлением
git log feature --oneline
# Переключитесь на main
git checkout main
# Примените только этот коммит
git cherry-pick <хеш-багфикса>
# Отправьте на сервер
git push origin main
Сценарий 2: Перенос фичи между ветками¶
Нужно перенести готовую фичу из одной ветки в другую, не сливая весь код.
git checkout target-branch
git cherry-pick <хеш-коммита-с-фичей>
Проблемы и ограничения¶
- Дублирование истории: Если потом слить исходную ветку, могут возникнуть конфликты, так как коммиты уже были применены.
- Потеря контекста: Cherry-pick копирует только изменения, но не историю развития фичи.
- Не для частого использования: Лучше использовать слияние веток для регулярной работы. Cherry-pick — для исключительных случаев.
Альтернатива: Rebase¶
Если нужно перенести несколько последовательных коммитов, иногда проще сделать rebase:
git checkout feature
git rebase --onto main <точка-разделения> feature
Но это сложнее и требует понимания истории.