- 三阶段模型:计划审批(1次) → 自动合并(仅异常中断) → 汇总收尾(1次),减少冗余介入 - 新增语义审查:合并后自动分析代码冗余/过时模式/未集成基础设施/风格不一致 - 完善安全锚点体系:全局锚点+分支级锚点,分级回退机制 - 修复多个逻辑缺陷:stash含未跟踪文件、分支匹配过宽、远端分支拉取重名、语义修复交叉污染等 - 明确提问工具选项和交互方式,消除歧义引导
12 KiB
将所有 dev* 分支智能合并到目标分支(默认 main),三阶段执行:计划审批(步骤1-3)→ 自动合并(步骤4)→ 汇总收尾(步骤5)。
约束
- 全程仅使用
git merge,禁止 rebase git add仅指定明确的文件路径,禁止git add ./git add -Agit reset --hard仅配合安全锚点 tag 使用,禁止裸用- 冲突文件禁止 AI 自主决定写入内容;用户在冲突面板中选择方案后,AI 按选定方案执行写入,属于授权行为
- 禁止自动
git push - 合并提交的确认在步骤 3 一次性完成,分支删除的确认在步骤 5 一次性完成;阶段二仅在冲突/异常时中断
- 语义审查的修复提交独立于合并提交,必要时可单独 revert
- 禁止使用 npm/npx/pnpm,前端命令统一使用 bun
安全锚点体系
| 锚点 | 创建时机 | 用途 |
|---|---|---|
pre-merge-backup-{timestamp} |
步骤 1,合并前目标分支 HEAD | 全局回退点,可撤销所有合并恢复到初始状态 |
merge-before-{分支名}-{timestamp} |
步骤 4 每个分支合并前 | 分支级回退点,撤销单个分支的合并和修复 |
全局锚点在步骤 4 中不主动使用,仅在用户需要"全部重来"时手动使用:git reset --hard pre-merge-backup-{timestamp}。
1. 准备(自动)
git status检查工作区- 不干净:
git stash push --include-untracked -m merge-auto-stash-{timestamp},记录 stash 引用,步骤 5 末尾恢复
- 不干净:
- 默认目标分支 main,用提问工具让用户确认或指定其他分支(选项:
main/develop/ 用户自定义,用户自定义时等待输入分支名) git checkout {target}- 失败(分支不存在):用提问工具让用户选择其他分支或终止
git pull- 失败:报告错误,用提问工具让用户选择:强制拉取(
git pull --rebase不允许,仅git fetch+ 手动合并)/ 终止
- 失败:报告错误,用提问工具让用户选择:强制拉取(
git fetch --all拉取远端引用- 列出 dev 分支(本地 + 远端分开):
- 本地:
git branch --list 'dev*' - 远端仅存在:
git branch -r --list 'origin/dev*',对远端独有的分支执行git checkout -b {分支名} origin/{分支名}拉取到本地- 若本地已存在同名分支:报告冲突,用提问工具让用户选择:使用本地版本 / 重命名后拉取 / 跳过
- 无任何 dev 分支则结束
- 本地:
- 创建全局安全锚点:
git tag pre-merge-backup-{timestamp}
2. 分析
2.1 信息收集(并行)
对每个 dev 分支并行收集:
| 维度 | 命令/方式 |
|---|---|
| 基础 | 分支名、git rev-parse {branch} 记录 HEAD commit hash、commit 数/消息、git branch --merged 判断是否已合并 |
| 变更 | git diff --name-status {target}...{branch}、按文件路径推断所属模块(如 backend/api/ → API)、行数统计 |
| 依赖 | 收集各分支变更文件列表,求交集判断文件重叠;重叠文件涉及公共模块(共享类型、工具函数、配置)的标记为有依赖关系 |
| 公共文件清单 | 基于依赖分析,标记出主分支上的公共文件路径列表,供步骤 4 语义审查使用 |
2.2 冲突预测(串行)
git merge --no-commit --no-ff 会修改工作区和索引,禁止并行,逐个分支串行执行:
git merge --no-commit --no-ff {branch} → git diff --name-only --diff-filter=U 收集冲突文件 → git merge --abort
若 git merge --abort 失败,执行 git reset --hard pre-merge-backup-{timestamp} 恢复到全局安全锚点后继续。若 hard reset 也失败,报告严重错误,终止流程,提示用户手动处理。
2.3 分析结果汇总
汇总 2.1 和 2.2 的结果,产出每个分支的:基础信息(含 HEAD hash)、变更范围、依赖关系、冲突预测。供步骤 3 和步骤 4 使用。
3. 计划(用户确认 — 阶段一唯一介入)
按优先级排序:已合并(跳过) → 公共/基础设施变更(变更文件仅涉及 2.1 标记的公共文件清单中的文件) → 独立模块 → 有依赖的 → 高冲突/跨模块。
风险评级:
- 低:无冲突且无依赖
- 中:有冲突或跨模块依赖
- 高:(冲突文件 ≥ 3 或冲突占比 ≥ 30%) 且 有跨模块依赖
输出合并计划表(列:分支、状态、模块、文件数、依赖、预估冲突、风险、语义审查),用提问工具让用户确认,选项:
- 确认执行:按当前计划顺序合并,语义审查设置不变
- 调整顺序:用户指定新的分支顺序
- 排除分支:用户指定不参与合并的分支名(支持多个)
- 调整语义审查:用户指定关闭某些分支的审查(等待用户输入分支名)
- 终止:取消整个流程
用户选择"调整顺序""排除分支""调整语义审查"后,重新展示更新后的计划表,再次确认。可多次调整,直到用户选择"确认执行"或"终止"。
计划表中"语义审查"列默认全部开启。确认后进入步骤 4,不再逐分支确认。
4. 执行(自动,仅冲突/异常时中断)
对计划表中待合并分支依次执行。若全部已合并(无可合并分支),直接跳到步骤 5。
合并前检查(自动)
git status确认在目标分支且工作区干净- 不在目标分支:
git checkout {target} - 工作区不干净(非预期状态):报告异常,用提问工具让用户选择:
git stash后继续 / 终止
- 不在目标分支:
git tag merge-before-{分支名}-{timestamp}创建分支级安全锚点(加时间戳防止重复)- 检查分支 HEAD commit hash 是否与步骤 2.1 记录的一致
- 不一致:报告分支有新提交,用提问工具让用户选择:重新分析该分支(回到 2.1+2.2 单分支分析,更新分析结果) / 按当前状态继续 / 跳过
合并
git merge {分支} --no-ff -m "merge: {分支名} → {target}"
合并可能出现三种结果:
- 无冲突 → 跳到语义审查
- 有冲突 → 进入冲突处理
- 合并失败(分支不存在、工作区锁定等非冲突错误)→ 报告错误,用提问工具让用户选择:跳过继续下一个 / 终止并输出进度
冲突处理(中断点)
git diff --name-only --diff-filter=U 列出冲突文件,展示冲突决策面板:
| # | 文件 | 冲突类型 | HEAD 改动 | 分支改动 | 推荐方案 |
|---|
用提问工具让用户选择:
- 按推荐方案全部处理:所有文件执行推荐方案
- 审查部分文件:用户输入要审查的文件编号,未审查文件按推荐方案处理;对审查文件一次性展示上下文 diff +
<<<<<<</=======/>>>>>>>原始标记,逐文件用提问工具选择方案(选项:双保留 / 保留目标(--ours) / 保留分支(--theirs) / 用户编辑) - 放弃合并:
git merge --abort,跳过当前分支,继续下一个
方案确定后执行:
- 双保留:AI 综合两侧变更生成合并后的文件内容,展示变更摘要(改了哪些函数、新增了哪些逻辑),用户确认后写入
- --ours/--theirs:
git checkout --ours/--theirs {file} - 用户编辑:告知用户文件路径,等待用户回复"完成"后
git add {file} - 逐文件
git add {file} git commit --no-edit完成合并提交(使用合并时指定的 commit message)
语义审查(自动,计划中开启时执行)
合并提交后,分析 git diff merge-before-{branch}-{timestamp}..HEAD 的语义质量。
辅助数据源:
| 数据 | 获取方式 | 用途 |
|---|---|---|
| 合并 diff | git diff merge-before-{branch}-{timestamp}..HEAD |
本次合入的所有变更 |
| 主分支趋势 | git log merge-before-{branch}-{timestamp} --oneline -20 + 对应 diff |
主分支的规范和架构方向 |
| 分支意图 | 步骤 2.1 已收集的 commit 消息 | 推断开发分支的业务目的 |
| 公共文件现状 | 步骤 2.1 标记的公共文件清单,读取这些文件在主分支上的当前内容 | 判断冗余实现 |
审查维度:
| 维度 | 检测方法 |
|---|---|
| 代码冗余 | 提取合并 diff 中新增的函数签名和 import,与公共文件清单中的已有实现做语义匹配 |
| 过时模式 | 从主分支近期 commit message 中筛选含 refactor/deprecate/remove/migrate 的提交,对比这些提交的 diff 提取被替换的 API,检查合并 diff 中是否仍在使用 |
| 未集成基础设施 | 从主分支近期 diff 中识别新增的中间件/工具/配置项,检查合并 diff 新增的代码是否缺少对应引用 |
| 风格不一致 | 对比主分支近期代码的命名惯例、文件组织、注释风格与合并 diff 中的新增代码 |
输出审查结果表:
| # | 类别 | 严重程度 | 文件 | 描述 | 建议修复方式 |
|---|
严重程度:问题(运行时风险或维护负担)/ 建议(不影响功能,影响一致性)。
无问题 → 跳到验证。有问题 → 用提问工具让用户选择:
- 全部修复:按编号顺序逐个执行
- 选择修复:用户输入要修复的编号
- 跳过:不处理,进入验证
修复执行流程:
- 按编号顺序逐个修复,记录每个问题的修改内容(文件路径 + 变更范围)
- 全部修复完成后,统一执行语法检查:
cd backend && go vet ./...+cd frontend && bunx tsc --noEmit - 语法检查通过 → 独立提交:
refactor: 语义审查修复 - {分支名} - 语法检查失败 → 逐个回退修改(按倒序,从最后一个修复开始
git checkout -- {file}),每回退一个重新检查,直到检查通过或全部回退 - 记录哪些修复成功、哪些被回退,在提交 message 中标注
验证(自动)
cd backend && go build ./...cd frontend && bun run build- 成功 → 继续下一个分支
- 失败(中断点),分级回退:
- 若有语义审查修复提交,先尝试
git revert该提交;revert 成功则再次构建验证 - revert 冲突或再次构建仍失败:
git reset --hard merge-before-{分支名}-{timestamp}(合并提交和修复提交一并回退) - 报告错误信息和当前 HEAD 位置,用提问工具让用户选择:
- 跳过:放弃当前分支,继续下一个
- 终止:停止整个流程,输出当前进度摘要(见下方"终止处理")
- 若有语义审查修复提交,先尝试
终止处理:输出当前进度摘要(已成功合并的分支、已跳过的分支及原因、未处理的分支、当前 HEAD 位置、全局锚点标签名),提示用户可用 git reset --hard pre-merge-backup-{timestamp} 全部回退。
断点(无)
分支间不暂停,自动继续下一个分支。
5. 清理(用户确认 — 阶段三唯一介入)
输出合并汇总,用提问工具一次性确认所有清理操作:
| 项目 | 内容 |
|---|---|
| 合并结果 | 成功 / 失败(跳过) / 已合并(跳过) 数量 |
| 冲突统计 | 涉及冲突的文件数(含按推荐方案处理和用户审查处理的) |
| 语义审查 | 各分支发现的问题数和修复数(含修复失败数) |
| 删除本地分支 | 成功合并的分支列表,勾选确认 |
| 删除远端分支 | 有远端对应的分支列表,勾选确认 |
| 安全锚点 | 保留 / 删除 |
选项:确认清理(按勾选执行)/ 调整(用户指定保留的分支或锚点)/ 跳过清理(仅保留汇总,不删除任何内容)
确认后执行清理:
- 本地分支删除:
git branch -d {分支}(git 安全机制:未完全合并的分支会拒绝删除) - 远端分支删除:
git push origin --delete {分支},失败则报告错误,跳过该远端分支,继续处理其余 - 锚点处理:按用户选择保留或删除
输出最终总结:目标分支、全局锚点标签、各分支最终状态(已合并+已删除 / 已合并+保留 / 跳过+原因)、冲突和语义审查统计。
工作区恢复
若步骤 1 有 stash:git stash pop
- 无冲突 → 结束
- 有冲突 → 展示冲突决策面板(同步骤 4 冲突处理流程),用提问工具逐文件选择(选项:保留 stash 内容 / 保留当前内容 / 双保留 / 用户编辑 / 放弃恢复
git stash drop)