研发流程真正需要解决的,不只是“代码如何提交”,而是任何一次线上变更都能回答五个问题:为什么改、谁改的、改了什么、如何验证、出了问题怎样回退。
一种简单而有效的方法,是把项目管理系统中的需求编号或 Bug 编号作为贯穿整个研发流程的关联键。
一条贯穿研发流程的主线
假设项目管理系统中存在以下事项:
- 需求:
REQ-1428,增加订单导出功能; - 缺陷:
BUG-2381,修复导出文件中金额精度错误。
编号会依次出现在分支、Commit、Pull Request、测试记录、构建产物和发布记录中:
1 | 需求或 Bug |
这样无论从项目管理系统、代码仓库还是线上版本出发,都能反向找到完整上下文。
Commit 信息规范
推荐采用下面的格式:
1 | 【需求编号】- 增加xxx |
实际示例:
1 | 【REQ-1428】- 增加订单导出功能 |
如果团队希望继续区分变更类型,可以扩展为:
1 | 【REQ-1428】feat: 增加订单导出功能 |
编号负责连接项目管理系统,feat、fix、refactor 等类型负责生成变更日志和版本统计。两者承担不同职责,可以同时保留。
一条好 Commit 应该表达什么
标题说明结果,正文解释原因、关键方案和验证方式:
1 | 【BUG-2381】fix: 修复导出金额精度错误 |
避免使用“修改一下”“优化代码”“修复问题”这类无法独立理解的描述。
分支命名规范
分支名建议同时表达事项类型、编号和简短主题:
1 | git switch -c feature/REQ-1428-order-export |
推荐类型:
| 类型 | 使用场景 |
|---|---|
feature/ |
新需求或功能 |
bugfix/ |
普通缺陷修复 |
hotfix/ |
需要紧急发布的线上故障 |
refactor/ |
不改变外部行为的重构 |
chore/ |
依赖、构建或工程配置 |
分支应保持短生命周期。一个分支只处理一个事项,避免把多个需求混进同一个 Pull Request。
从领取任务到发布的完整流程
1. 需求准备
需求进入开发前至少具备:
- 唯一编号、目标和业务价值;
- 明确范围与不做事项;
- 可验证的验收标准;
- 接口、数据、权限和兼容性影响;
- 发布方式与回滚条件。
缺陷还应包含复现步骤、期望结果、实际结果、环境和必要日志。
2. 创建分支
1 | git switch main |
--ff-only 可以避免拉取时意外生成合并提交。如果团队使用 rebase 工作流,也应在团队规范中统一说明。
3. 小步提交
先检查变化,再选择性暂存:
1 | git status |
git add -p 可以逐块选择变更,防止调试代码、格式化噪声或无关文件混入 Commit。
一个 Commit 应保持逻辑完整:代码、必要测试和相关文档一起提交,同时确保它可以独立通过构建。
4. 提交 Pull Request
PR 标题继续携带编号:
1 | 【REQ-1428】增加订单导出功能 |
PR 描述建议包含:
- 关联事项与背景;
- 方案概述和关键取舍;
- 数据库、接口或配置变化;
- 测试范围和验证证据;
- 风险、监控指标与回滚方式;
- 页面或交互变化截图。
5. CI 与评审门禁
合并前至少执行:
- 格式检查与静态分析;
- 单元测试和必要的集成测试;
- 依赖和安全扫描;
- 构建可部署产物;
- Commit 或 PR 编号格式校验;
- 至少一名非作者评审通过。
高风险变更可以要求架构、数据库或安全负责人追加评审。
6. 发布与回溯
构建产物应记录 Git Commit SHA,并在发布记录中写入关联编号:
1 | 版本:v2.8.0 |
出现线上问题时,可以从版本找到 Commit,再从 Commit 找到编号、PR、测试证据和负责人。
自动校验 Commit 格式
团队可以在 CI 中校验标题。以下正则接受需求、Bug 和技术任务编号:
1 | ^【(REQ|BUG|TECH)-[0-9]+】(feat|fix|refactor|docs|test|chore|perf|ci): .+ |
一个简单的 Shell 检查示例:
1 | message="$(git log -1 --pretty=%s)" |
本地 Hook 可以尽早反馈,但真正的强制校验应放在服务端或 CI,因为客户端 Hook 可以被跳过。
Git 常用命令速查
查看状态和历史
1 | git status |
分支操作
1 | git branch --all |
暂存与提交
1 | git add <file> |
--amend 会重写最近一次 Commit。已经推送且多人使用的分支,不应随意改写历史。
临时保存工作
1 | git stash push -m "REQ-1428 未完成的导出页面" |
撤销和恢复
1 | # 丢弃工作区中某个文件的未提交修改 |
不要在不理解影响时使用 git reset --hard 或强制推送。共享分支优先使用 git revert 保留可审计历史。
同步主分支
1 | git fetch origin |
团队应统一选择 rebase 或 merge 策略。不要为了“历史好看”反复重写已经进入共享分支的 Commit。
查找问题来源
1 | git log -S "关键代码" --oneline |
git bisect 可以通过二分法定位引入问题的 Commit,配合自动化测试效果更好。
Git Submodule 的适用场景
Submodule 是嵌入在主仓库中的独立 Git 仓库。主仓库不直接保存它的全部内容,而是记录子仓库的一个确定 Commit。
适合场景:
- 多个项目共享但需要独立发布的 SDK;
- 主项目需要锁定第三方源码的确定版本;
- 权限、发布节奏或历史必须独立的模块。
如果模块必须与主项目频繁原子修改,Monorepo、包管理器或制品仓库通常更简单。
添加 Submodule
1 | git submodule add https://git.example.com/team/common-sdk.git libs/common-sdk |
该操作会创建或更新 .gitmodules,同时让主仓库记录子模块当前 Commit。
克隆包含 Submodule 的项目
推荐一次性递归克隆:
1 | git clone --recurse-submodules https://git.example.com/team/app.git |
如果已经普通克隆:
1 | git submodule update --init --recursive |
其中 init 根据 .gitmodules 初始化本地配置,update 检出主仓库记录的 Commit,recursive 继续处理嵌套子模块。
更新 Submodule
按主仓库锁定版本更新
切换分支或拉取主仓库后执行:
1 | git pull --ff-only |
这不会自动追踪子模块远端最新版本,而是恢复到主仓库记录的确定 Commit,因此构建具备可复现性。
主动升级到子模块新版本
1 | cd libs/common-sdk |
主仓库中的这次 Commit 记录的是新的子模块 Commit 指针。
也可以根据 .gitmodules 中配置的分支执行:
1 | git submodule update --remote --merge libs/common-sdk |
升级后必须提交主仓库中的指针变化,否则其他开发者和 CI 仍会使用旧版本。
修改 Submodule 自身代码
进入子模块后,它就是一个独立仓库:
1 | cd libs/common-sdk |
子模块 PR 合并后,回到主仓库更新并提交指针:
1 | cd libs/common-sdk |
因此一次跨仓库需求通常有两组 Commit 和 PR,它们应引用同一个需求编号。
Submodule 常见问题
子模块目录为空
1 | git submodule update --init --recursive |
显示 modified content
先查看子模块内部状态:
1 | git -C libs/common-sdk status |
确认是未提交修改、未跟踪文件,还是当前 Commit 与主仓库记录不一致。
修改了仓库地址
更新 .gitmodules 后同步本地配置:
1 | git submodule sync --recursive |
子模块处于 detached HEAD
git submodule update 检出固定 Commit 时出现 detached HEAD 是正常现象。若要开发子模块,先显式切换或创建分支:
1 | git -C libs/common-sdk switch main |
查看所有子模块版本
1 | git submodule status --recursive |
团队使用 Submodule 的约定
为了避免“我本地能运行,CI 却缺代码”,建议统一以下规则:
- CI 克隆必须启用递归 Submodule;
- 子模块升级和主仓库指针更新分成清晰 Commit;
- 子模块 Commit 必须已推送,主仓库才能引用;
- 不直接在 detached HEAD 上开发;
- 发布记录同时列出主仓库与关键子模块 SHA;
- 修改
.gitmodules后执行并记录同步步骤; - 定期检查失效地址、权限和长期未升级依赖。
最终落地模板
一次需求可以按下面的最小模板执行:
1 | 事项:REQ-1428 |
规范的价值不在于让 Commit 更整齐,而在于把需求、代码、测试、发布和线上结果连接成一条可以搜索、审计和复盘的证据链。
参考资料
资料与流程复核日期:2026-08-22。团队应再以自身代码托管平台、分支保护和工作项规则为准。
评论