W3docs

git cherry-pick

Узнайте о команде git cherry-pick: как копировать отдельные коммиты между ветками, параметры, разрешение конфликтов и примеры.

Что делает git cherry-pick

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

На этой странице рассматривается, как cherry-pick работает внутри, как выбрать один коммит или диапазон, какие параметры вам действительно пригодятся, как разрешать конфликты и когда стоит использовать cherry-pick вместо merge или git revert.

git cherry-pick копирует коммит из feature-ветки в main

Как это работает

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

Это ключевое отличие в понимании: cherry-pick копирует изменение, а не перемещает его. Исходный коммит остаётся нетронутым в своей исходной ветке.

git switch main
git cherry-pick a1b2c3d

Изменение из коммита a1b2c3d теперь находится в main в виде нового коммита.

Пример использования

Допустим, исправление было зафиксировано в ветке feature, но оно должно быть в main. Сначала найдите хэш коммита с помощью git log:

git switch feature
git log --oneline
# d9ae654 fix login redirect
# 7c1a902 work in progress
# fa42ab5 base

Теперь переключитесь на main и скопируйте только этот один коммит:

git switch main
git cherry-pick d9ae654
[main 02bbf3e] fix login redirect
 1 file changed, 1 insertion(+)

Обратите внимание на новый хэш 02bbf3e — исправление теперь находится в main как совершенно новый коммит, тогда как d9ae654 по-прежнему существует нетронутым в ветке feature.

Выбор диапазона коммитов

Можно применить несколько коммитов за один раз. Диапазон копирует каждый коммит после первого вплоть до последнего включительно:

git cherry-pick a1b2c3d..f4e5d6c

При этом сам a1b2c3d исключается. Чтобы сделать диапазон включительным с начального коммита, добавьте суффикс ^, чтобы диапазон начинался с его родителя:

git cherry-pick a1b2c3d^..f4e5d6c

Коммиты применяются по одному в порядке очерёдности; если возникает конфликт, cherry-pick останавливается на этом коммите, чтобы вы могли его исправить перед продолжением.

Основные параметры

КомандаОписание
git cherry-pick <commit>Применяет изменение из <commit> как новый коммит в текущей ветке.
git cherry-pick -n <commit>Применяет изменение, но не фиксирует его, оставляя в индексе для проверки или доработки перед коммитом.
git cherry-pick -x <commit>Добавляет строку (cherry picked from commit …) к сообщению — полезно в публичных ветках, чтобы другие могли отследить происхождение.
git cherry-pick -e <commit>Открывает редактор, чтобы вы могли изменить сообщение коммита до его записи.
git cherry-pick --continueВозобновляет операцию после разрешения конфликтов.
git cherry-pick --skipПропускает текущий коммит (например, когда его изменение уже присутствует) и переходит к следующему.
git cherry-pick --abortОтменяет операцию и восстанавливает ветку в исходное состояние.

При использовании -x записанное сообщение выглядит следующим образом:

fix login redirect

(cherry picked from commit d9ae65426adbde425c3e386a32297e9e833d8816)

Обработка конфликтов

Если изменение не применяется без конфликтов, cherry-pick приостанавливается — так же, как при слиянии — и оставляет маркеры конфликта в затронутых файлах. Вы увидите:

CONFLICT (content): Merge conflict in app.js
error: could not apply d9ae654... fix login redirect
hint: ... fix conflicts and then run "git cherry-pick --continue".

Вручную разрешите конфликты в файлах, проиндексируйте их с помощью git add, затем продолжите:

git add app.js
git cherry-pick --continue

На этом этапе доступны три варианта выхода из ситуации:

  • git cherry-pick --continue — завершить после разрешения конфликтов.
  • git cherry-pick --skip — пропустить текущий коммит и перейти к следующему в диапазоне.
  • git cherry-pick --abort — полностью отменить операцию и вернуть ветку к исходному состоянию.

Используйте git status в любой момент, чтобы посмотреть, в каких файлах ещё остались конфликты.

Когда использовать

Cherry-pick особенно полезен, когда:

  • Исправление попало не в ту ветку и вам нужно перенести его в другое место.
  • Вы выполняете бэкпортирование отдельного патча в ветку релиза или сопровождения.
  • Вам нужен один коммит из feature-ветки без слияния всей ветки целиком.

Cherry-pick против merge, rebase и revert

ЦельКоманда
Скопировать один (или несколько) конкретных коммитов в другую веткуgit cherry-pick
Интегрировать всю историю веткиgit merge
Перенести коммиты ветки на новую базуgit rebase
Отменить коммит, записав противоположный коммитgit revert

Подводные камни

  • Дубликаты в общей истории. Cherry-picking в ветку, которая впоследствии будет слита обратно в исходную, создаёт два коммита с одинаковым изменением. Git обычно достаточно умён, чтобы пропустить дубликат при слиянии, но это может усложнить историю — предпочтите merge или rebase, если вам нужна вся ветка.
  • Пустые результаты. Если изменение уже присутствует в целевой ветке, cherry-pick останавливается с сообщением The previous cherry-pick is now empty. Используйте git cherry-pick --skip для продолжения или --abort для отмены.
  • Новый хэш, а не исходный. Поскольку коммит воссоздаётся заново, его хэш меняется. Добавьте -x, чтобы в сообщении было записано, откуда он пришёл.

Практика

Практика
Что делает 'git cherry-pick' с коммитом, который он копирует?
Что делает 'git cherry-pick' с коммитом, который он копирует?
Was this page helpful?