git bisect и cherry-pick: поиск ошибок и перенос коммитов
Коротко: С git bisect вы находите половинным делением коммит, внёсший ошибку; с git cherry-pick переносите отдельные коммиты в другую ветку.
Подробнее: Две продвинутые команды Git, которые сильно экономят время в повседневной работе. Обе предполагают, что история чисто разделена на осмысленные небольшие коммиты.
Подробности
git bisect: поиск ошибки бинарным поиском
Вы знаете: три недели назад работало, теперь нет, а между ними 200 коммитов. git bisect многократно делит диапазон пополам (бинарный поиск), и примерно через восемь шагов вы знаете виновника.
git bisect start
git bisect bad # текущее состояние неисправно
git bisect good v1.4.0 # это состояние было исправным
git bisect good # или: git bisect bad
git bisect reset # вернуться в исходное состояние
С тестовым скриптом он работает автоматически: git bisect run npm test (код завершения 0 = хорошо, 1–127 = плохо, 125 = пропустить).
git cherry-pick: перенос отдельных коммитов
Обычно сливают целые ветки. cherry-pick, напротив, копирует один или несколько коммитов в текущую ветку:
git switch release/1.2
git cherry-pick 3f4a2b1 # перенести один коммит
git cherry-pick A..B # диапазон
git cherry-pick -x 3f4a2b1 # указать источник в сообщении
Типичный случай: ошибка исправлена в основной ветке, но должна попасть и в ветку релиза. Перенесённый коммит получает новый хеш-идентификатор, потому что находится поверх другого родителя.
Конфликты и подводные камни
При конфликтах Git останавливается: разрешите конфликт, git add, затем git cherry-pick --continue (или --abort). Кто многократно переносит коммиты, создаёт в истории дубликаты, которые могут запутать последующие слияния. Cherry-pick не заменяет чистый процесс работы с ветками. При bisect проверяемые состояния должны собираться и быть тестируемыми; с git bisect skip пропускаются неработающие промежуточные состояния.
Связь
Небольшие чистые коммиты (см. Conventional Commits) вообще делают оба инструмента эффективными: огромный коммит «изменил всё» нельзя ни целенаправленно найти, ни целенаправленно перенести. git blame и git log -S также помогают в поиске.
См. также: Git, Git rebase, Конфликты слияния, Conventional Commits