为什么你的 Git 历史一团糟
几乎每个团队都经历过这样的提交记录:fix、fix again、临时提交、好像好了。三个月后想回滚一个 bug,git log 翻了三屏也找不到对应改动。问题不在 Git,而在没有人约定「怎么提交、怎么开分支」。
本文用两条主线解决:提交信息规范化(Conventional Commits)+ 分支模型选择(Git Flow / Trunk-Based),让你的仓库从「考古现场」变成「可读文档」。
一、提交信息:用 Conventional Commits 统一语言
Conventional Commits 是一套约定式提交规范,格式固定、机器可解析,也是 Semantic Versioning 和自动化 changelog 的基础。
基本格式
<type>(&<scope>): <subject>
<body>(可选)
<footer>(可选,如 BREAKING CHANGE / 关闭 issue)
常用 type:
feat:新功能fix:修复 bugdocs:文档变更style:代码格式(不影响逻辑,如空格、分号)refactor:重构(非 feat 也非 fix)perf:性能优化test:增加测试chore:构建/依赖/工具链变动build:构建系统或外部依赖变动ci:CI 配置变动
好例子 vs 坏例子
# 坏:信息量为零
git commit -m "更新"
# 好:一眼看懂做了什么、影响哪里
git commit -m "feat(order): 支持优惠券叠加计算
在结算服务新增 coupon-stacking 模块,允许用户叠加最多 3 张券,
并补充了边界单元测试。
Closes #142"
二、用工具把规范「卡」住,而不是靠自觉
规范写在文档里没人看,得用工具强制。推荐 Commitlint + Husky 在本地提交时校验,CI 里再校验一次。
# 安装
npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
# .commitlintrc.js
module.exports = { extends: ['@commitlint/config-conventional'] }
# husky 钩子(提交前校验)
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
这样不符合规范的提交会被直接拒绝,团队历史自然就干净了。
三、分支模型:选一个,别混着用
方案 A:Git Flow(适合有版本发布节奏的团队)
main:始终可发布的稳定版本develop:日常集成分支feature/*:新功能,从 develop 拉,合回 developrelease/*:发布准备,从 develop 拉,合回 main 和 develophotfix/*:线上紧急修复,从 main 拉,合回 main 和 develop
优点:职责清晰、适合多版本并行维护。缺点:分支多、流程重。
方案 B:Trunk-Based(适合高频交付/CI 成熟团队)
- 只有
main一条长生命周期分支 - 功能通过短命分支(1-2 天)或 Feature Flag 合入
- 每次合入都触发 CI,强调「小步快跑」
优点:极简、合并冲突少、交付快。缺点:对 CI 和测试覆盖要求高。
# Trunk-Based 典型一天
git switch main
git pull
git switch -c feature/login-oauth # 短命分支
# ... 写代码、本地测试 ...
git push -u origin feature/login-oauth
# 提 PR/MR,CI 通过即合入 main
四、几个让历史更干净的小习惯
- 一个提交只做一件事:别把「重构 + 修 bug + 加功能」塞进一个 commit,用
git add -p按需暂存。 - 学会 rebase 整理本地提交:推送到远程前,用
git rebase -i HEAD~3把零散提交压成有意义的几个。 - 禁止向共享分支强推:
git push --force只用于自己的特性分支,且优先用--force-with-lease。 - 合并用 –no-ff 保留轨迹:
git merge --no-ff feature/x让功能分支在历史上可见。
小结
提交规范解决「每条记录说什么」,分支模型解决「代码往哪流动」。两者配合,再配上 Commitlint 这种强制工具,你的 Git 历史会从负担变成资产——回滚、复盘、自动生成 changelog 都不再是难题。




