
过去这一年我最大的感受不是“AI 写代码有多快”而是“我们代码仓库里的 Merge 动作变得越来越沉重”。AI 编程工具——不管是 GitHub Copilot、Cursor还是我自费订阅的 Codex 这类付费 AI 编程软件——确实把“生成代码”的门槛按到了地板砖以下你只要会说人话把需求描述得稍微清楚一点一分钟内就能拿到一段像模像样的函数甚至是一个完整服务。可奇怪的是仓库里 Merge 按钮被按下的频率反而变低了或者说按下去之前犹豫的时间变长了。为什么因为门槛降低的是“写出代码”而 Merge 意味着你要对这段代码负责。写代码的爽感是即时的Merge 的代价却是长期的。这篇文章我想好好聊聊这个现象AI 编程狂飙之后真正卡住我们的不是写不出来而是不敢合、合不动、合完心里没底。我会把技术层面的冲突处理、工具选择、流程设计以及心理层面的信任问题一次说透。1. AI 编程狂飙写代码的门槛确实接近零了1.1 我一天“写”出了以前一周的代码量先说个真实场景。前阵子我接到一个任务把一套内部日志系统从单体脚本改造成分批处理的管道服务。放在以前这个活至少要排一周——要理清数据格式、写解析器、设计线程池、处理失败重试还要补单元测试。这次我直接打开 Cursor把需求拆成五段提示词一段一段喂进去包括“输入格式如下”“输出要符合现有日志规范”“失败重试用指数退避”。AI 在半小时内给出了全部核心代码我复制进项目改了几处类型不匹配跑通了本地测试。这个效率确实吓人。代码库里的产出速度肉眼可见地翻了几倍团队里几个刚转行的小伙子甚至能借助 AI 独立完成从前需要两年经验才能扛住的模块。但问题也从这一刻开始冒头了代码是有了可仓库里的冲突、回退、返工也同步变多。我检查了一下最近的 PR 数据AI 辅助产出的 PR 平均 diff 行数是人工手写的三倍左右而“引入新问题后被打回”的比例也明显上升。写代码的瓶颈确实消失了但瓶颈没有消失它只是往后移动移动到了 Merge 这一步。1.2 “生成”不等于“完成”AI 编程的真实工作流现在做开发的工作流已经不是“需求 - 写代码 - 提交”而是“需求 - 写提示词ai 编程提示词成了新技能- 生成代码 - 集成 - 审查 - 合并”。真正花时间的环节从“写”转移到了“验证和集成”。说白了AI 帮你把代码生产出来了但代码要融入现有代码库要经过编译、测试、静态检查、同行 review最后合入主干——这后面每一步都在替 AI 的产出“验货”。我试过最顺的一次是让 AI 生成一个完全独立的工具函数不依赖任何现有模块从生成到合入只花了二十分钟。但一旦涉及修改老代码、牵动多个调用方或者跟别人的分支并行改动同一个文件事情就完全不是那个味道了。生成是 AI 的合并是你自己的——这句话我最近常跟团队说。AI 生成的每一行代码最后都是签着你的名字进主干的出了问题Code Review 不会去找 AI 问责只会来找你。2. 为什么 Merge 成了新的“卡脖子”环节2.1 代码写得快合并却变慢了这是个非常反直觉的现象整体工作量明明在减少Merge 的耗时却翻了倍。我统计过自己最近两个月的数据一个中等规模的 AI 辅助功能从“代码生成完成”到“成功合入主干”平均要花掉原本手工开发 40% 的时间。而纯手工时代这个比例连 20% 都不到。原因其实不复杂。第一AI 生成的代码“块头大”。它倾向于一次性丢出一个完整模块而不是像人那样拆成几个语义清晰的 commit。第二AI 喜欢“顺手整理”生成代码时经常把文件里的 import 顺序重排、把双引号改成单引号、把函数声明顺序打乱——这些不是功能变化但都会在 diff 里制造大量噪音。第三AI 不擅长做“最小变更”。你跟它说“给这个函数加个边界判断”它往往会把整个函数重写一遍逻辑对了没错但本来 5 行的 diff 变成了 80 行。这直接导致了一个后果Code Review 的负担爆炸。人眼逐行审阅 80 行里只有 5 行真正变化的代码效率极低而且很容易漏掉 AI 偷偷改出来的行为差异。Merge 前必须 reviewreview 变慢Merge 自然就慢了。2.2 不敢 Merge 的本质信任与责任问题技术层面的“慢”还不是最可怕的最可怕的是心理层面的“不敢”。我自己就有这种体验面对一大段 AI 生成的代码运行起来好像没问题测试也过了但我就是不敢点 Merge。因为我不知道这段代码的“意图”。人工写的代码我知道作者在想什么我知道他为什么这么命名、为什么这么兜底AI 写的代码我看到的只是一堆“看起来合理”的逻辑它为什么加这个空指针判断为什么 catch 了这个异常却不处理这些问号在 review 阶段根本没办法验证只能靠猜。这就是信任问题。Git 的 Merge 操作在语义上代表“我确认这个改动可以进入主干”它本质上是一个承诺。而人很难对自己不理解的东西做出承诺。再加上万一合出生产事故责任是实打实落到你头上的——AI 不会替你背锅。我之前有个同事用 AI 生成了一段处理货币格式化的小工具本地测得好好的合入主干后在特定语言环境下直接炸了。事后排查发现AI 用了一个只支持部分 locale 的 API而这个 API 在他的机器上跑不出来边界问题。这个教训过后他每次 review AI 代码都带着“先怀疑后相信”的劲头。我觉得这种感觉会越来越普遍不是 AI 能力不行而是人类审查者天然对自己没参与过的东西缺乏安全感。3. 核心细节AI 时代的 Merge 困境拆解3.1 冲突从哪来AI 的“改写习惯”与人不一样Merge 冲突的本质是两个分支改了同一处代码。人工时代大家改代码都比较克制有冲突也往往是真正正交的业务改动。AI 时代不一样AI 的“改写习惯”导致冲突概率显著上升。具体来说有三种典型场景整块重写型你和 AI 分别在两个分支上改同一个函数AI 不会像人那样只加一行参数校验它会把整个函数体重新生成。等到合并时git 面对的是两个完全不同的函数版本冲突范围从“几行”扩大到“整个函数”。格式扰动型AI 的生成模型对代码风格有“自己的审美”它可能把双引号改成模板字符串把 for 循环改成 forEach甚至调整文件头注释的格式。这些改动和你的功能改动叠在一起在合并时产生大量本不该存在的冲突。重复实现型AI 不读全局代码你让它加一个“日期格式化”的功能它可能不知道项目里已经存在一个formatDate工具函数于是又生成一个功能几乎一样的formatTime。两个分支都这么干合并时就会出现“同一职责的重复代码”冲突的不是文本而是设计。碰到这类情况我的原则是先看 git diff再判断冲突的“性质”。如果冲突 80% 来自格式扰动直接git checkout --ours/theirs选定一边然后手动把真正需要的功能补进去如果冲突来自整块重写就别用合并工具硬拼了手动把两个版本的核心逻辑抽出来重新组织成一个干净的函数。3.2 JSON merge conflict语义冲突比文本冲突更可怕这个我要单独讲因为现在前后端分离的项目里JSON 配置文件的冲突几乎成了 AI 协作时代的标配。拿一个最常见的场景举例。项目根目录有个config.json{ features: { auth: true } }你在分支 A 上加了一个功能开关AI 在另一个分支 B 上也加了一个功能开关两边修改的是同一个features对象。等合并时git 的文本合并算法开始头疼它在同一个位置看到两个不同的改动于是报出 conflict。但真正的难点在下一步。git 只会告诉你“同一个区块被改两次”它不会告诉你两个改动其实可以兼容——一个加payment: true另一个加notifications: true这两个键合到一起才是正确结果。如果你用Accept Yours或Accept Theirs搞不好就把对方的功能开关丢了而且这种丢失在编译阶段完全不会被发现只有运行期功能异常了才暴露。我在生产环境踩过这个坑就是Accept Yours太顺手把一个部署分支的功能开关给吞了上线后那个功能毫无反应排查了一下午。所以现在我处理 JSON 冲突有个固定动作先看冲突上下文判断是“键级冲突”还是“值级冲突”。键级冲突两边新增各自的新键基本上手动合并就能解决把两边的键都保留值级冲突同一个键两边给不同值就麻烦些得弄明白哪边的值才是当前需求的正确答案。另外建议给配置文件配上 JSON Schema 校验CI 里加一步能提前挡掉很多结构性错误。3.3 Merge 还是 Rebase这是个判断题“merge rebase”这个搜索关键词能上热搜说明大家都在纠结。AI 时代这个纠结更严重了因为 AI 生成的 commit 往往又大又杂直接让 rebase 变成一种折磨。我个人的判断标准用一张表说清楚场景用 Merge用 Rebase公共主干分支master/main适合不适合会改写公共历史长期功能分支多人协作适合勉强但冲突会很多短期个人功能分支可用适合历史更干净AI 生成的大型改动强烈建议非常痛苦不建议需要保留“合并上下文”适合丢失上下文具体到 AI 协作场景我的默认方案是AI 产出的 PR 一律走 Squash Merge。因为 AI 生成的 commit message 通常是一段“我新增了 XX 功能”式的流水账不具备可追溯性。Squash 成一个 commit 后再合入主干主干历史干净回滚也容易。如果你真的很在意分支历史也请先git rebase -i把 AI 的 commit 整理成几个语义清晰的节点再碰合并操作。别拿原始 AI commit 直接上 rebase那只会让自己陷入“崽卖爷田不心疼”的连环冲突地狱。4. 实操重新捡起“敢 Merge”的底气4.1 从源头下手让 AI 写出“可合并”的代码与其等到冲突爆发再当消防员不如在写提示词的时候就把“可合并性”作为必要条件。这是我反复调教出来的提示词模板你可以直接抄请对我现有的函数 addUser 做最小化修改追加一个 phone 字段的校验逻辑。 要求 1. 只修改 addUser 函数内部不要改动其他任何函数 2. 不要重排 import 顺序不要修改代码格式 3. 不要重构文件内其他代码 4. 保持现有命名风格和代码风格 5. 输出时只描述你改了哪些行关键词是“最小化修改”和“不要动其他代码”。实测下来加了这两句话之后AI 产出的 diff 能从几十行缩到十几行合并冲突概率明显下降。另一个技巧是拆任务别让 AI 一次生成一个巨型功能而是把它拆成“先加工具函数”“再改调用点”“最后补测试”三个独立提示词分别提交。每个 commit 小一点review 轻松一点冲突面也跟着小。4.2 合并前的“信任检查清单”不敢 Merge本质上是不敢信任。那就把信任建立成一套可执行的流程。我给自己定了这么一份合并前检查清单每次合 AI 代码必须过一遍编译和测试本地全量跑一遍构建单测、集成测试一网打尽。重点跑新增代码涉及的所有模块的测试包括那些看似无关的调用方。静态检查跑 linter 和类型检查。AI 生成代码最常见的雷就是用了不存在的 API、参数类型不匹配、空指针没兜底。搜索“幻觉 API”去官方文档或依赖库里搜一遍 AI 用的关键类和方法。AI 特别喜欢一本正经地编一个不存在的第三方库方法这个检查能救你一命。安全扫描看有没有硬编码的密钥、Token、数据库连接串。AI 生成示例性质的配置时经常顺手塞进去假的密钥合并到主干再被扫出来就是事故。死代码清理AI 生成的时候经常会留一堆没被调用的辅助函数、未使用的 import。合并前删掉别让主干背着这些垃圾。反向检查 diff从整个 PR 的 diff 反推“这次改动到底想干什么”如果推不出来或者发现 diff 里混进了无关改动就打回去重来。这套清单看起来啰嗦但实际操作一分钟就能过完前三项真正花时间的只有第四和第六项。顺带说一句把能自动化的都自动化——CI 门禁上挂编译、测试、lint、安全扫描让机器把低级错误先挡在门外人只在关键点上做判断。4.3 冲突处理的实操手法从回退到手工合并冲突无法避免但要学会全身而退。我实战中踩过最大的坑就是“硬解冲突”——在一个复杂的大冲突里死磕两小时越改越乱最后代码比以前还糟。所以现在我的原则是超过 10 处冲突或者冲突涉及核心模块先撤退再进攻。撤退的第一道命令是git merge --abort这条命令会把当前仓库状态恢复到触发 merge 之前干净利落。如果你在合并过程中手动改了一部分文件git merge --abort会把这部分改动也丢掉——所以如果你已经改了超过一半的冲突就别 abort 了硬着头皮走完或者用git checkout -- .重置后重新处理。在 IntelliJ IDEA 里操作更直观。执行 merge 后如果弹出冲突对话框你可以选择 Accept Yours保留当前分支版本或 Accept Theirs保留合并进来的分支版本也可以打开 Three-Way Merge 面板手动编辑。如果你改着改着发现冲突太多了想放弃只需要打开 VCS - Git - Merge Changes在弹出的对话框里点 Abort 就行。很多人不知道 IDEA 里还有这个按钮都是傻乎乎地把文件改得乱七八糟再git reset --hard。至于已经合并完成的 commit 想回退IDEA 可以在 VCS 操作历史里找到这次 merge执行 Revert Commits终端方式则是找到 merge commit 后执行git revert -m 1 merge-commit-id-m 1指定保留主分支那一侧把被合并进来的改动整体撤销。这是回退合并提交最安全的姿势。手工合并 JSON 冲突时我的做法是把冲突标记里的两段都复制出来放到一个临时 JSON 文件里用格式化工具展开然后手动决定哪些键保留、哪些值取谁。虽然慢一点但不会丢配置。4.4 让 AI 帮你 review AI机器审机器人做裁决这是个实用到离谱的小技巧既然 AI 代码量大人工逐行看不过来那就让第二波 AI 来做摘要和初筛。我现在常用两个模型搭档干活一个生成代码另一个负责 review。review 的提示词大概是这样的请审查以下 diff重点检查 1. 是否有未定义或错误的 API 调用 2. 是否有资源未释放或异常被吞掉 3. 是否引入了对全局状态的意外修改 4. 命名和代码风格是否与项目一致 5. 性能上是否存在明显问题 并输出一个结论建议合并 / 打回修改 / 需要人工重点审查。实测下来AI review 能筛出不少低级错误比如 undefined 引用、错误处理缺失、不必要的外部依赖。但它也会有漏网之鱼尤其是涉及业务含义和理解项目上下文的问题。所以我的定位是AI 负责初筛人负责裁决。AI review 说“通过”了我还得抽查关键逻辑AI review 说“有问题”我基本都会信因为这通常意味着代码确实有什么不对劲。5. 常见问题与排查技巧实录这部分直接整理成速查表都是我和身边同事在 AI 协作模式下亲身撞过的问题现象可能的根因排查思路与解法合并时整个文件被 AI 重写冲突面积巨大AI 生成代码时做了大范围重构用git diff --stat看文件改动规模先git checkout --theirs引入对方版本再手动把最小改动补进去JSON 配置合并后功能开关消失文本合并工具吞掉了键打开冲突文件确认两边新增键都要保留给 JSON 加 Schema 校验进 CIMerge 到一半发现改不完了冲突数量超出承受范围git merge --abort回退把功能分支拆成更小的分支重新来合完主干后测试大面积失败AI 引用了错误的 API 或假定的依赖不存在全量编译 单测重点搜索 AI 用到的陌生 API对照官方文档验证rebase 过程中无限冲突AI commit 太大太杂放弃 rebase改用 squash merge或git rebase --abort后用交互式 rebase 拆分 commit代码能跑但 Code Review 没人敢批人类审查者无法理解 AI 意图在 PR 描述里补充“AI 生成已人工核验关键逻辑”的说明要求 AI 生成附带设计意图注释合并后出现重复的工具函数AI 没有感知到项目已有实现全局搜索同名或功能相近的工具函数合并阶段发现重复立即抽公共模块再分享两个独家小技巧。第一个是“先看 blame再决定谁改”。遇到合并后的诡异行为先用git blame定位每行代码来源如果发现某个函数全部来自 AI 生成的 merge commit别犹豫重写这个函数比你逐行理解它更划算。第二个是“给每个 AI 分支开一个专属临时分支”。让 AI 生成代码时不要把改动直接堆在你的工作分支上而是让它在临时特性分支上干活你审核通过后再用git cherry-pick把关键 commit 拿过来。这样即使 AI 写坏了你的主分支永远是干净的回退成本几乎为零。6. 门槛降低不等于责任转移折腾了这么久我最深的体会是AI 编程真正改变的不是“写代码”这个动作而是我们对“合并”这件事的态度。从前我们写代码是在用自己的逻辑组织系统Merge 只是最后一步确认现在我们写代码是在替别人写的代码签字画押Merge 变成了整个流程里最重要的一次决策。我个人现在的状态是代码生产速度提上来了但我花费在需求澄清、设计约束、审查门禁上的时间反而更多了。我不再把“AI 一天交付多少行代码”当作绩效指标而是看“这个月合入主干的代码有多少被回滚”。这个数字比任何时候都更能真实反映工程质量。最后分享一个小建议如果你也是个天天跟 AI 生成的代码打交道的人多花点时间把团队的 CI 和 Code Review 流程打磨成“AI 友好型”——小步提交、语义化 commit、自动化检查全覆盖、JSON 有 Schema、冲突有预案。让 AI 去狂飙让流程去兜底让 Merge 重新变成一件有底气的事。毕竟一个健康的仓库从来不是看写入速度有多快而是看每一次合并之后系统还能不能长久地稳定运行下去。