Git 是开发者的日常工具,但使用 Git 的方式——从分支策略到提交信息格式——每个人和每个团队都可能不一样。一个好的工作流能够让协作变得顺畅,而一个混乱的工作流则会让代码库和历史变得难以理解和维护。最近我整理了几种常见的 Git 工作流和提交规范,这里做一下记录。
先看三种最主流的分支策略。Git Flow 是最早被广泛采用的一种,它的分支类型非常丰富:main 分支存放正式发布的代码,develop 分支是日常集成的分支,feature 分支用于开发新功能,release 分支用于准备发布版本,hotfix 分支用于线上紧急修复。这种模式对于需要严格把控发布节奏的大中型项目来说是一个完整且可靠的方案,但对于开发节奏较快的项目来说可能会显得比较繁重。GitHub Flow 则简化了很多——只有 main 和 feature 两种分支。开发者在 feature 分支上开发并通过 Pull Request 合并到 main 分支,合并之后立即部署。这种模式适合持续交付节奏的项目,从开发到上线的周期最短。Trunk-Based Development(主干开发)更进一步,开发者直接在一个主干上提交,避免了长期存在的功能分支带来的合并冲突风险,但它对开发者的提交粒度和代码质量要求最高。
提交信息规范方面,Conventional Commits(约定式提交)是目前使用范围最广的一种规范。它的基本格式是 type(scope): description,类型包括 feat(新功能)、fix(修复)、docs(文档)、style(格式)、refactor(重构)、test(测试)、chore(构建工具或辅助工具)等。这种规范的结构化程度高、可读性好,而且可以被自动化工具解析——比如你可以根据提交类型自动生成 Changelog、自动决定版本号的升级方式(major、minor、patch)。搭配上 commitlint 和 husky 这类工具,可以在提交的时候自动检查提交信息格式是否符合规范。
写一段好的提交信息,除了遵循格式规范外,还有一个重要的原则:让未来的读者能够理解你做了什么以及为什么这么做。一段好的提交信息应该解释「why」,而不仅仅是「what」——因为「what」可以从代码的 diff 中看出来。比如 'Fix login redirect loop when session expires' 就比 'Fix login bug' 清晰得多。还有一个小的建议是尽量保持每次提交的粒度适中——不要在一个提交里混入多个不相关的改动,也不要把一个改动的不同部分拆成太多过于琐碎的提交。
在 Release 方面,无论是 GitHub Flow 还是 Git Flow,都应该使用 Tag 来标记发布的版本号。Tag 和 commitlint 配合 conventional-changelog 这类工具,可以完全自动地生成结构化的 Release Notes——你只需要保证每次提交的信息格式规范,剩下的都可以交给工具来处理。