From 086dd1fed77d2b2b4cf833461707228622108552 Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Thu, 23 Apr 2026 22:35:24 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E5=90=88=E5=B9=B6=E6=8F=90=E7=A4=BA=E8=AF=8D=EF=BC=8C?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BA=A4=E4=BA=92=E4=BD=93=E9=AA=8C=E5=B9=B6?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AF=AD=E4=B9=89=E5=AE=A1=E6=9F=A5=E8=83=BD?= =?UTF-8?q?=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 三阶段模型:计划审批(1次) → 自动合并(仅异常中断) → 汇总收尾(1次),减少冗余介入 - 新增语义审查:合并后自动分析代码冗余/过时模式/未集成基础设施/风格不一致 - 完善安全锚点体系:全局锚点+分支级锚点,分级回退机制 - 修复多个逻辑缺陷:stash含未跟踪文件、分支匹配过宽、远端分支拉取重名、语义修复交叉污染等 - 明确提问工具选项和交互方式,消除歧义引导 --- docs/prompts/prompt-smart-merge.md | 245 ++++++++++++++++++++--------- 1 file changed, 172 insertions(+), 73 deletions(-) diff --git a/docs/prompts/prompt-smart-merge.md b/docs/prompts/prompt-smart-merge.md index 2111508..8089a20 100644 --- a/docs/prompts/prompt-smart-merge.md +++ b/docs/prompts/prompt-smart-merge.md @@ -1,120 +1,219 @@ -请对当前项目中所有 `dev*` 分支进行智能合并到目标分支(默认 main),按以下流程执行。 +将所有 `dev*` 分支智能合并到目标分支(默认 main),三阶段执行:计划审批(步骤1-3)→ 自动合并(步骤4)→ 汇总收尾(步骤5)。 -## 约束(全局,不可违反) +## 约束 -- 所有操作(合并、删除)执行前必须用提问工具获得用户确认 -- 冲突文件严禁自主编辑,仅分析方案后交用户选择 -- 全程仅使用 `git merge`,禁止 rebase(rebase 会重写目标分支历史) -- `git add` 仅指定已解决冲突的文件路径,禁止 `git add .`/`git add -A` +- 全程仅使用 `git merge`,禁止 rebase +- `git add` 仅指定明确的文件路径,禁止 `git add .`/`git add -A` - `git reset --hard` 仅配合安全锚点 tag 使用,禁止裸用 -- 禁止自动 `git stash` `git push` +- 冲突文件禁止 AI 自主决定写入内容;用户在冲突面板中选择方案后,AI 按选定方案执行写入,属于授权行为 +- 禁止自动 `git push` +- 合并提交的确认在步骤 3 一次性完成,分支删除的确认在步骤 5 一次性完成;阶段二仅在冲突/异常时中断 +- 语义审查的修复提交独立于合并提交,必要时可单独 revert +- 禁止使用 npm/npx/pnpm,前端命令统一使用 bun -## 1. 环境检查 +## 安全锚点体系 -- `git status` 确认工作区干净,不干净则提示用户处理 -- 确认目标分支,拉取最新:`git pull` -- 列出 dev 分支:`git branch --list 'dev*'`,无则结束 -- 创建全局安全锚点:`git tag pre-merge-backup-{timestamp}`,报告标签名 +| 锚点 | 创建时机 | 用途 | +| ---- | -------- | ---- | +| `pre-merge-backup-{timestamp}` | 步骤 1,合并前目标分支 HEAD | 全局回退点,可撤销所有合并恢复到初始状态 | +| `merge-before-{分支名}-{timestamp}` | 步骤 4 每个分支合并前 | 分支级回退点,撤销单个分支的合并和修复 | -## 2. 分支分析 +全局锚点在步骤 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 分支并行收集: -| 维度 | 内容 | -| ------ | ---------------------------------------------------------------------------------------- | -| 基础 | 分支名、分叉 commit、commit 数/消息、是否推远端、是否已合并(`git branch --merged`) | -| 变更 | 文件列表(`git diff --name-status target...branch`)、所属模块、行数统计 | -| 依赖 | 是否依赖/被依赖其他 dev 分支、是否修改公共文件(共享类型、工具函数、配置) | -| 冲突 | dry-run 预测(逐个串行,因需修改工作区):`git merge --no-commit --no-ff branch` → 收集冲突 → `git merge --abort`;与其他 dev 分支文件重叠 | +| 维度 | 命令/方式 | +| ---- | --------- | +| 基础 | 分支名、`git rev-parse {branch}` 记录 HEAD commit hash、commit 数/消息、`git branch --merged` 判断是否已合并 | +| 变更 | `git diff --name-status {target}...{branch}`、按文件路径推断所属模块(如 `backend/api/` → API)、行数统计 | +| 依赖 | 收集各分支变更文件列表,求交集判断文件重叠;重叠文件涉及公共模块(共享类型、工具函数、配置)的标记为有依赖关系 | +| 公共文件清单 | 基于依赖分析,标记出主分支上的公共文件路径列表,供步骤 4 语义审查使用 | -## 3. 合并顺序 +### 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` -## 4. 逐个合并 +若 `git merge --abort` 失败,执行 `git reset --hard pre-merge-backup-{timestamp}` 恢复到全局安全锚点后继续。若 hard reset 也失败,报告严重错误,终止流程,提示用户手动处理。 -对每个分支重复以下流程: +### 2.3 分析结果汇总 -### 准备 +汇总 2.1 和 2.2 的结果,产出每个分支的:基础信息(含 HEAD hash)、变更范围、依赖关系、冲突预测。供步骤 3 和步骤 4 使用。 -1. 确认工作区干净、当前在目标分支 -2. `git tag merge-before-{分支名}` 创建分支级安全锚点 -3. 向用户确认即将合并的分支及风险 +## 3. 计划(用户确认 — 阶段一唯一介入) -### 执行 +按优先级排序:已合并(跳过) → 公共/基础设施变更(变更文件仅涉及 2.1 标记的公共文件清单中的文件) → 独立模块 → 有依赖的 → 高冲突/跨模块。 -`git merge {分支} --no-ff` +风险评级: +- 低:无冲突且无依赖 +- 中:有冲突或跨模块依赖 +- 高:(冲突文件 ≥ 3 或冲突占比 ≥ 30%) 且 有跨模块依赖 -- 无冲突 → 进入验证 -- 有冲突 → 进入冲突处理 +输出合并计划表(列:分支、状态、模块、文件数、依赖、预估冲突、风险、语义审查),用提问工具让用户确认,选项: -### 冲突处理(三层渐进) +- **确认执行**:按当前计划顺序合并,语义审查设置不变 +- **调整顺序**:用户指定新的分支顺序 +- **排除分支**:用户指定不参与合并的分支名(支持多个) +- **调整语义审查**:用户指定关闭某些分支的审查(等待用户输入分支名) +- **终止**:取消整个流程 -`git diff --name-only --diff-filter=U` 列出冲突文件,然后按以下三层逐步展开: +用户选择"调整顺序""排除分支""调整语义审查"后,重新展示更新后的计划表,再次确认。可多次调整,直到用户选择"确认执行"或"终止"。 -**第一层:冲突概览表** +计划表中"语义审查"列默认全部开启。确认后进入步骤 4,不再逐分支确认。 -向用户展示所有冲突文件的摘要,每文件一行: +## 4. 执行(自动,仅冲突/异常时中断) -| 文件 | 冲突区域 | 冲突类型 | 目标分支改动 | 合并分支改动 | 推荐方案 | -| ---- | -------- | -------- | ------------ | ------------ | -------- | +对计划表中待合并分支依次执行。若全部已合并(无可合并分支),直接跳到步骤 5。 -- 冲突类型:双方修改同一区域 / 一方删除一方修改 / 文件重命名冲突等 -- 改动描述:精简到关键差异(如"新增 rateLimit 字段"而非展示原文) -- 推荐方案:根据分析给出最合理的选项 +### 合并前检查(自动) -用提问工具让用户选择处理方式: -- 批量处理:对推荐方案无异议的文件一键确认 -- 逐个审查:用户指定要详细审查的文件,进入第二层 -- 放弃合并:`git merge --abort`,跳过当前分支,继续下一个 +- `git status` 确认在目标分支且工作区干净 + - 不在目标分支:`git checkout {target}` + - 工作区不干净(非预期状态):报告异常,用提问工具让用户选择:`git stash` 后继续 / 终止 +- `git tag merge-before-{分支名}-{timestamp}` 创建分支级安全锚点(加时间戳防止重复) +- 检查分支 HEAD commit hash 是否与步骤 2.1 记录的一致 + - 不一致:报告分支有新提交,用提问工具让用户选择:重新分析该分支(回到 2.1+2.2 单分支分析,更新分析结果) / 按当前状态继续 / 跳过 -**第二层:单个文件详情(按需)** +### 合并 -仅展示用户指定审查的文件: -- 冲突区域的上下文(前后几行非冲突代码) -- HEAD 侧与分支侧的具体差异(精简 diff,非完整文件内容) -- 方案选项:双保留 / 保留目标(--ours) / 保留分支(--theirs) / 用户编辑 / 放弃合并 +`git merge {分支} --no-ff -m "merge: {分支名} → {target}"` -若用户仍觉信息不足,进入第三层。 +合并可能出现三种结果: -**第三层:原始冲突标记(按需)** +- **无冲突** → 跳到语义审查 +- **有冲突** → 进入冲突处理 +- **合并失败**(分支不存在、工作区锁定等非冲突错误)→ 报告错误,用提问工具让用户选择:跳过继续下一个 / 终止并输出进度 -展示用户指定文件的完整 `<<<<<<<`/`=======`/`>>>>>>>` 原始标记内容。 +### 冲突处理(中断点) -**确认与提交** +`git diff --name-only --diff-filter=U` 列出冲突文件,展示冲突决策面板: -1. 方案全部确定后逐个执行: - - 双保留:AI 生成合并后的文件内容,展示给用户确认后才写入,严禁未经确认直接写入 - - 保留目标/分支:`git checkout --ours/--theirs {file}` - - 用户编辑:等待用户编辑完成后 `git add {file}` -2. 逐个 add 已解决文件:`git add {file}`(禁止 `git add .`) -3. 展示 `git diff --cached --stat`,用户确认后完成提交 +| # | 文件 | 冲突类型 | 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 中的新增代码 | + +输出审查结果表: + +| # | 类别 | 严重程度 | 文件 | 描述 | 建议修复方式 | +| - | ---- | -------- | ---- | ---- | ------------ | + +严重程度:问题(运行时风险或维护负担)/ 建议(不影响功能,影响一致性)。 + +无问题 → 跳到验证。有问题 → 用提问工具让用户选择: + +- **全部修复**:按编号顺序逐个执行 +- **选择修复**:用户输入要修复的编号 +- **跳过**:不处理,进入验证 + +修复执行流程: + +1. 按编号顺序逐个修复,记录每个问题的修改内容(文件路径 + 变更范围) +2. 全部修复完成后,统一执行语法检查:`cd backend && go vet ./...` + `cd frontend && bunx tsc --noEmit` +3. 语法检查通过 → 独立提交:`refactor: 语义审查修复 - {分支名}` +4. 语法检查失败 → 逐个回退修改(按倒序,从最后一个修复开始 `git checkout -- {file}`),每回退一个重新检查,直到检查通过或全部回退 +5. 记录哪些修复成功、哪些被回退,在提交 message 中标注 + +### 验证(自动) - `cd backend && go build ./...` - `cd frontend && bun run build` -- 失败则提供回退选项:`git reset --soft HEAD~1` 或 `git reset --hard merge-before-{分支名}`,由用户决定 +- 成功 → 继续下一个分支 +- 失败(中断点),分级回退: + 1. 若有语义审查修复提交,先尝试 `git revert` 该提交;revert 成功则再次构建验证 + 2. revert 冲突或再次构建仍失败:`git reset --hard merge-before-{分支名}-{timestamp}`(合并提交和修复提交一并回退) + 3. 报告错误信息和当前 HEAD 位置,用提问工具让用户选择: + - **跳过**:放弃当前分支,继续下一个 + - **终止**:停止整个流程,输出当前进度摘要(见下方"终止处理") -### 断点 +终止处理:输出当前进度摘要(已成功合并的分支、已跳过的分支及原因、未处理的分支、当前 HEAD 位置、全局锚点标签名),提示用户可用 `git reset --hard pre-merge-backup-{timestamp}` 全部回退。 -每个分支完成后询问是否继续,暂停则记录进度。 +### 断点(无) -## 5. 清理 +分支间不暂停,自动继续下一个分支。 -### 删除分支 +## 5. 清理(用户确认 — 阶段三唯一介入) -输出合并结果表,逐个确认删除: +输出合并汇总,用提问工具一次性确认所有清理操作: -- 本地:`git branch -d {分支}` -- 远端:独立确认后 `git push origin --delete {分支}` +| 项目 | 内容 | +| ---- | ---- | +| 合并结果 | 成功 / 失败(跳过) / 已合并(跳过) 数量 | +| 冲突统计 | 涉及冲突的文件数(含按推荐方案处理和用户审查处理的) | +| 语义审查 | 各分支发现的问题数和修复数(含修复失败数) | +| 删除本地分支 | 成功合并的分支列表,勾选确认 | +| 删除远端分支 | 有远端对应的分支列表,勾选确认 | +| 安全锚点 | 保留 / 删除 | -### 锚点 +选项:**确认清理**(按勾选执行)/ **调整**(用户指定保留的分支或锚点)/ **跳过清理**(仅保留汇总,不删除任何内容) -询问是否保留安全锚点标签。 +确认后执行清理: -### 总结 +- 本地分支删除:`git branch -d {分支}`(git 安全机制:未完全合并的分支会拒绝删除) +- 远端分支删除:`git push origin --delete {分支}`,失败则报告错误,跳过该远端分支,继续处理其余 +- 锚点处理:按用户选择保留或删除 -输出:目标分支、安全锚点标签、成功/失败/跳过数量、冲突解决文件数、已删除分支、保留分支及原因。 +输出最终总结:目标分支、全局锚点标签、各分支最终状态(已合并+已删除 / 已合并+保留 / 跳过+原因)、冲突和语义审查统计。 + +### 工作区恢复 + +若步骤 1 有 stash:`git stash pop` + +- 无冲突 → 结束 +- 有冲突 → 展示冲突决策面板(同步骤 4 冲突处理流程),用提问工具逐文件选择(选项:保留 stash 内容 / 保留当前内容 / 双保留 / 用户编辑 / 放弃恢复 `git stash drop`)