git cherry-pick <sha> берёт правку конкретного коммита и
применяет её на твою ветку. Без всей истории, без merge, без
rebase - только этот один коммит.
Базовая форма
git switch main
git cherry-pick a1b2c3d
▸создаёт новый коммит на main с тем же содержимым,
# что и a1b2c3d, но с новым SHA
Сообщение коммита копируется как есть. Можно добавить
cherry-picked from-метку:
git cherry-pick -x a1b2c3d
# Добавит в сообщение строку:
# (cherry picked from commit a1b2c3d...)
Полезно для аудита: видно, что коммит - копия другого.
Типичные сценарии
Hotfix в нескольких релизных ветках.
# На main починили баг
git switch main
git commit -m "fix: handle null in user.profile"
# SHA = a1b2c3d
# Перенесли в release/v1.4
git switch release/v1.4
git cherry-pick a1b2c3d
# И в release/v1.5
git switch release/v1.5
git cherry-pick a1b2c3d
Достать полезный коммит из заброшенной ветки.
Кто-то начал ветку, забросил, ушёл. Часть коммитов оттуда пригодилась бы. Cherry-pick'аешь нужные.
Коммит ошибочно сделан не в ту ветку.
Закоммитил на main вместо feature.
# Запомним SHA
LAST=$(git rev-parse HEAD)
# Откатим main на один коммит
git reset --hard HEAD~1
# Применим на feature
git switch feature
git cherry-pick $LAST
Диапазон коммитов
git cherry-pick A..B # коммиты после A до B включительно
# (не сам A)
git cherry-pick A^..B # включая A
Применяются по одному, в исходном порядке. При конфликте на любом Git останавливается.
--no-commit
git cherry-pick -n a1b2c3d
# Применит правку, но не закоммитит - оставит в индексе
Удобно, если хочется объединить несколько cherry-pick в один коммит:
git cherry-pick -n sha1 sha2 sha3
git commit -m "backport: nullability fixes from main"
Конфликт
Разрешается как при merge или rebase:
# Конфликт после cherry-pick - править файлы,
# убрать маркеры
git add <files>
git cherry-pick --continue
# или отмена:
git cherry-pick --abort
Подводные камни
- Дубли коммитов. После cherry-pick один и тот же набор правок лежит в двух коммитах с разными SHA. При последующем merge между ветками может возникнуть «ложный» конфликт.
- Зависимости. Cherry-pick переносит один коммит без предыдущих. Если он опирался на что-то добавленное в предыдущем коммите ветки-источника, на ветке-цели этого может не оказаться, и сборка сломается.
- Merge-коммиты. Cherry-pick merge-коммита требует флага
-m N, чтобы указать, какого родителя считать «основным». Обычно сложнее, чем кажется; чаще проще cherry-pick'нуть каждый коммит из merge'нутой ветки по отдельности.