工作流与最佳实践
Git 是工具,工作流是方法。好的工作流 + 好的习惯 = 高效的团队协作。
主流工作流
Git Flow(经典分支模型)
main ─●────────────●──────────────●──→
\ / \ /
release ●──●──●──● \ /
\ /
develop ──●──●──●──●──●──●──●──●──●──→
\ / \ /
feature ●──●──● ●──●──●| 分支 | 用途 | 来自 | 合并到 |
|---|---|---|---|
main |
生产代码 | — | — |
develop |
开发主线 | main |
main |
feature/* |
新功能 | develop |
develop |
release/* |
发布准备 | develop |
main + develop |
hotfix/* |
紧急修复 | main |
main + develop |
适合:有固定发布周期的传统软件项目。缺点:分支多,流程重。
GitHub Flow(简洁版)
main ─●────●────●────●────●──→
\ / / /
feature ●──● / /
/ /
●──●──● /
/
●──●──●原则:
main始终可部署- 所有工作从
main创建描述性分支 - 随时推送到远程分支
- 通过 Pull Request 合并
- 合并后立即部署
适合:持续部署的 Web 应用、SaaS 项目。GitHub、Netflix 等广泛使用。
Trunk-Based Development(主干开发)
main ─●──●──●──●──●──●──●──→ (每天多次合并)
│ │ │ │
└───┘ └───┘ (短生命周期分支,< 1 天)原则:
- 只有一条长期分支(trunk/main)
- 分支生命周期极短(几小时到一天)
- 通过 Feature Flag 控制未完成功能
- 高频小批量合并
适合:成熟的 DevOps 团队,有完善的 CI/CD 和测试体系。Google、Facebook 都用此模型。
工作流选择
| 工作流 | 分支数 | 合并频率 | 团队规模 | 发布节奏 |
|---|---|---|---|---|
| Git Flow | 多 | 低 | 大团队 | 固定周期 |
| GitHub Flow | 少 | 中 | 中小团队 | 随时部署 |
| Trunk-Based | 极少 | 极高 | 成熟团队 | 持续部署 |
Commit 规范
Conventional Commits(约定式提交)
<type>(<scope>): <description>
[optional body]
[optional footer]type 类型:
| Type | 说明 |
|---|---|
feat |
新功能 |
fix |
修复 bug |
docs |
文档变更 |
style |
代码格式(不影响功能) |
refactor |
重构(非新功能、非修复) |
perf |
性能优化 |
test |
添加/修改测试 |
chore |
杂务(构建、依赖等) |
ci |
CI/CD 变更 |
build |
构建系统变更 |
# 示例
feat(auth): add JWT authentication
fix(api): handle null response in user endpoint
refactor(db): simplify connection pool logic
docs(readme): update installation instructions
chore(deps): bump lodash to 4.17.21
# 破坏性变更(BREAKING CHANGE)
feat(api)!: drop support for v1 endpoints
# 或
feat(api): migrate to v2 API
BREAKING CHANGE: v1 API endpoints are no longer available.💡 使用 Conventional Commits 可以自动生成 CHANGELOG 和语义化版本号。配合
commitlint工具可做提交信息校验。
提交信息的七个规则
- 标题与正文之间空一行
- 标题不超过 50 字符
- 标题首字母大写(中文不限)
- 标题不用句号结尾
- 标题用祈使语气(“fix” 而不是 “fixed”)
- 正文每行不超过 72 字符
- 正文解释 做了什么 和 为什么,而不是"怎么做"
# ✅ 好的提交信息
fix: prevent racing of requests
Introduce a request id and a reference to the latest request. Dismiss
incoming responses other than the latest one.
Remove timeouts which were previously used to mitigate the racing issue
but are now unnecessary.
Closes #123
# ❌ 不好的提交信息
fixed bug
updated code
wip
各种修改分支命名规范
<type>/<description>
feature/login-with-oauth
fix/null-pointer-in-parser
hotfix/critical-security-patch
chore/update-dependencies
refactor/user-service
docs/api-guide日常操作最佳实践
提交前
-
git status确认状态 -
git diff --staged检查暂存区内容 - 不要
git add .一把梭,先用git status看一眼 - 大改动考虑
git add -p分批提交
分支操作
# ✅ 创建 feature 分支前先同步 main
git checkout main
git pull --rebase
git checkout -b feature/new-work
# ✅ 定期从 main 同步(用 rebase 保持线性历史)
git fetch origin
git rebase origin/main
# ✅ 推送前整理提交
git rebase -i HEAD~3 # squash 细碎的修复提交
git push --force-with-lease # 仅在个人分支
# ❌ 不要在 main 上直接开发
# ❌ 不要 force push main/master合并时
# ✅ 合并 feature 到 main 时,用 --no-ff 保留分支痕迹
git checkout main
git merge --no-ff feature
# ✅ 或者先 rebase 再 merge(保持线性)
git checkout feature
git rebase main
git checkout main
git merge feature安全实践
敏感信息处理
# ❌ 绝不要将密码、密钥、token 提交到 Git
# 如果已经提交了:
# 1. 立即轮换泄露的密钥/密码
# 2. 用 git filter-repo 清除历史(不只是 reset)
git filter-repo --path secrets/config.yml --invert-paths --force
git push origin --force --all
# 3. 通知团队成员重新 clone
# ✅ 使用环境变量或外部密钥管理
# .env 文件应加到 .gitignore.gitignore 安全项
# 永远忽略
.env
.env.*
*.pem
*.key
secrets/
credentials/
*.p12签名验证
# 配置 GPG 签名
git config --global user.signingkey <GPG-KEY-ID>
git config --global commit.gpgsign true
# 签名 commit
git commit -S -m "Signed commit"
# 签名 tag
git tag -s v1.0 -m "Signed release"
# GitHub/GitLab 会显示 Verified 标记提交历史维护
好的历史长什么样
git log --oneline
# a1b2c3d Add login rate limiting
# d4e5f6g Fix OAuth token refresh bug (#234)
# g7h8i9j Refactor auth middleware
# j0k1l2m Add JWT authentication
# m3n4o5p Initial project setup坏的提交历史
# wip
# fix test
# fixed
# update
# 修改了bug
# 再次修复
# oops
# tmp💡 原则:每个 commit 应该是一个逻辑上完整的、可单独 review 的最小变更。未来的你(和同事)通过
git log来理解项目历史。
常见陷阱汇总
| 🚨 陷阱 | 说明 | ✅ 正确做法 |
|---|---|---|
| Force push 到共享分支 | 覆盖团队成员的提交 | 仅 force push 个人分支,且用 --force-with-lease |
| rebase 已推送的提交 | 改写他人已基于的 commit hash | 只 rebase 本地未推送的提交 |
git add . 无脑用 |
可能混入调试代码、临时文件 | 先 git status,必要时 git add -p |
| commit 信息无意义 | “fix”、“update"没实际信息 | 遵循 Conventional Commits 规范 |
| 提交大文件 | 仓库膨胀,clone 变慢 | 使用 Git LFS 或 .gitignore |
| 在 main 上开发 | 没有分支隔离 | 总是在 feature 分支上工作 |
| 忘记 .gitignore | 构建产物、依赖被提交 | 项目创建时就建立 .gitignore |
| 提交敏感信息 | 密钥泄露到仓库历史 | .env 加入 .gitignore,泄露后立即轮换密钥 |
pull 产生无意义 merge commit |
本地和远程分叉时自动 merge | 配置 pull.rebase true 或 pull.ff only |
| 长时间不推送 | 本地 commit 堆积,冲突风险大 | 每天 push,小批量提交 |
日常操作 Checklist
每天开始
-
git fetch --prune更新远程分支信息 - 在正确的分支上开发(不在 main)
开发中
- 小的、有意义的 commit
- 提交信息遵循规范
- 定期
git stash或 commit WIP
准备推送
-
git status确认变更都是想要的 -
git diff --staged检查暂存内容 -
git rebase -i整理提交历史(可选) -
git pull --rebase同步远程
合并前
- 代码已经过 Review
- CI 通过
- 提交历史已整理干净