← Назад к вопросам

Как работает cherry-pick?

1.0 Junior🔥 51 комментариев
#Git и VCS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Git cherry-pick: копирование отдельных коммитов

cherry-pick — это команда Git, которая позволяет применить изменения из одного или нескольких коммитов на другую ветку, не переключая всю историю ветки.

Базовая концепция

Если в ветке feature есть коммиты A, B, C, D, но нам нужны только коммиты B и D на ветке main, мы можем cherry-pick их вместо merge всей ветки.

До cherry-pick:

main:       A ------- G ------- H
                    /
feature:   A - B - C - D - E

После cherry-pick B и D на main:

main:       A ------- G ------- H ------- B' ------- D'
                    /
feature:   A - B - C - D - E

(B' и D' — новые коммиты с теми же изменениями, но другие hash'и)

Основной синтаксис

Применить один коммит:

git cherry-pick abc1234

Это возьмёт изменения из коммита abc1234 и применит их на текущую ветку.

Применить несколько коммитов подряд:

git cherry-pick abc1234..def5678

Это применит все коммиты от abc1234 до def5678 (исключая abc1234, включая def5678).

Применить несколько отдельных коммитов:

git cherry-pick abc1234 def5678 ghi9012

Как это работает внутри

Шаг 1: Git вычисляет diff

Git берёт коммит и вычисляет, какие изменения он внёс:

# Коммит abc1234:
# Измененный файл: main.py
# - old_line_1
# + new_line_1
# - old_line_2
# + new_line_2

Шаг 2: Применяет diff на текущую ветку

Гит применяет эти изменения как патч (patch):

git apply abc1234.patch

Шаг 3: Создаёт новый коммит

Если патч применился без конфликтов, Git создаёт новый коммит с тем же сообщением (или похожим), но с новым hash'ем (потому что дата и parent изменились).

Оригинальный коммит:
  hash: abc1234
  parent: xyz9999
  message: "Fix bug in login"
  timestamp: 2024-01-15 10:30

cherry-picked коммит:
  hash: NEW8888  # Новый hash!
  parent: main_HEAD  # Новый parent
  message: "Fix bug in login"  # Обычно то же сообщение
  timestamp: 2024-03-22 14:45  # Текущее время

Практический пример

Представим, что мы разрабатываем две функции в разных ветках:

# Ситуация: у нас есть критичный баг fix в ветке feature/auth
# Но на main сейчас другие коммиты, и мы не хотим мержить весь feature

# 1. Смотрим историю feature/auth
git log feature/auth --oneline
# abc1234 Fix critical security bug in password reset
# def5678 Refactor login UI
# ghi9012 Add 2FA support

# 2. Переключаемся на main
git checkout main

# 3. Cherry-pick только коммит с фиксом
git cherry-pick abc1234
# [main new_hash] Fix critical security bug in password reset
#  1 file changed, 10 insertions(+), 5 deletions(-)

# 4. Проверяем результат
git log --oneline
# new_hash Fix critical security bug in password reset
# xyz9999 Previous commit on main
# ...

# 5. Запушим на main
git push origin main

Конфликты при cherry-pick

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

$ git cherry-pick abc1234
error: could not apply abc1234... Fix bug
hint: after resolving the conflicts, mark the resolved files
hint: with 'git add' and run 'git cherry-pick --continue'

Тогда нужно:

# 1. Отредактировать конфликтные файлы (удалить маркеры <<<<<<)
vim src/main.py

# 2. Добавить исправленные файлы
git add src/main.py

# 3. Продолжить cherry-pick
git cherry-pick --continue

# Или отменить, если хочется
git cherry-pick --abort

Опции cherry-pick

-e / --edit — отредактировать сообщение коммита:

git cherry-pick -e abc1234
# Откроется редактор, где можно изменить сообщение

-x — добавить ссылку на оригинальный коммит:

git cherry-pick -x abc1234
# Сообщение коммита добавит: (cherry picked from commit abc1234)

-n / --no-commit — применить изменения, но не создавать коммит:

git cherry-pick -n abc1234
# Изменения будут в staging area, но коммит не создастся
# Полезно, если нужно объединить несколько cherry-pick в один коммит

--continue / --abort / --quit:

git cherry-pick --continue  # Продолжить после разрешения конфликтов
git cherry-pick --abort      # Отменить весь cherry-pick
git cherry-pick --quit       # Выйти, но оставить текущее состояние

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

Хорошие причины:

  • Применить критичный баг-фикс из одной ветки на production
  • Портировать фичу из одной версии в другую
  • Перенести отдельный коммит, когда полный merge не подходит
# Пример: критичный фикс нужно применить на production
git checkout production
git cherry-pick abc1234  # Фикс из develop
git push origin production

Плохие причины:

  • Копировать много коммитов (используй merge)
  • Переписывать историю (используй rebase)
  • Избежать полноценного merge (это может привести к путанице)

Cherry-pick vs Merge vs Rebase

ОперацияИспользуется дляРезультат
cherry-pickОтдельные коммитыНовые коммиты с тем же содержимым
mergeВся веткаMerge коммит, объединяющий истории
rebaseПереписание историиПереписанная цепочка коммитов

Потенциальные проблемы

1. Дублирование кода

Если позже замержить ту же ветку целиком, одни и те же изменения будут применены дважды, что может вызвать конфликты.

2. Нарушение логики коммитов

Если cherry-pick применить в другом порядке или без зависимых коммитов, может получиться нелогичная история.

3. Сложность отследить происхождение

После нескольких cherry-pick'ов сложно понять, где оригинальные коммиты.

Лучшие практики

  1. Используй cherry-pick для одиночных критичных фиксов
  2. Документируй причину cherry-pick'а в сообщении коммита
  3. После cherry-pick'а все равно упомяни оригинальный коммит (git cherry-pick -x)
  4. Если нужно скопировать много коммитов, используй merge, а не несколько cherry-pick'ов
  5. Избегай cherry-pick'ов между веками, чтобы не путать историю

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

Как работает cherry-pick? | PrepBro