TuBrief
구독 채널
비디오
커뮤니티

Практическое руководство по Stacked PR: как избавиться от недельных задержек ревью из-за гигантских PR

TuBrief 편집팀
2026년 8월 7일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

Русский한국어EnglishEspañol中文हिन्दीDeutschFrançaisالعربيةPortuguêsBahasa Indonesia日本語

관련 영상

Главный релиз GitHub за последние годы. Стекированные PR.5:17

Главный релиз GitHub за последние годы. Стекированные PR.

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Практическое руководство по Stacked PR: как избавиться от недельных задержек ревью из-за гигантских PR

С внедрением AI-инструментов скорость генерации кода невероятно возросла. Однако скорость код-ревью за ней не поспевает. Согласно отчету DORA (DevOps Research and Assessment) за 2024 год, в командах с высоким уровнем внедрения AI средний размер PR увеличился на 154%, а время на ревью выросло на 91%. В результате частота деплоев только замедлилась. Любой устанет, если ему предлагают проревьюить за один раз более 1 000 строк кода. Чтобы покончить с этим хаосом, нужно перейти на цепочечную структуру из связанных друг с другом PR — Stacked PRs.

Делим кусок в 1 000 строк на 3 ветки

Если просто так разрезать код, компиляция упадет или нарушатся зависимости. Нужен четкий критерий. Ограничьте единичный PR изменением не более чем 200 строк кода и менее чем 10 файлами, чтобы ревьюер мог закончить работу за 15 минут. Одна гигантская задача делится максимум на 3 дочерние ветки в цепочке:

  • Layer 1: Схема БД, сущности, DTO
  • Layer 2: Доменная логика, реализации сервисов
  • Layer 3: Контроллеры, API-эндпоинты

Строго соблюдайте этот порядок. Названия веток также фиксируйте в формате feature/<название-фичи>/stack-<этап>-<описание>. Процесс декомпозиции уже запутанной ветки на 1 000 строк (legacy-giant-branch) в цепочку довольно прост.

Сначала обновите ветку main и сделайте бэкап оригинала.

`bash
git checkout main
git pull origin main
git checkout legacy-giant-branch
git branch backup/legacy-giant-branch

`

Затем ответвите Layer 1 от main и примените через cherry-pick только коммиты, относящиеся к схеме.

`bash
git checkout -b feature/order-refactor/stack-1-schema main
git cherry-pick
git push origin feature/order-refactor/stack-1-schema

`

Теперь, используя Layer 1 в качестве родительской ветки, последовательно создайте Layer 2 и Layer 3.

`bash
git checkout -b feature/order-refactor/stack-2-service feature/order-refactor/stack-1-schema
git cherry-pick
git push origin feature/order-refactor/stack-2-service

git checkout -b feature/order-refactor/stack-3-controller feature/order-refactor/stack-2-service
git cherry-pick
git push origin feature/order-refactor/stack-3-controller

`

Выбор инструментов тоже вызывает споры. Чистый Git CLI не требует затрат, но требует много ручной работы, а специализированные инструменты вроде Graphite удобны, но влекут за собой расходы и инфраструктурную зависимость.

Критерий оценки Pure Git CLI GitHub CLI (gh stack) Graphite / External Tools
Отслеживание зависимостей Ручная настройка базы веток Локальный .git и метаданные GitHub Отдельный удаленный движок и локальная БД
Автоматизация ребейза Ручная работа с каждой веткой Выполнение команды gh stack rebase Автоматическая обработка дочерней цепочки при изменении коммитов
Кривая обучения Высокая (требуется понимание принципов Git) Низкая (установка расширения CLI) Средняя (требуется адаптация к отдельному UI)
Операционная стабильность 100% совместимость со стандартным Git Статус Public Preview Очень высокая

Предотвращение конфликтов ребейза при изменении родительского PR

При использовании Stacked PR самый неприятный момент — это запрос на исправление родительского PR. Поскольку хеши коммитов меняются, все дочерние ветки ниже ломаются. Если просто применить git rebase, коммиты добавятся дубликатами. Диапазон для извлечения нужно указывать с помощью конструкции git rebase --onto.

Если был изменен Layer 1, перейдите в Layer 2 и перенесите изменения с момента коммита старого Layer 1 до текущего HEAD на новую вершину Layer 1.

`bash
git checkout feature/order-refactor/stack-2-service
git rebase --onto feature/order-refactor/stack-1-schema feature/order-refactor/stack-2-service
git push --force-with-lease

`

Точно так же перенесите Layer 3 поверх нового Layer 2.

`bash
git checkout feature/order-refactor/stack-3-controller
git rebase --onto feature/order-refactor/stack-2-service feature/order-refactor/stack-3-controller
git push --force-with-lease

`

Если делать эту работу вручную каждый раз, человек обязательно допустит ошибку. Напишитеシェル-скрипт (shell-скрипт) для автоматизации последовательного ребейза.

`bash
#!/usr/bin/env bash
set -e

STACK_BRANCHES=(
"feature/order-refactor/stack-1-schema"
"feature/order-refactor/stack-2-service"
"feature/order-refactor/stack-3-controller"
)
TARGET_BASE="main"

git fetch origin
CURRENT_PARENT="$TARGET_BASE"

for BRANCH in "STACKBRANCHES[@]";dogitcheckout"{STACK_BRANCHES[@]}"; do git checkout "STACKB​RANCHES[@]";dogitcheckout"BRANCH"
OLD_BASE=(gitmerge−base"(git merge-base "(gitmerge−base"CURRENT_PARENT" "BRANCH"2>/dev/null∣∣echo"")if[−n"BRANCH" 2>/dev/null || echo "") if [ -n "BRANCH"2>/dev/null∣∣echo"")if[−n"OLD_BASE" ]; then
git rebase --onto "CURRENTPARENT""CURRENT_PARENT" "CURRENTP​ARENT""OLD_BASE" "BRANCH"∣∣exit1figitpush−−force−with−leaseorigin"BRANCH" || exit 1 fi git push --force-with-lease origin "BRANCH"∣∣exit1figitpush−−force−with−leaseorigin"BRANCH"
CURRENT_PARENT="$BRANCH"
done

`

Не забудьте включить функцию сохранения истории разрешения конфликтов в настройках Git. Она автоматически пропустит повторяющиеся конфликты.

`bash
git config --global rerere.enabled true
git config --global rerere.autoupdate true
git config --global rebase.autoStash true
git config --global rebase.updateRefs true

`

Предотвращение траты ресурсов CI-раннеров и путаницы в порядке слияния

Разделение PR на три части приводит к проблеме троекратного запуска CI-раннеров. Запускать тяжелые E2E-тесты для каждого PR не требуется. Настройте окружение GitHub Actions так, чтобы на нижних уровнях выполнялись только надежные юнит-тесты, а полная интеграционная проверка выполнялась только в PR верхнего уровня.

Добавьте условие позиции в стеке в .github/workflows/ci.yml.

`yaml
name: Stack-Aware CI Pipeline

on:
pull_request:
branches: [ main ]

jobs:
fast-lint-and-unit-test:
name: Fast Validation (All Layers)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Linter & Unit Tests
run: |
npm ci
npm run test:unit

heavy-integration-test:
name: Full E2E Test (Top Layer Only)
runs-on: ubuntu-latest
if: |
github.event.pull_request.stack == null ||
github.event.pull_request.stack.position == github.event.pull_request.stack.size
steps:
- uses: actions/checkout@v4
- name: Run Heavy Integration & E2E Tests
run: |
npm ci
npm run test:e2e

`

Настройка правил защиты ветки на уровне организации также обязательна.

  1. Включите функцию GitHub Merge Queue, чтобы принудительно объединять одобренные стэк-PR по порядку.
  2. Включите 'Require Linear History' в Repository Rulesets, чтобы предотвратить появление мусорных коммитов слияния (Merge Commit).
  3. Используйте 'Require Status Checks to Pass Before Merging', чтобы предотвратить ситуации, когда PR верхнего уровня попадает в main до слияния нижнего PR.

Культура командного ревью и устранение проблем с UI после Squash Merge

Для полноценной работы со Stacked PR ревьюеры должны видеть общую картину. Укажите карту стека в файле .github/PULL_REQUEST_TEMPLATE.md.

`markdown
Stack Overview
Этот PR является частью цепочки Order Refactoring Stack.

  1. #101 - feature/order-refactor/stack-1-schema (DB Migration)
  2. [Current PR] #102 - feature/order-refactor/stack-2-service (Business Logic)
  3. #103 - feature/order-refactor/stack-3-controller (API Controller)

Current Layer Scope

  • Реализация логики изменения статуса платежа в OrderService
  • Добавление обработки публикации доменных событий и тестов интеграции с репозиторием

Dependency Status

  • Base PR: #101 (Должен быть слит в первую очередь)

`

После того как нижний PR #101 объединяется с main через Squash Merge, Diff в пользовательском интерфейсе GitHub для дочернего PR #102 неожиданно взрывается. Это явление, при котором изменения уже слитого #101 начинают учитываться как изменения дочернего PR. Это происходит потому, что SHA Squash-коммита и SHA родительского коммита в графе коммитов Git стали разными. Не паникуйте, просто перенесите коммиты дочерней ветки поверх main в следующем порядке:

`bash
git log --graph --oneline
git checkout feature/order-refactor/stack-2-service
git fetch origin
git rebase --onto origin/main feature/order-refactor/stack-2-service
git push --force-with-lease origin feature/order-refactor/stack-2-service

`

Работа по разделению гигантского PR на 1 000 строк — это не просто вопрос владения технологией Git. Это инженерная задача по наведению порядка в процессе код-ревью команды и во всей цепочке деплоя. Столкнувшись с грязной устаревшей веткой, сначала сделайте бэкап и попробуйте разбить её на 3-уровневые слои. Вы не только снизите усталость ревьюеров, но и сами научитесь гораздо лучше контролировать код.