Git 工作流
选择从单人到团队可扩展的分支模型和提交约定。
为什么
分支模型决定你多频繁合并以及每次合并多痛。主干开发(短命分支、每日合并)让集成痛苦接近零,因为冲突小且新鲜。Git-flow(feature/develop/release/hotfix 分支)感觉安全但产生长命分支,积累周级合并冲突。Conventional Commits(feat:、fix:、chore:)加在任一模型上,免费给你自动生成 changelog 和语义版本 bump。选择不如一致性重要:混用两种模型的团队有两者的最差。
何时使用
第二个贡献者加入之前。文档化约 15 分钟。团队超 5 人或每日发 prod 时重新审视。
如何做
1. ≤10 人或每日部署选主干;大团队有发布经理选 git-flow - 主干:从 main 分支,24h 内 PR,合回,删分支 - 在 CONTRIBUTING.md 文档化选择,没人猜 2. 采用 Conventional Commits 提交消息格式 - feat: 新功能,fix: 修 bug,chore: 工具,refactor: 无行为变化 - 破坏性变更:feat!: 或 feat(scope)!: + BREAKING CHANGE: footer 3. 用 commitlint + husky 强制格式 - pnpm add -D @commitlint/cli @commitlint/config-conventional - .husky/commit-msg: npx --no-install commitlint --edit $1 4. 在 GitHub 仓库设置里开 squash-merge - Squash 合并在 main 上每个 PR 产生一个干净提交 - PR 标题变提交主题——也在那里强制 conventional 格式 5. 在 CI 加 auto-changelog 或 release-please 步骤 - 合入 main 时,从提交历史 bump 版本 + 生成 CHANGELOG.md
示例
# 功能 PR 生命周期(主干开发)
git checkout main && git pull
git checkout -b feat/checkout-session
# ... 写代码,用 conventional 格式提交 ...
git commit -m "feat(checkout): 新增 stripe 支付意图创建"
git push -u origin feat/checkout-session
# 开 PR → CI 跑 → 评审 → squash 合入
# main 现在有:"feat(checkout): 新增 stripe 支付意图创建 (#42)"
# commitlint 配置(commitlint.config.js)
module.exports = { extends: ["@commitlint/config-conventional"] };常见问题
- ⚠长命 feature 分支分叉一周,要 2 小时合并冲突会话。
- ⚠合并提交交错历史,git bisect 无法二分查找破坏性提交。
- ⚠不一致的提交消息('stuff'、'fix'、'wip')让 changelog 无用、git log 不可搜。
- ⚠分支前忘拉 main,PR 立即与昨天合入的工作冲突。
最佳实践
- ✓分支最大年龄 2 天——PR 更老就拆分或先合就绪部分,新 PR 继续。
- ✓只用 squash 合并,main 每个 PR 一个提交——bisect 和 revert 都变简单。
- ✓在 PR 标题上跑 commitlint(非仅提交),squash 合并消息保持 conventional。
- ✓开 PR 前而非评审后 rebase 到 main——保持评审者看到的 diff 干净。