Bisect и cherry-pick
Updated Jul 2026
Git bisect: поиск регрессий бинарным поиском
Когда тест, который раньше проходил, теперь падает, git bisect выполняет бинарный поиск по истории коммитов, чтобы найти точно тот коммит, который внёс регрессию. Вместо ручной проверки десятков коммитов bisect находит ответ за log2(n) шагов. Для 1000 коммитов это около 10 шагов.
Как работает bisect
Вы сообщаете Git один «хороший» коммит (где тест проходил) и один «плохой» коммит (где тест падает). Git переключается на среднюю точку и просит вас оценить её. На основе вашего ответа он сужает диапазон вдвое и повторяет.
Commit history: A B C D E F G H I J K L M N O P
good? bad
Step 1: Git checks out H (midpoint)
→ You test: PASS → good
Range narrows to: I J K L M N O P
Step 2: Git checks out L (midpoint of remaining)
→ You test: FAIL → bad
Range narrows to: I J K L
Step 3: Git checks out J (midpoint)
→ You test: PASS → good
Range narrows to: K L
Step 4: Git checks out K
→ You test: FAIL → bad
Result: K is the first bad commit
Четыре шага, чтобы найти проблему среди 16 коммитов.
Ручной bisect
# Start the bisect session
git bisect start
# Mark the current commit as bad (the test is failing here)
git bisect bad
# Mark a known good commit (a tag, SHA, or branch where the test passed)
git bisect good v2.3.0
# Git checks out a middle commit. Run your test:
npm run test:checkout
# If the test passes:
git bisect good
# If the test fails:
git bisect bad
# Git narrows the range and checks out another commit.
# Repeat until Git identifies the first bad commit.
# Git will output something like:
# abc123f is the first bad commit
# Author: Dev McDevface
# Date: Mon Jan 15 14:32:00 2024
# Subject: refactor coupon validation logic
# When done, reset to your original branch:
git bisect reset
Автоматизированный bisect
Настоящая сила bisect — в автоматизации. Дайте Git команду, которая возвращает 0 (хорошо) или ненулевое значение (плохо), и он выполнит весь bisect автоматически.
# Fully automated bisect
git bisect start HEAD v2.3.0
git bisect run npm run test:checkout
# Or with a specific test file
git bisect start HEAD v2.3.0
git bisect run npx playwright test tests/checkout.spec.ts
# Using a custom script for more complex checks
git bisect start HEAD v2.3.0
git bisect run ./scripts/bisect-test.sh
Практичный скрипт bisect с обработкой настройки:
#!/bin/bash
# scripts/bisect-test.sh
# Install dependencies (they may differ between commits)
npm ci --silent 2>/dev/null
# Run the specific test
npx playwright test tests/checkout.spec.ts --reporter=list 2>/dev/null
# Exit code 0 = good, non-zero = bad
# Exit code 125 = skip (cannot test this commit, e.g., build fails)
Код выхода 125 сообщает bisect пропустить этот коммит (его невозможно протестировать, возможно, потому что он не компилируется). Bisect продолжает со следующим кандидатом.
Когда использовать bisect
| Сценарий | Почему bisect помогает |
|---|---|
| Тест, проходивший на прошлой неделе, теперь падает | Найти точный коммит, который его сломал |
| Регрессия производительности (загрузка страницы в 3 раза медленнее) | Найти, когда было введено замедление |
| Визуальная регрессия (сместилась вёрстка) | Найти, какой коммит изменил CSS |
| Появился нестабильный тест | Найти, когда была введена нестабильность |
| Функция, которая «работала раньше», сломана | Доказать, какой коммит внёс баг |
Bisect незаменим для QA, потому что даёт вам конкретный коммит, автора и описание для ссылки в баг-репорте. «Эта регрессия была введена в коммите abc123f от @developer 15 января при рефакторинге валидации купонов» гораздо более actionable, чем «оформление заказа сломано».
Cherry-pick: точечное применение коммитов
Cherry-pick применяет конкретный коммит из одной ветки в другую без слияния всей ветки. Создаётся новый коммит с теми же изменениями, но другим хэшем.
# A bug fix was committed to develop, but you need it on the release branch now
git checkout release/2.4
git cherry-pick abc123f
# Cherry-pick multiple commits
git cherry-pick abc123f def456a ghi789b
# Cherry-pick a range of commits
git cherry-pick abc123f..ghi789b
# If there is a conflict, resolve it and continue
git add .
git cherry-pick --continue
# Or abort the cherry-pick
git cherry-pick --abort
Типичные QA-сценарии для cherry-pick
Исправление теста нужно в нескольких ветках
Вы исправили нестабильный тест в develop, но тот же тест нестабилен в ветке release/2.4.
# Find the commit hash of your fix on develop
git log --oneline develop -- tests/payment.spec.ts
# Output: abc123f fix(payment): stabilize test by awaiting API response
# Apply it to the release branch
git checkout release/2.4
git cherry-pick abc123f
Верификация хотфикса
Хотфикс был закоммичен в main для продакшен-проблемы. Вам нужно проверить его на тестовой ветке без слияния всего main.
git checkout test/regression-suite
git cherry-pick <hotfix-commit-hash>
# Run regression tests including the fix
npm run test:regression
Перенос тестовой инфраструктуры в фича-ветку
Тестовая инфраструктура была обновлена в develop (например, новые хелперы page object), но ваша фича-ветка была создана до этого обновления.
git checkout feature/my-tests
git cherry-pick <infrastructure-commit-hash>
# Now you have the new helpers without merging everything else from develop
Лучшие практики cherry-pick
- Cherry-pick создаёт новый коммит: оригинальный и cherry-pick коммиты имеют разные хэши. Git не знает, что они связаны.
- Конфликты часты: если cherry-pick коммит зависит от предшествующих изменений, отсутствующих в целевой ветке, вы получите конфликты.
- Предпочитайте merge или rebase, когда возможно: cherry-pick предназначен для точечных, исключительных случаев. Если вы часто используете cherry-pick, возможно, ваша стратегия ветвления нуждается в корректировке.
- Документируйте cherry-pick: добавьте примечание в сообщение коммита: «Cherry-picked from abc123f on develop.»
# Cherry-pick with a note
git cherry-pick abc123f --edit
# In the editor, add: "(cherry-picked from abc123f on develop)"
Комбинирование bisect и cherry-pick
Мощный QA-рабочий процесс:
- Bisect для нахождения коммита, внёсшего регрессию
- Изучение коммита для понимания корневой причины
- Работа с разработчиком для создания исправления
- Cherry-pick исправления в ветку релиза для немедленного развёртывания
- Слияние исправления в develop для долгосрочной интеграции
# Step 1: Find the regression
git bisect start HEAD v2.3.0
git bisect run npx playwright test tests/checkout.spec.ts
# Result: commit abc123f introduced the regression
# Step 2: Review
git show abc123f
# Step 3: Developer creates fix on develop (commit def456a)
# Step 4: Cherry-pick fix to release branch
git checkout release/2.4
git cherry-pick def456a
# Step 5: Verify the fix
npx playwright test tests/checkout.spec.ts
Практическое упражнение
- Создайте репозиторий с 20+ коммитами. Намеренно сломайте тест в коммите 12.
- Используйте
git bisect(ручной режим) для нахождения сломавшего коммита. - Повторите с автоматизированным bisect:
git bisect run <test-command> - Потренируйтесь в cherry-pick одного коммита из одной ветки в другую.
- Намеренно создайте конфликт cherry-pick, разрешите его и завершите cherry-pick.
- Напишите скрипт bisect, который обрабатывает установку зависимостей и возвращает код выхода 125 для некомпилируемых коммитов.