当巨大PR导致代码审查延误一周时,我所采用的Stacked PR实战迁移法
TuBrief 편집팀
2026년 8월 7일
0
Computing/Software원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
커뮤니티의 다른 글
댓글 (0)
Log in to leave a comment
아직 작성된 글이 없습니다
원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.
Log in to leave a comment
아직 작성된 글이 없습니다
引入AI工具后,代码生成速度变得极快。然而,代码审查的速度却跟不上。根据2024年DORA(DevOps Research and Assessment)报告显示,AI采用率高的团队,PR平均体积增加了154%,而审查耗时却增加了91%之多。结果反而导致发布周期变慢了。如果把1000多行代码扔给别人要求一次性审查,无论谁都会感到眼睛疲劳。为了结束这种混乱局面,我们需要转换为将代码层层堆叠的Stacked PRs(堆叠PR)链式结构。
盲目地裁剪代码会导致编译报错或依赖关系破坏。因此需要明确的标准。单个PR应限制在200行变更代码以内、修改文件少于10个,以便审查人员能在15分钟内完成。一个巨大的功能最多可分为3个子分支链:
严格遵守这一顺序。分支名称也请固定为 feature/<功能名>/stack-<阶段>-<说明> 的形式。将已经缠绕在一起的1000行分支(legacy-giant-branch)拆解为链条的过程非常简单。
首先,更新 main 分支并备份原分支。
`bash
git checkout main
git pull origin main
git checkout legacy-giant-branch
git branch backup/legacy-giant-branch
`
接下来,从 main 检出 Layer 1 分支,并仅通过樱桃拣选(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 |
|---|---|---|---|
| 依赖追踪 | 手动设置分支 Base | 本地 .git 及 GitHub metadata | 独立远程引擎及 Local DB |
| 变基自动化 | 各分支手动操作 | 执行 gh stack rebase 命令 | 更改提交时自动处理下级链条 |
| 学习曲线 | 高(需熟练掌握 Git 原理) | 低(安装 CLI 扩展) | 中(需适应独立专用 UI) |
| 运营稳定性 | 100% 标准 Git 兼容 | 公共预览状态 | 非常高 |
在使用 Stacked PR 时,收到父 PR 的修改请求往往是最痛苦的时刻。因为提交 Hash 发生变化会导致下方挂载的所有子分支全部失效。如果直接执行 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 "BRANCH"
OLD_BASE=CURRENT_PARENT" "OLD_BASE" ]; then
git rebase --onto "OLD_BASE" "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
`
如果将 PR 拆分为 3 个,就会产生 CI 运行器运行次数增加 3 倍的问题。并非所有 PR 都需要运行沉重的 E2E 测试。请配置 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
`
设置组织层面的分支保护规则也是必不可少的:
为了正常运行 Stacked PR,审查人员必须能够看到全局。请在 .github/PULL_REQUEST_TEMPLATE.md 中明确写出堆栈地图。
`markdown
Stack Overview
此 PR 是 Order Refactor Stack 链的一部分。
Current Layer Scope
Dependency Status
`
当底层 PR #101 通过 Squash Merge 进入 main 后,子 PR #102 的 GitHub UI Diff 会突然暴增。这是因为已合并的 #101 的代码全部被捕获为子 PR 的变更事项。由于在 Git Commit Graph 上,Squash 提交的 SHA 和父提交的 SHA 发生了变化,从而导致了该现象。请不要惊慌,按照以下顺序将子分支提交重新放置到 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
`
将巨大的 1000 行 PR 进行拆分,不仅仅是处理 Git 技术的问题,更接近于一项彻底整理团队代码审查方式和整个发布链的工程任务。当你遇到杂乱的遗留分支时,请先建立备份,然后将其切分为 3 个阶段的图层试试看。不仅审查人员的疲劳会减轻,你自己也能更加清晰地掌控代码。