小项目实战:代码审查、重构与提交前检查全流程指南
1. 为什么“提交前检查”值得单独拎出来讲很多人做小项目时有个习惯功能跑通了随手一个git add . git commit -m update就推上去了。等到过两周回头看自己的代码或者别人接手你的仓库第一反应往往是——“这写的是啥”我做过一个统计在自己经手的十几个小项目里真正花在“写新功能”上的时间大概只占四成剩下六成里有相当一部分是花在代码审查、重构和提交前检查这三件事上。听起来像是额外负担但实际做下来它反而是省时间的那一环。因为一个没做提交前检查的仓库后期每改一次都要重新理解一遍混乱的逻辑成本是复利的。这篇内容就是围绕“小项目实战”的第四环展开代码审查怎么做、重构该在什么时候动刀、提交前检查清单长什么样。它适合正在独立做小项目、或者两三个人协作写代码的朋友尤其是那种“能跑就行、但越写越乱”的阶段。我会把每一步背后的判断逻辑讲清楚而不是只丢一份清单让你照抄——因为清单是死的判断是活的。核心关键词我先摆在这代码审查、重构、提交前检查、小项目实战、Git 提交规范。这几个词会贯穿全文你读完应该能直接在自己项目里落地一套流程。2. 代码审查小项目里到底审什么2.1 小项目审查和团队审查的区别大团队的代码审查Code Review通常有严格的流程提 PR、指定 Reviewer、CI 跑测试、逐行评论、Approve 才能合并。但小项目照搬这套会累死自己——你既是作者又是审查者搞得太正式反而没人愿意做。我的做法是把审查拆成两个层次一个是“自己审自己”的提交前自审另一个是“拉个人帮你看”的交叉审查。前者每次提交都做后者一周或一个功能节点做一次。这样既不会因为流程太重而放弃又能在关键节点拿到外部视角。自审的核心不是找 bugbug 靠测试找而是找**“三个月后的自己会不会骂现在的自己”。具体看三件事命名是否表意、逻辑是否有隐藏假设、有没有留下临时调试代码。交叉审查则重点看设计层面**的问题模块划分是否合理、有没有重复造轮子、接口是否清晰。提示小项目最忌讳“审查等于挑刺”。审查的目标是让代码更容易被修改而不是证明谁写得更好。心态摆正这件事才能持续做下去。2.2 自审清单提交前必须过一遍的五个问题我给自己定了一份自审清单每次git commit前花两分钟过一遍。这五个问题按重要性排序这段代码如果换个人来看能不能在 30 秒内看懂它在干什么如果看不懂多半是命名或结构的问题。有没有硬编码的值比如魔法数字、写死的路径、临时的时间戳。这些是后期最容易埋雷的地方。异常和边界情况处理了吗空输入、超长输入、网络失败、文件不存在——小项目最容易忽略这些。有没有console.log、print、TODO之类的残留调试代码留在提交里是典型的“技术债”。这次改动是否只做了一件事如果一个提交里既改了功能又调了格式又删了注释回滚的时候会很痛苦。这五条看起来简单但真正每次都做的人不多。我自己的经验是坚持一个月后代码的可读性会有肉眼可见的提升因为你在写的时候就会下意识地避开这些问题。2.3 交叉审查怎么找人、怎么提意见小项目找人审查最实际的方式是找一个也写代码的朋友互相看对方的仓库。不用搞正式流程就是“你帮我扫一眼这个模块我帮你看看那个函数”。时间成本低但收益很高因为别人能一眼看出你“当局者迷”的地方。提意见的时候有个技巧用提问代替断言。比如不说“这里应该用 Map 而不是 Object”而说“这里用 Object 存键值对如果 key 是动态的会不会有原型链污染的风险”——提问式反馈让对方自己思考接受度更高也不容易伤和气。如果实在找不到人还有个退而求其次的办法隔一天再自己审一遍。刚写完代码时大脑还停留在“实现思路”里隔一天再看你就变成了“读者视角”很多问题会自己冒出来。我试过很多次隔夜自审发现的命名问题比当天多一倍。3. 重构什么时候动刀怎么动才不翻车3.1 重构的触发信号别等代码烂透了才动手重构最大的误区是“等有空了再重构”。实际上重构应该由信号触发而不是由时间触发。我总结了几个明确的信号出现任意一个就该考虑重构了同一个逻辑在三个地方出现复制粘贴超过两次就该抽成函数。改一个功能要动五个文件说明模块边界没划清耦合太重。函数超过 50 行不是说 50 行是硬线而是超过这个长度通常意味着它做了不止一件事。加新功能时越来越慢如果每加一个小功能都要花半天理解旧代码说明结构该调整了。测试写不下去测试难写往往是因为代码依赖太多、职责不清。这些信号里我最看重的是“改一个功能要动五个文件”。它直接反映了模块划分的问题而模块划分是重构里收益最大的部分。3.2 重构的三条铁律小步、可回滚、有测试重构不是重写。重写是把房子推倒重建重构是换地基的同时房子还能住人。所以有三条铁律必须守第一小步走。每次只改一个点改完立刻验证。比如先把一个长函数拆成两个跑一遍测试确认没问题再继续拆。不要一次性大改否则出了问题根本不知道是哪一步引入的。第二保证可回滚。重构前先提交一次重构后再提交一次中间用清晰的 commit message 标记。这样万一重构引入 bug可以快速回退到重构前的状态。我习惯在重构分支上操作主干保持稳定。第三有测试兜底。如果项目没有测试重构前至少写几个“冒烟测试”——覆盖核心路径的最小测试集。没有测试的重构等于闭着眼睛改代码风险极高。注意如果项目完全没有测试而你又急着重构可以先写测试再重构。写测试的过程本身就会暴露很多设计问题一举两得。3.3 常见重构手法在小项目里的应用小项目里最常用的重构手法其实就那么几种我按使用频率排个序重构手法适用场景操作要点提取函数长函数、重复逻辑把一段独立逻辑抽成命名清晰的函数重命名命名表意不清用“动词名词”结构避免缩写消除魔法值硬编码的数字/字符串抽成常量或配置项合并重复条件多个 if 判断同一变量用查表法或策略模式替代拆分模块单文件过大按职责拆成多个文件明确依赖方向拿“提取函数”举例。假设你有一段代码在解析用户输入、校验格式、然后存库全挤在一个函数里。重构时先找到“校验格式”这一段把它抽成validateInput(input)参数和返回值明确。这样主函数就变成了“解析→校验→存储”三步一眼就能看懂流程。再比如“消除魔法值”。代码里出现if (status 3)这种三个月后你绝对想不起来 3 代表什么。抽成const STATUS_APPROVED 3之后代码自解释改起来也安全。3.4 重构后的验证怎么确认没改坏重构完最重要的一步是验证。我的验证流程分三层单元测试如果有直接跑全绿才继续。手动冒烟把核心功能手动走一遍确认主流程没问题。对比输出对于有明确输入输出的模块重构前后跑同样的输入对比输出是否一致。第三层最容易被忽略但最有效。比如一个数据处理函数重构前先记录几组输入输出重构后用同样的输入跑一遍结果一致就说明行为没变。这个方法对没有测试的项目特别实用。4. 提交前检查一份能直接抄的清单4.1 提交前检查的四个维度提交前检查不是简单地看一眼git diff而是有结构地过一遍。我把它分成四个维度代码质量命名、注释、格式、是否有调试残留。功能完整性这次改动是否完成了预期目标有没有半成品。安全性有没有泄露密钥、密码、个人信息依赖是否有已知问题。提交信息commit message 是否清晰描述了“做了什么”和“为什么”。这四个维度里安全性是最容易被小项目忽略的。我见过太多仓库里直接写着数据库密码、API Key 的配置文件被提交上去。一旦推到公开仓库后果很严重。4.2 逐项检查清单可直接复制使用下面这份清单是我自己用了很久的版本你可以直接抄也可以按项目特点增删代码质量[ ] 变量、函数命名是否表意清晰没有a、b、temp这类命名[ ] 是否有未使用的导入、变量、函数[ ] 是否有console.log、print、debugger等调试代码[ ] 注释是否还有效有没有和代码矛盾的过时注释[ ] 代码格式是否统一缩进、引号、分号功能完整性[ ] 本次改动是否完成了 commit message 里描述的目标[ ] 是否有未完成的TODO或半成品逻辑[ ] 边界情况是否处理空值、超长、异常输入安全性[ ] 是否包含密钥、密码、Token、个人信息[ ].gitignore是否覆盖了配置文件、日志、依赖目录[ ] 依赖版本是否锁定有没有引入来源不明的包提交信息[ ] commit message 是否说明了“做了什么”[ ] 如果是修复 bug是否说明了“为什么”[ ] 是否一次提交只做一件事这份清单过一遍大概三到五分钟但能挡掉大部分低级问题。4.3 用 Git 钩子把检查自动化手动检查靠自觉容易偷懒。更稳的做法是用 Git 的pre-commit钩子在提交前自动跑检查。最简单的实现是写一个 shell 脚本放在.git/hooks/pre-commit内容大概是#!/bin/sh # 检查是否有调试代码残留 if grep -rn console.log\|debugger\|TODO --include*.js --include*.ts src/; then echo 发现调试代码或 TODO请清理后再提交 exit 1 fi # 检查是否有明显的密钥泄露 if grep -rn password\s*\|api_key\s*\|secret\s* --include*.js --include*.py src/; then echo 疑似密钥泄露请检查 exit 1 fi exit 0这个脚本在git commit时自动执行发现问题就阻止提交。虽然简单但非常有效。我自己的项目里就靠这个挡掉过好几次误提交密钥的情况。提示钩子脚本不会随仓库自动同步给协作者需要在 README 里说明或者用工具统一管理。小项目里手动同步也能接受。4.4 提交信息的写法让历史记录能当文档用commit message 写得好git log就是一份免费的项目文档。我的写法是**“动词开头 简短描述 必要说明”**好例子修复用户登录时 token 过期未刷新的问题好例子重构数据解析模块拆分为校验和转换两个函数差例子update、fix bug、修改如果改动比较复杂我会在标题下空一行写详细说明解释“为什么这么改”。比如重构数据解析模块拆分为校验和转换两个函数 原来的 parseData 函数同时做了格式校验和类型转换 导致测试很难写。拆成 validateInput 和 transformData 之后两个函数可以独立测试职责也更清晰。这样的提交信息三个月后回来看能立刻回忆起当时的思路。5. 常见问题与排查技巧实录5.1 审查和重构中最容易踩的坑坑一审查变成“风格之争”。有人喜欢两个空格缩进有人喜欢四个这种争论没有意义。小项目里应该用工具如 Prettier、Black统一格式把人的精力留给逻辑问题。坑二重构时顺手加新功能。这是大忌。重构和加功能混在一起一旦出问题你分不清是重构引入的还是新功能引入的。我的原则是重构的提交里不出现新功能加功能的提交里不做重构。坑三提交前检查流于形式。清单列了但不看等于没有。解决办法是把检查自动化能脚本化的绝不靠人。人只负责判断“这个逻辑对不对”机械检查交给工具。坑四commit message 写得太随意。这个坑的代价在后期才显现。当你需要回滚某个功能时面对一堆update的提交记录根本找不到该回滚哪个。5.2 问题速查表问题现象可能原因排查方向提交后发现密钥泄露检查清单没做.gitignore不全立即撤销提交轮换密钥补全忽略规则重构后功能异常重构步子太大没有测试兜底回滚到重构前拆小步骤重做代码审查没人愿意做流程太重反馈方式太生硬简化流程用提问代替断言commit 历史混乱提交粒度太粗信息不清晰从下次提交开始规范历史不必强改加新功能越来越慢模块耦合缺少抽象识别重复逻辑提取函数或模块5.3 几个我踩过的具体坑坑一把配置文件提交上去了。早期做项目时我把带数据库密码的config.js直接提交了。发现后虽然删了文件但 Git 历史里还留着。后来学乖了项目一开始就写好.gitignore配置文件用config.example.js做模板。坑二重构时改了行为但没意识到。有一次我把一个循环改成map以为只是写法变化结果原来的循环里有breakmap不支持提前退出行为变了。这个坑让我明白重构的前提是理解原代码的每一个行为细节不能只看表面。坑三提交前检查漏了依赖更新。有一次我升级了一个依赖本地测试没问题就提交了结果协作者拉下来跑不起来因为package.json改了但 lock 文件没提交。后来我把“lock 文件是否同步”加进了检查清单。6. 把这套流程变成习惯的几个实操建议6.1 从最小可行的流程开始不要一上来就搞全套钩子、清单、交叉审查、自动化测试全上。那样大概率坚持不过一周。我的建议是先做一件事每次提交前花两分钟过一遍自审清单。等这个习惯稳定了再加钩子自动化再加交叉审查。习惯的养成靠的是低门槛而不是高强度。两分钟的自审任何人都做得到做一个月就能感受到变化。6.2 给项目配一份“开发约定”小项目也值得有一份简短的CONTRIBUTING.md或DEVELOPMENT.md写清楚代码格式用什么工具、提交信息怎么写、分支怎么命名、提交前要做什么检查。不用长一页纸就够。它的作用是让协作有据可依也让自己有章可循。我自己的项目里这份文档大概就三段格式约定、提交约定、检查清单。每次开始新功能前扫一眼能避免很多低级问题。6.3 定期做一次“代码体检”除了每次提交前的检查我还会每隔一段时间比如两周或一个功能节点做一次“代码体检”。内容是通读一遍核心模块看看有没有新的重复逻辑、有没有过时的注释、依赖有没有需要升级的。这个过程不一定要改代码但能让你对项目状态保持清醒。体检的产出通常是一份“待重构清单”按优先级排好下次有空时按单处理。这样重构就不是“想起来才做”而是有计划地进行。6.4 工具推荐轻量但够用小项目不需要重型工具几个轻量的就够格式统一Prettier前端、BlackPython、gofmtGo配置一次编辑器自动格式化。静态检查ESLintJS/TS、PylintPython能提前发现很多低级错误。提交规范commitlint husky自动检查 commit message 格式。密钥扫描gitleaks 或 trufflehog扫描仓库里有没有泄露的密钥。这些工具配置起来都不复杂一次配置长期受益。我自己的项目里Prettier 和 ESLint 是标配钩子脚本用 shell 手写够用就行。代码审查、重构、提交前检查这三件事单独看都是“额外工作”但合在一起它们构成了小项目能长期维护的基础。我自己的体会是前期多花十分钟检查后期少花十小时排查。这个投入产出比做过的人都懂。