1
0

refactor: 优化提示词文档,增强智能合并与规范审查能力

This commit is contained in:
2026-04-24 18:12:23 +08:00
parent 086dd1fed7
commit 4ddae6be74
5 changed files with 1032 additions and 268 deletions

View File

@@ -1,219 +1,595 @@
将所有 `dev*` 分支智能合并到目标分支(默认 main三阶段执行计划审批步骤1-3→ 自动合并步骤4→ 汇总收尾步骤5
将所有 `dev*` 分支按计划合并到目标分支(默认 `main`),按准备→分析→计划→执行→清理执行;先探测当前仓库的规则、模块边界、验证命令和提交风格,再基于探测结果执行,避免写死仓库结构
## 约束
- 全程仅使用 `git merge`,禁止 rebase
- `git add`指定明确文件路径,禁止 `git add .`/`git add -A`
- `git reset --hard` 仅配合安全锚点 tag 使用,禁止裸用
- 冲突文件禁止 AI 自主决定写入内容用户在冲突面板中选择方案后AI 按选定方案执行写入,属于授权行为
- 禁止自动 `git push`
- 合并提交的确认在步骤 3 一次性完成,分支删除的确认在步骤 5 一次性完成;阶段二仅在冲突/异常时中断
- 语义审查的修复提交独立于合并提交,必要时可单独 revert
- 禁止使用 npm/npx/pnpm前端命令统一使用 bun
- 全程仅使用 `git merge` 完成分支集成,禁止 `rebase`
- `git add`允许明确文件路径,禁止 `git add .``git add -A`
- 不直接使用默认 `git pull`;同步目标分支时仅允许显式策略:`git fetch` + `git merge`,或 `git pull --no-rebase`
- `git reset --hard` 仅允许回到已记录的安全锚点 tag且执行前必须再次确认
- `git stash push``git stash apply``git stash drop``git revert``git branch -d``git push {remote} --delete {branch}` 执行前都必须再次确认
- 禁止自动推送代码;远端分支删除在步骤 5 获得确认后执行
- 冲突文件禁止 AI 自主决定写入内容
- 用户选择 `--ours``--theirs`、保留删除的一侧、保留重命名的一侧等机械方案后AI 可执行对应写入
- 凡涉及“双保留”“重组逻辑”“补写缺失代码”等内容生成,必须逐文件展示最终结果并再次获得确认后写入
- 步骤 3 的“确认执行”仅授权按计划执行正常 merge不授权自动执行 `stash``reset --hard``revert``drop`、删除分支、远端删除、冲突内容重写
- 合并提交与语义审查修复提交必须分离;语义审查修复允许拆成多条独立提交
- 若仓库文档定义了命令、包管理器、提交格式、目录规范,优先遵守文档;若未定义,再根据清单文件、脚本和近期提交历史推断
- 不把当前仓库的路径结构、技术栈、构建命令写死到流程里;一切按探测结果执行
- 信息展示按“概览 → 详情 → 原始数据”分层输出,避免一次性输出全部 diff
## 安全锚点体系
## 记录项
执行中持续维护以下记录,后续所有决策和总结都基于这些记录:
| 记录项 | 内容 |
| ---- | ---- |
| `session_timestamp` | 本次流程唯一时间戳 |
| `target` | 目标分支名 |
| `target_upstream` | 目标分支上游,如 `{remote}/{target}`;无则记为空 |
| `target_remote` | 从 `target_upstream` 解析出的远端名;无上游则优先使用默认远端,否则为空 |
| `repo_rules` | 从 README、CONTRIBUTING、开发文档、脚本、清单文件中识别出的规则 |
| `commit_style` | 仓库现有提交信息风格和默认合并/修复提交模板 |
| `module_map` | 按当前仓库结构推断出的模块边界、公共目录、配置目录、基础设施目录 |
| `validation_commands` | 按模块或作用域归纳出的 lint/build/test 命令 |
| `auto_stashes[]` | 本流程创建的 stash 列表,记录唯一 message、创建时 ref、创建顺序、后续是否恢复/保留 |
| `created_local_tracking_branches[]` | 为远端独有 `dev*` 分支创建的本地跟踪分支 |
| `global_tag` | 全局安全锚点 |
| `branch_tags[]` | 每个待合并分支对应的分支级安全锚点 |
| `analysis[]` | 每个分支的分析快照HEAD hash、提交数、变更文件、依赖、初始冲突预测、风险、语义审查模式 |
| `results[]` | 每个分支的最终状态:已合并、已跳过、已回退、失败原因、修复提交列表、验证结果 |
## 安全锚点
| 锚点 | 创建时机 | 用途 |
| ---- | -------- | ---- |
| `pre-merge-backup-{timestamp}` | 步骤 1,合并前目标分支 HEAD | 全局回退点,可撤销所有合并恢复到初始状态 |
| `merge-before-{分支名}-{timestamp}` | 步骤 4 每个分支合并前 | 分支级回退点,撤销单个分支的合并和修复 |
| `pre-merge-backup-{timestamp}` | 步骤 1 完成目标分支准备后 | 全局回退点,恢复到本轮合并开始前的目标分支状态 |
| `merge-before-{branch}-{timestamp}` | 步骤 4 每个分支正式 merge 前 | 分支级回退点,回退当前分支的合并提交和其后的语义修复提交 |
全局锚点在步骤 4 中不主动使用,仅在用户需要"全部重来"时手动使用`git reset --hard pre-merge-backup-{timestamp}`
除非用户明确要求“全部回退”或“放弃当前分支并回到分支级锚点”,否则不主动使用 `git reset --hard`
## 1. 准备(自动)
## 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}`
### 1.1 仓库规则探测
并行收集当前仓库的规则来源:
- 根目录文档:`README*``CONTRIBUTING*``DEVELOPMENT*``docs/**` 中与开发、构建、测试、提交流程有关的文档
- 常见任务入口:`Makefile``justfile``Taskfile.yml``package.json`、工作区配置、CI 文件、脚本目录
- 常见清单/锁文件:`package-lock.json``pnpm-lock.yaml``yarn.lock``bun.lock*``go.mod``Cargo.toml``pyproject.toml``pom.xml``build.gradle*`
- 近期提交:`git log --oneline -20`
探测目标:
| 项目 | 识别方式 | 记录结果 |
| ---- | -------- | -------- |
| 包管理器/任务入口 | 文档、锁文件、任务文件、脚本 | 记录允许的执行方式和优先级 |
| 模块边界 | 顶层目录、工作区配置、语言清单文件、子项目 README | 记录 `module_map` |
| 公共/基础设施目录 | shared/common/lib/core/config/scripts/ci 等目录和根级配置文件 | 记录到 `module_map` |
| 验证命令 | 文档中的 lint/build/test 命令,或脚本中的标准任务 | 记录到 `validation_commands` |
| 提交风格 | 文档约束优先,否则看近期 `git log` | 记录 `commit_style` |
识别规则:
- 文档和脚本冲突时,以文档为准
- 文档缺失时,以仓库当前可见的任务入口和近期提交习惯为准
- 无法确定时,先在步骤 3 的计划表中展示“待确认规则”,由用户确认
### 1.2 初始化现场
- 执行 `git status --short --branch`,记录当前分支和工作区状态
- 执行 `git remote -v`,记录可用远端
- 用提问工具确认目标分支:`main` / `master` / `develop` / 用户自定义
### 1.3 处理非干净工作区
-`git status --porcelain` 非空,先展示变更文件概览,再用提问工具让用户选择:
- `stash 后继续`
- `终止`
- 用户选择 `stash 后继续` 后,执行 `git stash push --include-untracked -m smart-merge-{timestamp}-precheck-{n}`
- 记录 stash 唯一 message 和创建时 ref 到 `auto_stashes[]`
### 1.4 切换并校验目标分支
- 执行 `git checkout {target}`
- 若失败,使用提问工具让用户选择:
- `重新指定目标分支`
- `终止`
### 1.5 解析上游并同步远端引用
- 执行 `git for-each-ref --format='%(upstream:short)' refs/heads/{target}` 获取 `target_upstream`
- 若存在 `target_upstream`
- 解析 `target_remote`
- 执行 `git fetch {target_remote} --prune`
- 执行 `git rev-list --left-right --count {target}...{target_upstream}` 计算 ahead/behind
- 若不存在 `target_upstream`
- 若仓库存在默认远端,记为 `target_remote`
- 否则 `target_remote` 置空
目标分支同步决策:
| 状态 | 处理 |
| ---- | ---- |
| 无 upstream | 记录后继续,不自动同步 |
| 仅落后 upstream | 用提问工具选择:`快进同步` / `保持当前本地 HEAD` / `终止`;若选同步,执行 `git merge --ff-only {target_upstream}` |
| 仅领先 upstream | 记录后继续,不自动 push |
| 与 upstream 分叉 | 用提问工具选择:`保持当前本地 HEAD` / `终止`;不自动把 upstream merge 进 target |
### 1.6 收集候选分支
- 本地分支:`git branch --list 'dev*'`
-`target_remote` 非空,远端分支:`git branch -r --list '{target_remote}/dev*'`
- 过滤掉 `HEAD ->` 这类符号引用
- 计算“远端存在、本地不存在”的分支列表
对远端独有分支,不直接 `checkout`,改为先展示清单,再用提问工具选择:
- `全部创建本地跟踪分支`
- `选择部分创建`
- `仅使用已有本地分支`
- `终止`
创建本地跟踪分支使用:`git branch --track {local_branch} {remote}/{remote_branch}`
若本地已存在同名分支,使用提问工具逐项选择:
- `使用现有本地分支`
- `改名创建跟踪分支`
- `跳过该远端分支`
所有自动创建的本地跟踪分支都记录到 `created_local_tracking_branches[]`
### 1.7 无候选分支时直接结束
- 若最终没有任何 `dev*` 分支,输出概览:目标分支、工作区状态、探测到的仓库规则、是否创建过 stash、是否创建过本地跟踪分支
- 若本流程已创建 stash进入步骤 5 的“工作区恢复”
- 否则直接结束
### 1.8 创建全局安全锚点
- 执行 `git tag pre-merge-backup-{timestamp}`
- 记录为 `global_tag`
## 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 语义审查使用 |
| 维度 | 命令/方式 | 结果 |
| ---- | --------- | ---- |
| 基础 | `git rev-parse {branch}` | 记录分支 HEAD hash |
| 合并状态 | `git merge-base --is-ancestor {branch} {target}` | 判断该分支是否已完全被目标分支包含 |
| 提交范围 | `git log --oneline {target}..{branch}` | 记录独有提交数和提交消息,推断分支意图 |
| 变更范围 | `git diff --name-status {target}...{branch}` | 记录文件列表、状态、变更集中区域 |
| 行数统计 | `git diff --stat {target}...{branch}` | 估算改动体量 |
| 模块归属 | 按 `module_map` 归类;若未命中则按顶层目录或最近的语言清单文件归类 | 识别受影响模块 |
### 2.2 冲突预测(串行)
模块归类优先级:
`git merge --no-commit --no-ff` 会修改工作区和索引,禁止并行,逐个分支串行执行:
1. 仓库文档明确声明的子项目、包、服务、应用、库
2. 工作区配置或语言清单文件定义的模块边界
3. 顶层目录边界
4. 根级共享文件、配置文件、脚本、CI 文件,统一归为 `shared/config/infra`
`git merge --no-commit --no-ff {branch}``git diff --name-only --diff-filter=U` 收集冲突文件 → `git merge --abort`
常见的 `shared/config/infra` 候选包括但不限于:
`git merge --abort` 失败,执行 `git reset --hard pre-merge-backup-{timestamp}` 恢复到全局安全锚点后继续。若 hard reset 也失败,报告严重错误,终止流程,提示用户手动处理。
- 根目录配置文件、锁文件、工作区文件
- 构建脚本、部署脚本、CI 配置、容器配置、基础设施配置
- 公共库目录、共享类型目录、通用组件目录、公共工具目录
### 2.3 分析结果汇总
### 2.2 依赖判定
汇总 2.1 和 2.2 的结果,产出每个分支的:基础信息(含 HEAD hash、变更范围、依赖关系、冲突预测。供步骤 3 和步骤 4 使用。
依赖同时从 ancestry 和文件重叠两个维度判断:
## 3. 计划(用户确认 — 阶段一唯一介入)
| 维度 | 方法 | 判定规则 |
| ---- | ---- | -------- |
| ancestry 依赖 | `git merge-base --is-ancestor {a} {b}` | 若 `a``b` 的祖先,记为 `b 依赖 a` |
| 文件重叠 | 比较各分支 `git diff --name-only {target}...{branch}` | 同一文件被多个分支修改,记为重叠 |
| 公共文件依赖 | 关注 `shared/config/infra` 范围和公共抽象 | 即使文件数少,也记为高优先级依赖 |
按优先级排序:已合并(跳过) → 公共/基础设施变更(变更文件仅涉及 2.1 标记的公共文件清单中的文件) → 独立模块 → 有依赖的 → 高冲突/跨模块。
为每个分支输出:
- `depends_on[]`:它依赖哪些分支
- `blocks[]`:哪些分支依赖它
- `shared_files[]`:与其他分支重叠的文件
- `common_files[]`:被识别为公共/基础设施的文件
### 2.3 初始冲突预测(串行)
仅对“未合并且有实际差异”的分支串行执行:
1. 执行 `git merge --no-commit --no-ff {branch}`
2. 若工作区进入 merge 状态:
- 执行 `git diff --name-only --diff-filter=U` 记录冲突文件
- 若存在 `MERGE_HEAD`,执行 `git merge --abort`
3. 若命令输出为 `Already up to date`、无 `MERGE_HEAD`、无冲突文件,记为“已包含或无差异”,不执行 `git merge --abort`
4.`git merge --abort` 失败:
- 报告错误和当前状态
- 用提问工具让用户选择:
- `回到全局锚点后继续分析`:执行 `git reset --hard {global_tag}`
- `终止`
- `reset --hard` 失败则终止并提示用户手动处理
### 2.4 风险分级与排序
风险评级:
- 低:无冲突且无依赖
- 中:有冲突或跨模块依赖
- 高:(冲突文件 ≥ 3 或冲突占比 ≥ 30%) 且 有跨模块依赖
输出合并计划表(列:分支、状态、模块、文件数、依赖、预估冲突、风险、语义审查),用提问工具让用户确认,选项:
- 低:无预测冲突、无依赖、单一模块、小体量改动
- 中:存在依赖,或存在预测冲突,或跨两个以上模块,或触及公共文件
- 高:预测冲突文件 `>= 3`,或冲突占改动文件比例 `>= 30%`,或存在 ancestry 依赖且触及公共文件 / 根级配置 / 基础设施文件
- **确认执行**:按当前计划顺序合并,语义审查设置不变
- **调整顺序**:用户指定新的分支顺序
- **排除分支**:用户指定不参与合并的分支名(支持多个)
- **调整语义审查**:用户指定关闭某些分支的审查(等待用户输入分支名)
- **终止**:取消整个流程
初始排序规则:
用户选择"调整顺序""排除分支""调整语义审查"后,重新展示更新后的计划表,再次确认。可多次调整,直到用户选择"确认执行"或"终止"。
1. 已合并 / 无差异(默认跳过,仅展示)
2. 被其他分支依赖的基础分支
3. 仅改公共/基础设施文件的分支
4. 独立、低风险分支
5. 存在依赖或共享文件的分支
6. 高风险、跨模块分支
计划表中"语义审查"列默认全部开启。确认后进入步骤 4不再逐分支确认。
### 2.5 验证命令归纳
## 4. 执行(自动,仅冲突/异常时中断)
根据步骤 1 探测结果,为后续语义修复和构建验证归纳命令:
对计划表中待合并分支依次执行。若全部已合并(无可合并分支),直接跳到步骤 5。
| 作用域 | 优先级 |
| ---- | ---- |
| 模块级 lint/build/test | 优先使用模块文档或模块脚本中声明的命令 |
| 仓库级 lint/build/test | 若模块级命令缺失,使用仓库统一命令 |
| 无现成命令 | 记录为“无法自动验证”,步骤 3 显示给用户 |
### 合并前检查(自动)
归纳原则:
- `git status` 确认在目标分支且工作区干净
- 不在目标分支:`git checkout {target}`
- 工作区不干净(非预期状态):报告异常,用提问工具让用户选择:`git stash` 后继续 / 终止
- `git tag merge-before-{分支名}-{timestamp}` 创建分支级安全锚点(加时间戳防止重复)
- 检查分支 HEAD commit hash 是否与步骤 2.1 记录的一致
- 不一致:报告分支有新提交,用提问工具让用户选择:重新分析该分支(回到 2.1+2.2 单分支分析,更新分析结果) / 按当前状态继续 / 跳过
- 优先使用仓库文档明确写出的命令
- 其次使用标准任务入口中的现有命令
- 再其次使用就近模块的标准脚本
- 不自行发明新的构建或测试命令
### 合并
### 2.6 分析结果汇总
`git merge {分支} --no-ff -m "merge: {分支名} → {target}"`
为每个分支形成分析快照:
合并可能出现三种结果:
| 字段 | 内容 |
| ---- | ---- |
| `status` | 已合并 / 无差异 / 待合并 |
| `head` | 步骤 2 记录的 HEAD hash |
| `modules` | 受影响模块 |
| `files` | 改动文件数 |
| `depends_on` | 依赖分支 |
| `predicted_conflicts` | 初始冲突文件列表 |
| `risk` | 低 / 中 / 高 |
| `semantic_review_mode` | 默认 `仅报告` |
| `validation_scope` | 该分支后续优先使用的验证范围和命令 |
- **无冲突** → 跳到语义审查
- **有冲突** → 进入冲突处理
- **合并失败**(分支不存在、工作区锁定等非冲突错误)→ 报告错误,用提问工具让用户选择:跳过继续下一个 / 终止并输出进度
## 3. 计划(用户确认)
### 冲突处理(中断点)
输出合并计划表,列至少包含:
`git diff --name-only --diff-filter=U` 列出冲突文件,展示冲突决策面板:
| 分支 | 状态 | 模块 | 文件数 | 依赖 | 预测冲突 | 风险 | 语义审查 | 验证命令 |
| ---- | ---- | ---- | ------ | ---- | -------- | ---- | -------- | -------- |
| # | 文件 | 冲突类型 | HEAD 改动 | 分支改动 | 推荐方案 |
| - | ---- | -------- | --------- | -------- | -------- |
默认规则:
- `已合并``无差异` 分支仅展示,不进入执行队列
- `待合并` 分支按步骤 2.4 的排序进入执行队列
- `语义审查` 默认值为 `仅报告`
- 若某分支缺少可自动执行的验证命令,在计划表中明确标记
同时展示仓库级探测结果摘要:
- 识别出的模块边界
- 公共/基础设施范围
- 识别出的验证命令
- 提交风格摘要
- 无法确定、需要用户补充的规则
用提问工具让用户选择:
- **按推荐方案全部处理**:所有文件执行推荐方案
- **审查部分文件**:用户输入要审查的文件编号,未审查文件按推荐方案处理;对审查文件一次性展示上下文 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` 的语义质量。
最终确认后,记录最终执行队列。并明确提示:
- 正常 merge 已获授权
- 冲突内容重写、`stash``revert``reset --hard`、删除分支、远端删除仍需单独确认
## 4. 执行(顺序执行,冲突/异常时中断)
对执行队列中的分支依次处理。若队列为空,直接进入步骤 5。
### 4.1 单分支合并前检查
每个分支开始前都执行以下检查:
1. `git status --short --branch`,确认当前仍在 `{target}`
2. 若不在 `{target}`,执行 `git checkout {target}`;失败则中断并询问
3. 若工作区非干净,展示异常文件,并用提问工具让用户选择:
- `stash 后继续`
- `终止`
4. 若用户选择 `stash 后继续`,执行 `git stash push --include-untracked -m smart-merge-{timestamp}-runtime-{n}`,记录到 `auto_stashes[]`
5. 检查分支是否仍存在;不存在则记录为 `已跳过:分支不存在`
6. 执行 `git rev-parse {branch}`,对比步骤 2 记录的 `head`
7. 若 HEAD 已变化,先对该分支重新执行步骤 2 的单分支分析,再更新计划快照
### 4.2 基于当前 HEAD 的动态复核
步骤 2 的分析基于初始目标分支;每次实际 merge 前都必须基于“当前最新 HEAD”重新复核当前分支
1. 执行 `git diff --name-status HEAD...{branch}`,获取当前变更文件列表
2. 串行执行 `git merge --no-commit --no-ff {branch}` 做实时 dry-run
3. 若进入 merge 状态,收集 `git diff --name-only --diff-filter=U` 冲突文件后执行 `git merge --abort`
4. 若无 `MERGE_HEAD`,按实际结果记为“无冲突”或“已包含 / 无差异”
5. 将实时结果与步骤 3 的计划快照对比
视为“计划漂移”的情况:
- 冲突文件集合发生变化
- 改动文件数变化明显(以 `20%` 为阈值)
- 新出现公共文件 / 根级配置 / 基础设施文件
- 原本 `无冲突` 变成 `有冲突`
- 原本模块级验证命令不再覆盖当前改动范围
若发生计划漂移,用提问工具让用户选择:
- `按更新后的当前结果继续`
- `重新生成剩余分支计划`:对“当前分支 + 尚未处理的剩余分支”重新执行步骤 2再回到步骤 3
- `跳过当前分支`
- `终止`
### 4.3 生成提交模板并创建分支级锚点
先根据 `commit_style` 生成本轮使用的提交模板:
- 若仓库文档明确约束了提交格式,严格遵守
- 若文档未约束,但近期提交风格稳定,沿用仓库现有风格
- 若无法识别,合并提交使用 `chore: merge {branch} into {target}`,语义修复提交使用 `refactor: address post-merge issues in {branch}`
然后:
- 执行 `git tag merge-before-{branch}-{timestamp}`
- 记录到 `branch_tags[]`
### 4.4 正式合并
- 执行正式合并:`git merge --no-ff -m "{merge_commit_message}" {branch}`
正式合并结果分三类:
- 无冲突:进入步骤 4.6
- 有冲突:进入步骤 4.5
- 非冲突错误:展示错误信息,用提问工具选择:`跳过当前分支` / `终止`
### 4.5 冲突处理(中断点)
先执行 `git diff --name-only --diff-filter=U` 获取冲突文件清单,再按文件生成冲突决策面板:
| # | 文件 | 冲突类型 | HEAD 改动摘要 | 分支改动摘要 | 可批量机械处理 | 推荐方案 |
| - | ---- | -------- | ------------- | ------------ | -------------- | -------- |
推荐方案规则:
- 仅当解决方案明确等价于 `--ours``--theirs`、保留删除的一侧、保留重命名的一侧时,才允许给出“可批量机械处理”的推荐
- 只要需要合并两边逻辑、补全缺失分支、重排代码顺序、解决同一函数 / 类 / 配置段双改,就标记为 `需逐文件确认`
- `需逐文件确认` 的文件不能被“全部按推荐方案”一键处理
用提问工具让用户选择:
- `处理全部机械型冲突`
- `审查部分文件`
- `放弃当前合并`
若用户选择 `审查部分文件`,先让用户输入文件编号,再对这些文件逐个展示:
- 上下文 diff
- 原始冲突块 `<<<<<<<` / `=======` / `>>>>>>>`
- 当前建议与风险说明
逐文件可选方案:
- `保留目标 (--ours)`
- `保留分支 (--theirs)`
- `AI 起草双保留结果`
- `用户手动编辑`
执行规则:
- `--ours` / `--theirs`:执行 `git checkout --ours/--theirs {file}`
- `AI 起草双保留结果`
- 先生成完整最终结果或统一 diff
- 说明具体合并逻辑
- 再次用提问工具确认后写入文件
- `用户手动编辑`:告知文件路径,等待用户回复“完成”后再执行 `git add {file}`
- 所有冲突文件都必须逐文件 `git add {file}`
- 执行 `git diff --name-only --diff-filter=U`,确认已无未解决冲突
- 再执行 `git commit --no-edit`
若用户选择 `放弃当前合并`
- 用提问工具确认是否执行 `git merge --abort`
-`abort` 成功,记录当前分支为 `已跳过:用户放弃合并`
-`abort` 失败,再用提问工具确认是否执行 `git reset --hard merge-before-{branch}-{timestamp}` 回到分支级锚点
### 4.6 语义审查
语义审查基于 `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 | `git diff merge-before-{branch}-{timestamp}..HEAD` | 查看本次实际引入的改动 |
| 分支意图 | 步骤 2 的 commit 消息 | 推断业务目的 |
| 主干近期趋势 | `git log --oneline {target} -20` 及相关 diff | 识别近期重构、迁移、废弃方向 |
| 公共文件现状 | 步骤 2 标记的 `common_files[]` | 判断是否重复造轮子或遗漏基础设施 |
| 仓库规则 | `repo_rules``module_map``validation_commands` | 判断是否偏离当前仓库约定 |
审查维度:
| 维度 | 检测方法 |
| ---- | -------- |
| 代码冗余 | 提取合并 diff 中新增函数签名和 import与公共文件清单中的已有实现做语义匹配 |
| 过时模式 | 从主分支近期 commit message 中筛选含 refactor/deprecate/remove/migrate 的提交,对比这些提交的 diff 提取被替换的 API检查合并 diff 中是否仍在使用 |
| 未集成基础设施 | 从主分支近期 diff 中识别新增的中间件/工具/配置项,检查合并 diff 新增的代码是否缺少对应引用 |
| 风格不一致 | 对比主分支近期代码的命名惯例、文件组织、注释风格与合并 diff 中的新增代码 |
| 维度 | 检查点 |
| ---- | ------ |
| 代码冗余 | 新增函数、组件、类型、工具、配置是否已在仓库公共位置存在等价实现 |
| 过时模式 | 是否继续使用近期已迁移、废弃、替换的 API、脚本、配置项、目录模式 |
| 基础设施遗漏 | 新代码是否绕过既有公共抽象、统一错误处理、统一日志、统一配置、统一数据访问、统一请求封装等既有基础设施 |
| 风格不一致 | 命名、文件组织、测试组织、错误处理、注释风格是否偏离当前主干 |
| 模块边界破坏 | 是否把本应落在公共层、共享层、基础设施层的逻辑塞进业务分支目录 |
输出审查结果表:
| # | 类别 | 严重程度 | 文件 | 描述 | 建议修复方式 |
| - | ---- | -------- | ---- | ---- | ------------ |
严重程度:问题(运行时风险或维护负担)/ 建议(不影响功能,影响一致性)。
严重程度仅分两类
无问题 → 跳到验证。有问题 → 用提问工具让用户选择:
- `问题`:有运行时风险、明显架构偏差或维护成本高
- `建议`:功能可用,但与主干一致性较差
- **全部修复**:按编号顺序逐个执行
- **选择修复**:用户输入要修复的编号
- **跳过**:不处理,进入验证
按计划中的 `semantic_review_mode` 处理:
修复执行流程:
- `关闭`:跳过语义审查
- `仅报告`:展示结果后直接进入步骤 4.7
- `报告并修复`:展示结果后,用提问工具选择:`全部修复` / `选择修复` / `跳过`
1. 按编号顺序逐个修复,记录每个问题的修改内容(文件路径 + 变更范围)
2. 全部修复完成后,统一执行语法检查:`cd backend && go vet ./...` + `cd frontend && bunx tsc --noEmit`
3. 语法检查通过 → 独立提交:`refactor: 语义审查修复 - {分支名}`
4. 语法检查失败 → 逐个回退修改(按倒序,从最后一个修复开始 `git checkout -- {file}`),每回退一个重新检查,直到检查通过或全部回退
5. 记录哪些修复成功、哪些被回退,在提交 message 中标注
修复执行规则:
### 验证(自动)
1. 每个问题编号视为一个独立修复单元
2. 一次只处理一个编号,避免回退时互相污染
3. 每个修复单元只修改其必要文件,保持最小变更
4. 修复完成后,按 `validation_commands` 和当前改动作用域执行最小充分检查:
- `cd backend && go build ./...`
- `cd frontend && bun run build`
- 成功 → 继续下一个分支
- 失败(中断点),分级回退:
1. 若有语义审查修复提交,先尝试 `git revert` 该提交revert 成功则再次构建验证
2. revert 冲突或再次构建仍失败:`git reset --hard merge-before-{分支名}-{timestamp}`(合并提交和修复提交一并回退)
3. 报告错误信息和当前 HEAD 位置,用提问工具让用户选择:
- **跳过**:放弃当前分支,继续下一个
- **终止**:停止整个流程,输出当前进度摘要(见下方"终止处理"
| 作用域 | 检查策略 |
| ---- | -------- |
| 仅单模块 | 优先执行该模块的 lint 或等价静态检查 |
| 多模块 | 执行覆盖这些模块的仓库级检查或组合检查 |
| 触及 `shared/config/infra` | 执行受影响范围内最严格的可用检查 |
| 无自动检查命令 | 记录为“未自动验证”,并在结果中明确说明 |
终止处理:输出当前进度摘要(已成功合并的分支、已跳过的分支及原因、未处理的分支、当前 HEAD 位置、全局锚点标签名),提示用户可用 `git reset --hard pre-merge-backup-{timestamp}` 全部回退。
5. 若检查通过,立即提交独立修复 commitmessage 遵循 `commit_style`
6. 若检查失败,只回退当前修复单元的未提交修改:`git restore --staged --worktree --source=HEAD -- {files}`
7. 记录该编号为 `修复失败并已回退`,继续处理下一个编号
### 断点(无)
### 4.7 构建验证
分支间不暂停,自动继续下一个分支。
根据当前分支实际引入的改动范围,从 `validation_commands` 中选择最小充分的构建 / 测试 / 检查命令:
## 5. 清理(用户确认 — 阶段三唯一介入)
| 改动范围 | 验证策略 |
| -------- | -------- |
| 单模块业务改动 | 优先运行该模块的 build / test / lint 组合 |
| 多模块改动 | 运行覆盖这些模块的聚合命令 |
| 触及共享层、配置、基础设施 | 优先运行仓库级验证或覆盖共享层的更高等级验证 |
| 仓库没有可自动执行命令 | 记录为“无法自动验证”,并向用户说明 |
输出合并汇总,用提问工具一次性确认所有清理操作
构建成功
- 记录当前分支为 `已合并`
- 记录冲突处理方式、语义审查结果、修复提交列表、实际执行的验证命令
- 继续下一个分支
构建失败:
1. 展示失败命令和错误摘要
2. 若当前分支存在语义修复提交,用提问工具让用户选择:
- `依次 revert 当前分支的语义修复提交后重试验证`
- `放弃当前分支并回到分支级锚点`
- `终止`
3. 若用户选择 revert
- 按提交时间倒序执行 `git revert --no-edit {commit}`
- 每 revert 一条后重试验证,直到通过或全部 revert 完成
- 若 revert 冲突,立即中断并询问:`回到分支级锚点` / `保留冲突现场并终止`
4. 若无语义修复提交,或全部 revert 后验证仍失败,用提问工具让用户选择:
- `git reset --hard merge-before-{branch}-{timestamp}` 放弃当前分支
- `终止并保留当前现场`
5. 若用户确认回到分支级锚点,记录当前分支为 `已跳过:验证失败并回退`
## 5. 清理(用户确认)
所有分支处理完成后,输出汇总表:
| 项目 | 内容 |
| ---- | ---- |
| 合并结果 | 成功 / 失败(跳过) / 已合并(跳过) 数量 |
| 冲突统计 | 涉及冲突的文件数(含按推荐方案处理和用户审查处理的) |
| 语义审查 | 各分支发现的问题数和修复数(含修复失败数) |
| 删除本地分支 | 成功合并的分支列表,勾选确认 |
| 删除远端分支 | 有远端对应的分支列表,勾选确认 |
| 安全锚点 | 保留 / 删除 |
| 目标分支 | `{target}` |
| 当前 HEAD | 当前提交 hash |
| 合并结果 | 成功 / 跳过 / 已合并 / 无差异 数量 |
| 冲突统计 | 冲突分支数、冲突文件数、机械处理数、逐文件确认 |
| 语义审查 | 每个分支的问题数、建议数、修复成功数、修复失败数 |
| 实际验证 | 每个分支实际执行了哪些验证命令,哪些未验证 |
| 已创建资源 | `global_tag``branch_tags[]``auto_stashes[]``created_local_tracking_branches[]` |
| 候选删除 | 可删除的本地分支、远端分支、可删除 tag |
选项:**确认清理**(按勾选执行)/ **调整**(用户指定保留的分支或锚点)/ **跳过清理**(仅保留汇总,不删除任何内容)
用提问工具一次性确认清理策略:
确认后执行清理:
- `确认清理`
- `调整清理范围`
- `跳过清理`
- 本地分支删除:`git branch -d {分支}`git 安全机制:未完全合并的分支会拒绝删除)
- 远端分支删除:`git push origin --delete {分支}`,失败则报告错误,跳过该远端分支,继续处理其余
- 锚点处理:按用户选择保留或删除
清理项包括:
输出最终总结:目标分支、全局锚点标签、各分支最终状态(已合并+已删除 / 已合并+保留 / 跳过+原因)、冲突和语义审查统计。
- 删除已成功合并的本地分支:`git branch -d {branch}`
- 删除已成功合并且用户确认的远端分支:`git push {remote} --delete {branch}`
- 删除用户明确不再保留的安全锚点 tag
- 删除本流程仅为分析/合并而创建、且最终不需要保留的本地跟踪分支
远端分支删除规则:
- 优先删除该分支自己的 upstream remote
- 若分支无 upstream但来自 `target_remote`,则删除 `target_remote/{branch}`
- 删除失败只记录错误,不影响其余清理项
### 工作区恢复
步骤 1 有 stash`git stash pop`
`auto_stashes[]` 非空,用提问工具让用户选择:
- 无冲突 → 结束
- 有冲突 → 展示冲突决策面板(同步骤 4 冲突处理流程),用提问工具逐文件选择(选项:保留 stash 内容 / 保留当前内容 / 双保留 / 用户编辑 / 放弃恢复 `git stash drop`
- `按顺序恢复全部 stash`
- `查看 stash 列表后选择恢复`
- `暂不恢复,保留 stash`
恢复时按后进先出顺序处理。由于 `stash@{n}` 会随列表变化而漂移,先根据已记录的唯一 message 在 `git stash list` 中定位当前 ref再对该 stash 执行 `git stash apply {ref}`,不直接 `pop`
1. `apply` 成功后,再询问是否 `git stash drop {ref}`
2.`apply` 冲突,展示 stash 冲突决策面板,逐文件选择:
- `保留 stash 内容`
- `保留当前内容`
- `AI 起草双保留结果`
- `用户手动编辑`
- `放弃恢复该 stash`
3. 冲突解决完成后,再询问是否 `drop` 对应 stash
输出最终总结:目标分支、当前 HEAD、探测到的仓库规则摘要、保留的锚点、各分支最终状态、未删除的远端分支、stash 恢复结果。
## 终止处理
任一步骤选择 `终止` 时,输出终止摘要:
| 项目 | 内容 |
| ---- | ---- |
| 当前步骤 | 准备 / 分析 / 计划 / 执行 / 清理 |
| 当前 HEAD | 当前提交 hash |
| 已完成分支 | 成功合并的分支 |
| 已跳过分支 | 分支及原因 |
| 未处理分支 | 剩余执行队列 |
| 已创建资源 | `global_tag``branch_tags[]``auto_stashes[]``created_local_tracking_branches[]` |
| 已识别规则 | `repo_rules``module_map``validation_commands` |
若终止时存在活动 merge 状态,再用提问工具让用户选择:
- `执行 git merge --abort 并结束`
- `回到当前分支级锚点并结束`
- `保留当前冲突现场,交给用户手动处理`
若终止时不存在活动 merge 状态,不自动变更现场;仅提示用户:
- 全部回退可使用 `git reset --hard {global_tag}`
- 当前分支级回退可使用 `git reset --hard merge-before-{branch}-{timestamp}`
- 本流程创建的 stash 和本地跟踪分支仍保留,是否恢复/删除由步骤 5 或用户后续手动决定