第 81 章:Git 规范与协作
学习目标
- 掌握 Git Flow / GitHub Flow / Trunk Based 三种分支模型
- 编写清晰的 commit message 和 PR 描述
- 学会代码审查与团队协作
一、为什么需要 Git 规范?
没有规范的痛点:
- 分支命名混乱:
fix、bug、new、temp、test - commit message 没意义:
update、改一下、tmp - 多人冲突频繁
- 上线后找不到变更点
二、三大分支模型
1. Git Flow(重型)
| 分支 | 作用 | 寿命 |
|---|---|---|
| master | 生产代码,每个 commit 都是发布版本 | 永久 |
| develop | 集成分支,所有 feature 合并到这里 | 永久 |
| feature/* | 新功能分支 | 临时 |
| release/* | 发布准备分支 | 临时 |
| hotfix/* | 紧急修复分支 | 临时 |
适用:有明确版本号的发布型产品(移动 App、桌面软件)。
2. GitHub Flow(轻量,推荐)
特点:
- 只有
main一个长期分支 - 从
main拉feature/*,完成后 PR 合并 - 合并后自动部署
- 修复:拉
hotfix/*,合并后自动部署
适用:持续部署的 Web 服务(SaaS、互联网产品)。
3. Trunk Based(极简)
特点:
- 主干开发,分支寿命 < 1 天
- 频繁合并到 trunk
- 靠特性开关(feature flag)控制未完成功能
适用:Google、Facebook 等大型互联网公司。
三、分支命名规范
bash
# 功能
feature/user-login
feature/order-export
feature/IUS-123-add-cart # 加 ticket 号
# 修复
fix/order-timeout-bug
fix/123-coupon-calc-error
# 重构
refactor/user-service-split
# 紧急修复
hotfix/payment-callback-fail
# 发布
release/v1.5.0
# 个人实验
experiment/cache-redis-test四、Commit Message 规范(Conventional Commits)
格式
<type>(<scope>): <subject>
<body>
<footer>Type 类型
| Type | 说明 | 示例 |
|---|---|---|
feat | 新功能 | feat(user): 新增用户注册接口 |
fix | 修复 bug | fix(order): 修复订单超时未关闭 |
docs | 文档变更 | docs(readme): 更新部署说明 |
style | 代码格式(不影响逻辑) | style: 统一 IDE 格式化 |
refactor | 重构 | refactor(user): 拆分 UserService |
perf | 性能优化 | perf(cache): 引入 Caffeine 二级缓存 |
test | 测试 | test(order): 添加订单超时单测 |
chore | 构建/工具变更 | chore(deps): 升级 Spring Boot 3.2 |
revert | 回滚 | revert: 回滚 feat(user): xxx |
实战示例
bash
# ✅ 规范的 commit
git commit -m "feat(user): 新增用户分页查询接口
- 支持按用户名、手机号模糊搜索
- 按创建时间倒序
- 分页参数:current、size
Closes #123"
# ✅ 修复
git commit -m "fix(order): 修复并发场景下库存超卖
原因:乐观锁字段未配置
方案:增加 version 字段 + 重试机制
Fixes #456"
# ❌ 不规范的 commit
git commit -m "update"
git commit -m "fix bug"
git commit -m "改一下"五、提交粒度
原则:一个 commit 一个原子变更。
bash
# ❌ 反例:一次 commit 改了一堆东西
git commit -m "重构 + 加新功能 + 修 bug"
# ✅ 正例:拆成多个 commit
git add user-refactor/
git commit -m "refactor(user): 拆分 UserService"
git add user-search/
git commit -m "feat(user): 新增搜索功能"
git add payment-bugfix/
git commit -m "fix(payment): 修复回调签名校验"好处:
- Code Review 容易
git revert可以单独撤销某个变更git bisect能精确定位 bug
六、Pull Request 规范
PR 标题
[类型] 模块 - 简述
[Feat] 用户管理 - 新增批量导入功能
[Fix] 订单服务 - 修复并发库存超卖PR 描述模板
markdown
## 改动内容
<!-- 简要描述本次改动 -->
## 改动原因
<!-- 为什么改、解决了什么问题 -->
## 关联 Issue
<!-- 关联的 Issue / Ticket -->
## 测试说明
<!-- 如何测试、是否覆盖所有场景 -->
## 截图(如涉及 UI)
<!-- 改动前 vs 改动后 -->
## Checklist
- [ ] 代码符合团队规约
- [ ] 已添加/更新单元测试
- [ ] 已更新相关文档
- [ ] 已与产品/设计确认
- [ ] 已自测通过PR 大小
bash
# ✅ 小而专注:< 300 行变更
# ❌ 巨型 PR:3000 行变更,没人 review经验法则:单 PR 改动的行数 ≤ 400 行。
七、Code Review 规范
Reviewer 视角
markdown
## 🎯 看什么
### 1. 业务正确性
- 是否解决了 Issue 描述的问题?
- 边界条件、异常情况是否覆盖?
### 2. 代码质量
- 命名是否清晰?
- 函数是否过长(> 50 行需重构)?
- 是否重复造轮子?
### 3. 测试覆盖
- 是否有单测?
- 测试用例是否覆盖核心场景?
### 4. 性能与安全
- 是否有 SQL 注入风险?
- 大数据量场景下性能如何?
- 是否有敏感信息泄露?
### 5. 规范
- 是否符合阿里规约?
- 是否有遗留 TODO / FIXME?反馈方式
markdown
# ❌ 反例(不友好)
"这写的是什么垃圾"
"你不会用 Optional 吗"
# ✅ 正例(建设性)
"这里如果用 Optional.ofNullable(user).map(User::getName).orElse(default) 会更优雅,参考 xxx 模块。"
"建议加个单元测试覆盖 userId 为空的场景。"
# 标记级别
🔴 必须改(MUST):阻塞合并
🟡 建议改(SHOULD):建议但不强制
🟢 讨论(MAY):纯讨论,可不采纳八、合并策略
Squash Merge
bash
# 把所有 commit 合并成一个,PR 干净
git merge --squash feature/user-login适合:功能分支,commit 多且杂乱时。
Merge Commit
bash
# 保留完整历史
git merge --no-ff feature/user-login适合:希望保留开发过程的 commit。
Rebase
bash
# 变基后线性历史
git rebase main
git push --force-with-lease适合:个人分支变整洁后再合并。
推荐:
- 功能 PR 用 Squash(清爽)
- hotfix 用 Merge Commit(保留紧急修复记录)
- 个人分支用 Rebase(整洁)
九、Git Hooks
pre-commit:提交前检查
bash
# .git/hooks/pre-commit
#!/bin/sh
echo "运行规约检查..."
mvn p3c:check -q
if [ $? -ne 0 ]; then
echo "❌ 阿里规约检查失败,请修复"
exit 1
fi
echo "运行单元测试..."
mvn test -Dtest=*QuickTest
if [ $? -ne 0 ]; then
echo "❌ 单元测试失败"
exit 1
fi
echo "✅ 检查通过"commit-msg:校验提交信息
bash
# .git/hooks/commit-msg
#!/bin/sh
commit_msg=$(cat "$1")
# 简单校验:必须以 feat/fix/docs 等开头
if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|chore|revert)"; then
echo "❌ Commit message 必须以 Conventional Commits 类型开头"
echo "示例: feat(user): 新增用户注册"
exit 1
fibash
# 用 commitlint 校验(更专业)
npm install --save-dev @commitlint/cli @commitlint/config-conventional
echo "module.exports = {extends: ['@commitlint/config-conventional']};" > commitlint.config.js十、保护分支
GitHub
yaml
# Settings → Branches → Branch protection rules
- main 分支:
✅ Require pull request reviews before merging
✅ Require approvals: 2
✅ Dismiss stale pull request approvals when new commits are pushed
✅ Require status checks to pass before merging
✅ Require linear history
✅ Include administrators
❌ Allow force pushesGitLab
yaml
# Settings → Repository → Protected branches
- main 分支:
Allowed to merge: Maintainers
Allowed to push: No one
Require code owner approval: Yes十一、紧急修复流程
bash
# ① 从 main 拉 hotfix 分支
git checkout main
git pull
git checkout -b hotfix/payment-bug
# ② 修复 + 测试
# ... 改代码 ...
git commit -m "fix(payment): 修复支付回调签名校验失败"
# ③ 合回 main 并打 tag
git checkout main
git merge --no-ff hotfix/payment-bug
git tag -a v1.5.1 -m "紧急修复支付 bug"
# ④ 合回 develop(如有)
git checkout develop
git merge --no-ff hotfix/payment-bug
# ⑤ 推送到远程
git push origin main --tags
git push origin develop
# ⑥ 删除 hotfix
git branch -d hotfix/payment-bug十二、本章小结
| 要点 | 关键 |
|---|---|
| 分支模型 | Git Flow(重)/ GitHub Flow(推荐)/ Trunk Based(最简) |
| 分支命名 | feature/* fix/* refactor/* hotfix/* |
| Commit | Conventional Commits(type(scope): subject) |
| 粒度 | 一个 commit 一个原子变更 |
| PR | < 400 行,描述完整,关联 Issue |
| Review | 建设性反馈,分级标记(必改 / 建议 / 讨论) |
| 合并 | Squash(功能)/ Merge Commit(hotfix)/ Rebase(个人) |
| 保护 | 主分支禁止 push、PR + 流水线 + 审批 |
动手练习
练习 1:基础题
按照 Conventional Commits 规范重写你最近 10 个 commit message,并配置 commitlint 校验。
练习 2:进阶题
配置 GitHub Flow:
- 拉
feature/*分支开发 - 提交规范的 commit
- 提交 PR,关联 Issue
- 通过流水线 + Review 后合并
练习 3:思考题
你的团队有 10 个开发者,如何用 Git 规范 + PR 模板 + 自动化检查避免"合代码就崩"?
下一章:第 82 章:综合实战项目 →