Инструкция

git cherry-pick: как перенести отдельный коммит в другую ветку

Обновлено: · Skillaria.Top

git cherry-pick берёт изменения указанного коммита и создаёт на текущей ветке новый коммит с тем же диффом и сообщением, но другим хешем. Перейдите в целевую ветку и выполните git cherry-pick <хеш>; при конфликте исправьте файлы, сделайте git add и git cherry-pick --continue.

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

Типичный сценарий: в ветке фичи вы исправили баг, а исправление срочно нужно в релизной ветке, где фича ещё не готова. Сливать всю ветку нельзя, а один коммит — можно.

Как перенести один коммит в другую ветку

Сначала найдите хеш нужного коммита, затем переключитесь на ветку, куда его нужно перенести, и выполните cherry-pick.

# 1. Находим коммит в ветке feature
git log --oneline feature
a1b2c3d Исправить деление на ноль в расчёте скидки
9f8e7d6 Добавить новый экран оплаты

# 2. Переходим в целевую ветку
git switch release-1.4

# 3. Переносим коммит
git cherry-pick a1b2c3d
[release-1.4 4e5f6a7] Исправить деление на ноль в расчёте скидки
 Date: Mon Oct 5 14:12:03 2026 +0300
 1 file changed, 3 insertions(+), 1 deletion(-)

Обратите внимание: новый коммит получил хеш 4e5f6a7, а не a1b2c3d. Это два разных объекта с одинаковыми изменениями. Исходная ветка feature не меняется.

Вместо хеша можно передать любую ссылку на коммит: git cherry-pick feature возьмёт последний коммит ветки feature, git cherry-pick feature~2 — третий с конца.

Как перенести несколько коммитов

Перечислением

Хеши можно передать списком — Git применит их в указанном порядке, создав столько же новых коммитов.

git cherry-pick a1b2c3d 7c8d9e0 3f4a5b6

Порядок важен: если второй коммит зависит от первого, а вы перечислили их наоборот, получите конфликт или сломанный код. Безопаснее указывать от старых к новым.

Диапазоном

Для подряд идущих коммитов используется синтаксис диапазона. Здесь есть ловушка, на которой спотыкаются почти все: A..B означает «коммиты, достижимые из B, но не из A», то есть сам A в диапазон не входит.

# Перенесёт коммиты ПОСЛЕ A вплоть до B включительно
git cherry-pick A..B

# Перенесёт A и всё до B включительно
git cherry-pick A^..B

Если нужно перенести всё, что есть в ветке feature и чего нет в main, удобна запись git cherry-pick main..feature. Но если коммитов много, задумайтесь: возможно, вам нужен rebase или merge, а не cherry-pick.

Полезные флаги git cherry-pick

ФлагЧто делаетКогда нужен
-xДобавляет в сообщение строку «(cherry picked from commit …)»При переносе исправлений между публичными ветками — видно происхождение
-n, --no-commitПрименяет изменения в индекс и рабочую директорию без коммитаХотите объединить несколько коммитов в один или поправить перед коммитом
-e, --editОткрывает редактор для правки сообщенияНужно уточнить сообщение под целевую ветку
-s, --signoffДобавляет строку Signed-off-byПроекты с требованием DCO
-m 1Указывает «основного» родителя для merge-коммитаПеренос merge-коммита
--ffПерематывает ветку, если HEAD — родитель выбранного коммитаРедко; позволяет не плодить дубликат
--allow-emptyРазрешает переносить изначально пустые коммитыСлужебные пустые коммиты

Зачем нужен -x

Через полгода кто-то увидит в релизной ветке исправление и захочет понять, откуда оно. Строка, добавленная -x, даёт прямой ответ:

git cherry-pick -x a1b2c3d
git log -1
    Исправить деление на ноль в расчёте скидки

    (cherry picked from commit a1b2c3d4e5f60718293a4b5c6d7e8f9012345678)

Используйте -x, когда исходный коммит уже опубликован. Для переноса из своей локальной ветки, которую вы потом удалите, ссылка будет вести в никуда — там флаг не нужен.

Собрать несколько коммитов в один: -n

git cherry-pick -n a1b2c3d 7c8d9e0
git status          # изменения обоих коммитов в индексе
git commit -m "Исправления расчёта скидки"

Конфликты при cherry-pick и как их решать

Конфликт возникает, когда изменения коммита не ложатся на текущий код: в целевой ветке те же строки уже выглядят иначе. Git останавливается и сообщает об этом.

git cherry-pick a1b2c3d
Auto-merging src/discount.js
CONFLICT (content): Merge conflict in src/discount.js
error: could not apply a1b2c3d... Исправить деление на ноль в расчёте скидки
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".

Дальше у вас три пути:

  1. Разрешить и продолжить. Откройте файл, уберите маркеры <<<<<<<, =======, >>>>>>>, оставив правильный вариант, затем git add src/discount.js и git cherry-pick --continue.
  2. Пропустить коммит. При переносе списка git cherry-pick --skip пропустит проблемный коммит и перейдёт к следующему.
  3. Отменить всё. git cherry-pick --abort вернёт ветку в состояние до начала операции.

Есть ещё git cherry-pick --quit: он прекращает операцию, но оставляет уже применённые коммиты и текущее состояние файлов. Полезно, когда половину списка вы перенесли успешно и дальше хотите действовать вручную.

Если конфликты повторяются из раза в раз (например, вы регулярно переносите исправления в несколько релизных веток), включите git config rerere.enabled true — Git запомнит, как вы разрешили конфликт, и применит решение автоматически в следующий раз.

Как перенести merge-коммит

У merge-коммита два родителя, и Git не знает, относительно какого считать дифф. Без подсказки вы получите ошибку:

git cherry-pick 5d6e7f8
error: commit 5d6e7f8 is a merge but no -m option was given.

Флаг -m 1 говорит: считай изменения относительно первого родителя — обычно это ветка, в которую сливали. Так вы перенесёте всё, что принесла слитая ветка, одним коммитом.

git cherry-pick -m 1 5d6e7f8

Учтите, что после этого Git не будет считать ветку слитой: при будущем merge он может попытаться применить те же изменения повторно.

git cherry-pick и git apply: в чём разница

git apply часто вспоминают рядом с cherry-pick, потому что обе команды «накладывают изменения». Но работают они с разными входными данными.

git cherry-pickgit apply
ИсточникКоммит, который есть в репозиторииФайл патча (дифф)
Создаёт коммитДа (без -n)Нет, только меняет файлы (с --index — ещё и индекс)
Сохраняет автора и сообщениеДаНет, в патче их нет
КонфликтыТрёхстороннее слияние с маркерамиПо умолчанию просто отказ; с --3way — маркеры
Нужен общий репозиторийДа, коммит должен быть доступен локальноНет, патч можно передать как угодно

Пример использования git apply, когда коммита нет в вашем репозитории — коллега прислал дифф файлом:

# Коллега делает
git diff main..fix-discount > fix.patch

# Вы проверяете и применяете
git apply --check fix.patch   # проверить, ляжет ли патч
git apply fix.patch           # применить к рабочей директории
git apply --3way fix.patch    # при расхождениях — с маркерами конфликтов

Если нужно передать коммит целиком, с автором и сообщением, используйте пару git format-patch и git am: первая сохраняет коммиты в файлы, вторая создаёт из них коммиты. По сути это cherry-pick «по почте».

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

Когда cherry-pick — плохая идея

Cherry-pick создаёт дубликаты: одно и то же изменение живёт в истории под двумя хешами. В небольших дозах это нормально, но есть сценарии, где он вредит.

  • Перенос десятков коммитов. Если вы переносите почти всю ветку — это rebase или merge. Cherry-pick здесь даст длинную историю дублей и больше конфликтов.
  • Двусторонние переносы. Коммит перенесли из feature в main, а потом feature сливают в main. Git обычно справляется (изменения совпадают), но если после переноса строки правили, получите конфликт на ровном месте.
  • Зависимые коммиты. Коммит использует функцию, добавленную двумя коммитами ранее. Cherry-pick перенесёт только сам коммит, и код в целевой ветке не соберётся. Всегда проверяйте сборку и тесты после переноса.

Хорошая практика для хотфиксов — делать исправление сразу в самой старой поддерживаемой ветке и сливать его «вверх» в новые. Тогда cherry-pick нужен только как исключение.

Как отменить cherry-pick

Если операция ещё идёт (конфликт) — git cherry-pick --abort. Если коммит уже создан и не отправлен на сервер, уберите его:

git reset --hard HEAD~1

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

git revert 4e5f6a7

А если вы сделали reset и передумали, потерянный коммит находится через git reflog.

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

Раз хеши разные, обычный git branch --contains не поможет. Git умеет сравнивать коммиты по содержимому изменений (patch-id):

git cherry -v release-1.4 feature
- a1b2c3d Исправить деление на ноль в расчёте скидки
+ 9f8e7d6 Добавить новый экран оплаты

Минус означает, что эквивалентное изменение в release-1.4 уже есть, плюс — что ещё нет. Альтернатива — git log --cherry-pick --oneline release-1.4...feature, которая скрывает коммиты-близнецы. Если вы использовали -x, можно просто искать по сообщению: git log --grep="cherry picked from commit a1b2c3d".

Итог

git cherry-pick — точечный инструмент: перенести хотфикс в релиз, вытащить полезный коммит из заброшенной ветки, восстановить случайно сделанный не туда коммит. Запомните три вещи: новый коммит получает новый хеш, диапазон A..B не включает A, а для публичных веток стоит добавлять -x. Если нужно перенести не коммит, а дифф из файла, берите git apply. Rebase, stash, cherry-pick и теги подробно разобраны на практике в курсе по Git.

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

Меняет ли cherry-pick исходную ветку?

Нет. Исходный коммит остаётся на месте, а в текущей ветке появляется его копия с новым хешем.

Можно ли сделать cherry-pick коммита из удалённой ветки?

Да. Выполните git fetch, после чего коммит доступен по хешу или как origin/имя-ветки, и его можно передать в git cherry-pick.

Почему после cherry-pick у коммита другой хеш?

Хеш зависит от родителя, времени коммита и содержимого дерева. У копии другой родитель и время коммиттера, поэтому хеш тоже другой.

Сохраняется ли автор коммита при cherry-pick?

Да, автор и дата авторства берутся из исходного коммита, а коммиттером становитесь вы с текущей датой.

Что делать, если cherry-pick говорит, что коммит пустой?

Значит, такие изменения в ветке уже есть. Пропустите его через git cherry-pick --skip или зафиксируйте пустым через git commit --allow-empty.

Разберите тему на видео

Эта тема подробно разобрана с практикой в курсе «Git с нуля до уверенного разработчика».

Перейти к курсу