尧图精选

基于Git与LLM Agent的自动化代码审查流程实战

🕒 发布时间:2026/9/20 23:40:22 📁 来源:尧图网络
1. 为什么我要自己搭一套 open-code-review 流程团队里代码合并请求越堆越多人工逐行看 diff 这件事说实话早就成了瓶颈。一个中等规模的仓库一天十几个合并请求每个请求动辄几百行改动光靠两三个资深工程师轮着审眼睛看花了不说漏掉的边界条件、空指针、资源没释放这类问题事后补锅的成本比当场拦下来高十倍不止。我试过纯靠人工加检查清单也试过只上静态扫描工具前者不稳定后者噪音大最后落到一个折中方案用 CLI 把 Git 的变更拉出来交给 LLM Agent 做第一轮语义审查人只看它标出来的可疑点和它给不出的业务判断。这套东西我内部叫它 open-code-review核心就是三个词——Git、CLI、LLM Agent。先把概念理清楚因为热词里混了一堆容易搞混的名词。Git是版本控制负责记录每次改动git diff、git log、git worktree这些命令是我们拿数据的入口。CLI是命令行界面也就是你在终端里敲命令的那层壳codex cli、claude cli、trae cli、deveco cli 这些都是不同厂商提供的命令行工具本质都是让你在终端里调用背后的模型能力。LLM是大语言模型DeepSeek、GPT 系列、Claude 系列都属于这一类它是“大脑”。Agent是在 LLM 外面套了一层循环和工具调用能力的东西它能自己决定“我要读哪个文件”“我要跑哪条命令”“我要不要再问一轮”所以 Agent 和 LLM 的区别简单说就是 LLM 只会回答Agent 会动手。Embedding是把文本转成向量用来做相似度检索和审查这件事关系不大但做代码库索引时会用到。搞清这几个词后面选型就不会乱。这套 open-code-review 适合谁适合已经会用 Git 基本命令、想在团队里落地自动化审查、又不想被某个商业平台绑死的开发者。你不需要是算法专家但要能看懂 diff、能写一点脚本、能配环境变量。下面我按“整体设计—核心细节—实操落地—问题排查”四块讲全部是我自己踩过坑之后沉淀下来的做法能直接抄。2. 整体设计与选型为什么是 CLI Agent 而不是插件2.1 方案对比插件、平台、自建 CLI 三条路一开始我评估过三条路。第一条是 IDE 插件比如在 VS Code 里装个审查助手优点是上手快缺点是它绑死在编辑器里CI 流水线跑不了而且不同人用的编辑器不一样统一不了。第二条是托管平台自带的审查机器人优点是省事缺点是数据要出自己机房规则也不透明遇到 login failed、api token 这类问题你还得去翻它的文档。第三条就是自建 CLI 流程用 Git 拿 diff用命令行工具调 Agent输出结构化结果。我最后选第三条理由很实在可控。diff 怎么切、prompt 怎么写、哪些文件跳过、结果怎么落库全在我手里。而且 CLI 天然适合塞进 CI也适合本地 pre-push 钩子。热词里那么多人在搜 codex cli 安装、claude cli 安装、windows 安装 git 命令说明大家其实都在往“终端里干活”这个方向走这不是偶然是因为终端是唯一能同时覆盖本地和流水线的入口。2.2 核心链路拆解从 git diff 到审查报告整条链路我拆成五步每一步都有它存在的理由。第一步确定审查范围。不是每次都要审全量那样又慢又贵。我用git diff --name-only先拿到改动文件列表再用git diff拿具体内容。如果是合并请求场景就用git diff main...feature这种三点语法只拿分支分叉之后的改动。这里有个细节git -c diff.mnemonicprefixfalse -c core.quotepathfalse这两个参数我几乎每次都带前者让 diff 前缀稳定成 a/ b/后者防止中文路径被转义成八进制不然后面解析路径会出错。第二步过滤和分块。二进制文件、锁文件、自动生成的代码直接跳过不然纯浪费 token。大文件要按函数或按 hunk 切块因为模型上下文有限一次塞几千行它会漏看中间。第三步构造 prompt。这是整套东西的灵魂。我不用“帮我看看这段代码有没有问题”这种废话而是给 Agent 一个明确的角色、明确的输出格式、明确的检查维度。检查维度我固定成六类正确性、边界条件、资源管理、并发安全、错误处理、可读性。输出要求它按严重级别分档并且必须给出文件、行号、理由、修改建议。第四步调用 Agent。这里 CLI 工具就派上用场了它负责把 prompt 发给模型、把工具调用读文件、搜代码串起来、把结果拿回来。Agent 相比裸 LLM 的价值就在这——它能自己去读被改函数的调用方判断这个改动会不会破坏上游。第五步汇总与去重。多个文件、多个块的审查结果要合并同一类问题要去重最后按严重级别排序输出。我一般输出成 Markdown 表格加详情方便贴到合并请求里。2.3 为什么坚持“人只看 Agent 标出来的点”有人会问既然上了 Agent为什么不干脆全自动拦截我的经验是语义审查的误报率永远不可能为零。模型会把一些它不理解的业务约定当成 bug也会漏掉需要跨仓库才能看出的问题。所以我的定位很明确Agent 做第一轮筛选把明显的问题捞出来把可疑的点标出来人只做决策。这样人的精力从“逐行看”变成“看结论”效率提升是数量级的。这个定位决定了后面所有设计——prompt 要让它敢标可疑点而不是让它假装什么都懂。3. 核心细节解析prompt、分块与 Git 数据获取3.1 Git 侧的数据获取要点Git 这块看着简单坑不少。先说git diff的几种用法很多人分不清。git diff不带参数是工作区和暂存区比git diff --cached是暂存区和 HEAD 比git diff HEAD是工作区和 HEAD 比。审查合并请求时最稳的是git diff base...head三点表示从共同祖先开始算避免把 base 分支自己的新提交也算进来。再说git worktree这个命令在审查场景里特别好用。你可以在不切换当前工作区的情况下把目标分支 checkout 到一个临时目录然后在那里跑审查互不干扰。我经常一边在主目录写代码一边让审查脚本在 worktree 里跑两边不打架。还有git log我一般用git log --oneline -n 20看最近提交判断这次改动是不是夹带了无关提交。如果一次合并请求里混了格式化、重命名、功能改动三种东西我会先让作者拆开因为混在一起审查质量会直线下降。提示路径里有中文或空格时务必带上-c core.quotepathfalse否则git diff --name-only输出的路径是转义过的脚本解析会失败。3.2 prompt 设计把“审查”拆成可执行的检查项prompt 我改了十几版最后稳定下来的结构是这样的。先给角色“你是一名资深代码审查者只关注改动引入的问题不评价既有代码风格。”这句话很重要不然模型会对着没改的老代码一顿输出。然后给上下文改动文件列表、每个文件的 diff、必要的调用方代码。接着给检查清单就是我前面说的六类。最后给输出格式强制它用固定字段。输出格式我要求每条问题包含severityblocker/major/minor、file、line、issue、suggestion。severity 分三档是为了让人快速排序blocker 必须改major 建议改minor 可改可不改。这个分档不是拍脑袋是让模型自己判断影响面——会导致崩溃或数据错误的算 blocker逻辑可能不对的算 major风格和可读性算 minor。有个技巧我实测很有效让模型先复述它理解的改动意图再给问题。这一步能逼它先读懂代码而不是上来就挑刺。复述错了说明它没理解那它给的问题可信度也低我会直接丢弃这一轮结果。3.3 分块策略按 hunk 切还是按函数切分块这件事直接决定审查质量。我试过三种整文件、按 hunk、按函数。整文件的问题是上下文太长模型注意力涣散中间的问题容易漏。按 hunk 的问题是切得太碎一个函数被拆到两个 hunk 里模型看不到全貌。最后我选按函数切hunk 作为兜底。具体做法是先用语言对应的解析器Python 用 astJS 用 tree-sitter 之类把改动文件解析成函数列表然后看 diff 落在哪些函数里把整个函数体连同 diff 一起给模型。如果解析不了比如配置文件、脚本就退回按 hunk 切但每个 hunk 前后各带 10 行上下文。这个 10 行是我试出来的太少模型看不懂太多浪费 token。token 预算也要算。我一般给单次审查设 8k token 上限超了就拆。一个函数平均 200 行加上 prompt 和上下文大概 3k token一次能塞两三个函数。这个数字不是死的你模型上下文大就多塞点但别塞满留出空间给模型输出。3.4 工具选型CLI 工具怎么挑热词里 codex cli、claude cli、trae cli、deveco cli 都在被搜说明选择确实多。我的选型标准就三条能不能在 CI 里非交互运行、能不能自定义 prompt、能不能拿到结构化的工具调用结果。第一条是硬门槛很多 CLI 默认是交互式的跑在流水线里会卡住。第二条决定你能不能把审查逻辑固化下来。第三条决定你能不能做后续处理。安装这类 CLI 工具时Windows 用户最容易遇到的就是“命令找不到”。热词里那句unable to locate the codex cli binary我太熟了本质就是安装路径没进 PATH。解决办法很简单找到安装目录把它加到系统环境变量 PATH 里然后重开终端。codex --version能出版本号说明装好了但如果在 Windows Terminal 里还是找不到多半是终端没继承新环境变量关掉重开就行。注意CLI 工具首次使用一般要配 API tokentoken 别写死在脚本里用环境变量传不然提交到仓库就泄露了。4. 实操落地从零跑通一次 open-code-review4.1 环境准备Git 与 CLI 工具安装先把 Git 装好。Windows 上直接下安装包一路下一步注意勾选“把 Git 加入 PATH”。装完开终端敲git --version出版本号就成。Linux 用包管理器apt install git或yum install git。装完配一下身份git config --global user.name和git config --global user.email不配的话提交会报错。然后是 CLI 工具。按你选的工具走官方安装步骤装完配 token。我习惯把 token 放在 shell 的 profile 里比如export REVIEW_API_TOKENxxx脚本里用$REVIEW_API_TOKEN引用。这样换机器只改一处。接着准备审查脚本的目录结构我一般这样组织open-code-review/ review.sh # 主入口 prompt/ system.txt # 系统角色 checklist.txt # 检查清单 output/ # 审查结果落这里system.txt放角色设定checklist.txt放六类检查项主脚本负责拼 prompt、调 CLI、收结果。4.2 主脚本实现拿 diff、切块、调 Agent主脚本我用 bash 写逻辑清晰够用。核心步骤我贴一下关键片段。#!/usr/bin/env bash set -euo pipefail BASE${1:-main} HEAD${2:-HEAD} # 1. 拿改动文件列表注意 quotepath git -c core.quotepathfalse diff --name-only $BASE...$HEAD /tmp/changed.txt # 2. 过滤掉不需要审的文件 grep -Ev \.(lock|min\.js|png|jpg|svg)$ /tmp/changed.txt /tmp/to_review.txt # 3. 逐个文件拿 diff while read -r f; do git -c diff.mnemonicprefixfalse diff $BASE...$HEAD -- $f /tmp/diff_$(echo $f | tr / _).patch done /tmp/to_review.txt拿到 diff 之后按前面说的按函数切块。切块我用一个 Python 小脚本因为 bash 处理文本太费劲。import ast, sys def split_by_function(filepath, diff_text): with open(filepath, encodingutf-8) as f: source f.read() tree ast.parse(source) funcs [] for node in ast.walk(tree): if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): funcs.append((node.lineno, node.end_lineno, node.name)) # 根据 diff 行号匹配函数返回需要审查的函数块 return funcs这个脚本只处理 Python其他语言你换成对应解析器。切完块把每个块的源码和 diff 拼进 prompt调 CLI。PROMPT$(cat prompt/system.txt prompt/checklist.txt) PROMPT$PROMPT\n\n以下是改动\n$(cat /tmp/block_1.txt) echo -e $PROMPT | your-cli-tool --non-interactive output/review_1.md--non-interactive这个参数是关键不加的话在 CI 里会卡住等输入。4.3 结果汇总去重、排序、输出多个块的结果要合并。我写了个小脚本做三件事按filelineissue去重、按 severity 排序、生成 Markdown 表格。去重是因为同一个问题可能被相邻两个块都报出来。排序是为了让人先看 blocker。汇总后的输出长这样严重级别文件行号问题建议blockersrc/db.py88连接未关闭用 with 语句majorsrc/api.py42未处理空返回加 None 判断minorsrc/util.py15变量命名含糊改为 user_count这个表格直接贴到合并请求评论里作者一眼就能看到要改什么。4.4 接入 CI让审查自动跑本地跑通之后接进 CI 才是价值最大化。我在流水线里加一个 job触发条件是合并请求创建或更新。job 里先 checkout 代码注意要 fetch 完整历史不然git diff base...head算不出共同祖先。然后跑主脚本把输出作为评论发出去。这里有个坑CI 环境里 Git 默认可能是浅克隆git diff会失败。解决办法是 checkout 时设fetch-depth: 0拉全量历史。另一个坑是 CI 里没有交互终端CLI 工具必须支持非交互模式前面强调过。提示CI 里跑审查要设超时模型调用偶尔会慢别让整个流水线卡死。我一般设 5 分钟超时超了就跳过审查不阻塞合并。5. 常见问题与排查技巧实录5.1 Git 相关的高频问题问题一git diff输出路径是转义的八进制。这是core.quotepath默认开启导致的中文路径会变成\344\275\240这种。解决就是加-c core.quotepathfalse我前面反复强调过。问题二git diff base...head报错找不到共同祖先。多半是浅克隆历史不全。用git fetch --unshallow补全或者 checkout 时设fetch-depth: 0。问题三git commit --amend之后审查结果对不上。amend 会改提交哈希如果你缓存了上次审查的 commit id就对不上了。我的做法是每次审查都重新算 diff不缓存 commit id。问题四git worktree用完忘了删。worktree 会占磁盘跑完审查记得git worktree remove。我写了个 trap 在脚本退出时自动清理。5.2 CLI 与 Agent 相关的问题问题一unable to locate the codex cli binary。前面说过PATH 问题。找到二进制位置加进 PATH重开终端。Windows 上还要注意如果你在 Git Bash 里装在 PowerShell 里可能找不到因为两者的 PATH 可能不一样统一在系统环境变量里配。问题二login failed. check api token。token 没配、配错、或者过期。先确认环境变量有没有传进去echo $REVIEW_API_TOKEN看一眼。再确认 token 有没有多余空格复制粘贴最容易带空格。问题三Agent 每次都要确认动作跑不动。这是权限设置问题很多 CLI 工具有“完全访问”模式开了之后它就不再逐条问你。但要注意开了完全访问意味着它能执行命令审查场景里我只让它读文件不给写权限安全第一。问题四模型输出格式不稳定。有时候它不按你要求的字段输出。解决办法是在 prompt 里给一个输出示例让它照着填。我实测给了示例之后格式合规率从七成提到九成五以上。5.3 审查质量相关的问题问题一误报太多。多半是 prompt 里没限定“只关注改动引入的问题”。加上这句再让它先复述改动意图误报会明显下降。问题二漏报严重问题。检查上下文给少了。把被改函数的调用方也塞进去让它能看到影响面。另外检查清单要具体别写“检查代码质量”这种空话写“检查所有资源获取是否有对应的释放”。问题三大文件审查超时。分块没做好。按函数切单块控制在 500 行以内。超大的自动生成文件直接跳过。问题四同一问题重复报。去重没做。按filelineissue三元组去重简单有效。5.4 常见问题速查表现象可能原因解决路径转义quotepath 开启加-c core.quotepathfalse找不到共同祖先浅克隆fetch-depth: 0命令找不到PATH 未配加环境变量重开终端登录失败token 缺失或过期检查环境变量重新生成卡在确认交互模式开非交互或完全访问格式乱无输出示例prompt 里给示例误报多未限定范围加“只关注改动引入”漏报多上下文不足补调用方代码超时块太大按函数切限 500 行重复报未去重按三元组去重6. 我踩过的坑和几条实在建议先说一个我印象最深的坑。有次审查一个并发相关的改动模型信誓旦旦说没问题结果上线后出了竞态。复盘发现模型只看了被改的那个函数没看它调用的那个共享状态在别处怎么用的。从那以后我强制要求把被改函数的直接调用方也塞进上下文哪怕多花点 token。这个改动之后并发类问题的漏报少了一大半。第二个坑是 token 成本。一开始我不分块整个文件往里塞一个月下来账单吓人。后来按函数切只审改动涉及的函数成本直接降到原来的三分之一。所以分块不只是为了质量也是为了钱。第三个坑是过度信任 severity。模型标的 blocker 不一定真是 blocker它标的 minor 有时候反而是大问题。我的做法是blocker 和 major 必须人工确认minor 扫一眼就行。别把决策权完全交出去。最后分享一个提效小技巧。我把审查脚本挂到 pre-push 钩子上本地 push 前自动跑一遍只审本次要推的提交。这样很多低级问题在本地就被拦下来了推到远端的时候已经干净很多团队里其他人的审查负担也轻了。钩子脚本就几行git diff origin/main...HEAD拿改动跑审查有问题就提示但不强制阻断给人留个“我知道但我要推”的余地。这套 open-code-review 我用了大半年最大的体会是工具的价值不在于多智能而在于它能不能稳定地嵌进你现有的工作流。Git 给你数据CLI 给你入口Agent 给你判断三者各司其职人才有精力去做真正需要人做的事。你要是也在被审查压得喘不过气不妨从最小可用版本开始——先跑通一个文件的审查再慢慢加过滤、加分块、加去重别一上来就追求全自动那样大概率会卡在半路。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →