Git cherry-pick: как перенести коммит в другую ветку

Категория: Git · Язык: Bash · Обновлено:

Команда git cherry-pick хеш копирует выбранный коммит в текущую ветку как новый коммит с тем же содержимым. Так удобно переносить исправление в другую ветку, не вливая всю остальную работу. Хеш коммита берут из git log.

Перенести один коммит

Bash
git switch release/1.2          # ветка, куда нужно перенести исправление
git cherry-pick a1b2c3d         # коммит из другой ветки

Git создаст в release/1.2 новый коммит с теми же изменениями и сообщением. Хеш у него обычно другой, потому что у коммита другой родитель.

Перенести несколько коммитов

Bash
git cherry-pick a1b2c3d e4f5a6b            # перечислить коммиты
git cherry-pick a1b2c3d^..e4f5a6b          # диапазон: от первого до второго включительно

Запись первый^..второй включает и первый коммит. Без знака ^ первый коммит в диапазон не войдёт.

Полезные флаги

Флаг

Что делает

-x

Дописывает в сообщение «(cherry picked from commit …)», удобно для истории

-n или --no-commit

Применяет изменения, но не создаёт коммит

-e

Открывает редактор для сообщения

-m 1

Нужен для merge-коммита: выбирает родителя, относительно которого считать изменения

--abort

Отменяет операцию при конфликте

--continue

Продолжает после ручного разрешения конфликта

Если возник конфликт

Bash
git status                      # какие файлы конфликтуют
# исправьте файлы, затем
git add путь/к/файлу
git cherry-pick --continue      # завершить перенос
git cherry-pick --abort         # отказаться и вернуть ветку как было

Перенести изменения без коммита

Когда нужно забрать правки из чужого коммита и добавить свои в тот же коммит:

Bash
git cherry-pick -n a1b2c3d
git add .
git commit -m "Исправление из main и мои доработки"

Частые вопросы

Чем cherry-pick отличается от merge?

merge переносит всю историю ветки. cherry-pick копирует только выбранные коммиты и создаёт для них новые.

Как узнать, перенесён ли коммит уже в ветку?

Выполните git cherry -v release/1.2 main: перед коммитами, которых нет в release/1.2, стоит знак +, перед уже перенесёнными стоит -.

Что будет с исходным коммитом?

Ничего: он остаётся в своей ветке. При последующем слиянии веток git обычно распознаёт одинаковые изменения и не создаёт конфликт.