3、代码管理:Git仓库搭建、分支策略(Git Flow)、代码拉取与版本锁定

代码管理这事儿,说大不大,说小不小。我见过不少团队,业务逻辑写得挺溜,结果一到多人协作就乱成一锅粥——覆盖代码、丢失提交、上线版本对不上……说白了,就是没把代码管理当回事。

这一章,咱们就聊聊验证服务部署里,代码管理到底该怎么搞。我会从仓库搭建、分支策略、到版本锁定,一条线讲清楚。

3.1 Git仓库搭建:别小看这一步

仓库搭建听起来简单,git init 一下不就完了?嗯,但生产环境里,我建议你至少要考虑三个问题:权限、备份、和命名规范。

3.1.1 仓库选型

我个人习惯用 GitLab 自建,或者用 Gitee / GitHub 的私有仓库。选哪个不重要,重要的是——权限粒度要够细。验证服务涉及敏感配置和部署脚本,不能谁都能 push 到 master。

平台 优点 缺点
GitLab 自建 权限控制灵活、CI/CD 集成好 需要维护服务器
GitHub 生态好、社区活跃 私有仓库有数量限制(免费版)
Gitee 国内速度快、免费私有库 部分高级功能收费

3.1.2 仓库结构建议

我建议一个验证服务项目,至少拆成两个仓库:

  • 验证服务代码库:放业务代码、测试用例、部署脚本。
  • 配置与版本库:放环境配置、版本锁文件、密钥模板(注意:密钥本身不要入库)。

为什么要拆?我在项目中遇到过,配置文件和代码混在一起,每次改个数据库地址都要走一遍完整的代码审查流程,效率极低。拆开之后,配置变更可以单独走审批,灵活多了。

我的小习惯: 仓库根目录下一定要放 .gitignore 和 README.md。.gitignore 提前把日志、临时文件、IDE 配置过滤掉,省得后面手忙脚乱。

3.2 分支策略:Git Flow 还是其他?

分支策略这东西,没有银弹。但如果你问我,验证服务部署最适合什么?我会说——Git Flow 的简化版。

为什么不是标准的 Git Flow?标准版太重了,有 hotfix、release、develop、feature 五六个分支,小团队根本玩不转。我踩过这个坑,有一次为了修一个线上 bug,在 hotfix 和 release 之间来回合并,最后搞出了冲突,差点耽误上线。

3.2.1 我推荐的分支模型

说白了,就三个核心分支:

  • master:只接受来自 release 或 hotfix 的合并。永远保持可部署状态。
  • develop:日常开发的主战场。feature 分支从这里拉,合并回这里。
  • release/x.y.z:从 develop 拉出,只做 bug 修复和版本号更新,合并到 master 和 develop。

再加上两个辅助分支:

  • feature/xxx:从 develop 拉,开发完合并回 develop。
  • hotfix/xxx:从 master 拉,修完合并回 master 和 develop。

核心原则: master 永远是稳定的。任何未经测试的代码,都不允许直接推到 master。

3.2.2 分支命名规范

没有规范的分支名,就是灾难。我见过有人用 "fix-bug"、"test" 这种名字,过两周自己都忘了是干嘛的。

我建议这样命名:

feature/<模块名>-<简短描述>
release/<版本号>
hotfix/<问题编号>-<简短描述>

举个例子:

feature/deploy-script-optimize
release/1.2.0
hotfix/INC-3421-fix-timeout

3.3 代码拉取与版本锁定

代码拉取,听起来就是 git clone 和 git pull。但验证服务部署里,这里有个关键点——版本锁定。

你想想看,如果部署脚本里写的是 git pull 拉最新代码,那每次部署的结果都可能不一样。今天能跑,明天可能就挂了。为什么?因为有人中间合入了未测试的代码。

3.3.1 版本锁定的做法

我建议用 Git Tag + 版本锁文件 的方式。

  1. 每次发布前,在 master 上打一个 tag,比如 v1.2.0。
  2. 在部署脚本里,明确指定拉取某个 tag 的代码。
  3. 把 tag 信息记录到一个版本锁文件(比如 VERSION_LOCK)中。

示例版本锁文件内容:

# VERSION_LOCK
# 格式:服务名 版本号 部署日期
verify-service v1.2.0 2025-03-15
verify-config v1.0.1 2025-03-14

3.3.2 部署时的拉取流程

我习惯的部署脚本核心逻辑是这样的:

#!/bin/bash
# 部署脚本片段
TAG=$(cat VERSION_LOCK | grep verify-service | awk '{print $2}')
cd /opt/verify-service
git fetch --tags
git checkout tags/$TAG -b deploy-$TAG
# 然后执行构建和启动

为什么要 checkout 到一个新分支?因为这样部署环境里的代码是只读的,不会因为误操作被修改。

我曾经踩过的坑: 有一次部署脚本里直接用了 git pull,结果有人往 master 上 push 了一个未编译通过的提交,部署脚本拉下来后服务直接起不来。从那以后,我所有的部署脚本都强制指定 tag,绝不拉最新代码。

3.4 本章知识体系

下面这张图,把代码管理的核心流程串起来了。你可以把它当作一个检查清单。

代码管理核心流程 代码管理核心流程 1. 仓库搭建 2. 分支策略 3. 版本锁定 • 权限控制 • 仓库拆分 • .gitignore • README • master 稳定 • develop 开发 • release 发布 • hotfix 修复 • Git Tag • 版本锁文件 • 部署指定tag • 只读分支 feature → develop → release → master ✅ 可部署的稳定版本 核心原则:master 永远稳定,版本锁定确保可重复部署

3.5 避坑指南

最后,分享几个我亲身踩过的坑,希望能帮你省点时间。

  • 不要直接在 master 上改代码。哪怕只是改个注释,也走分支流程。我曾经图省事,直接在 master 上改了个配置项,结果忘了 push,别人部署时拉到了旧版本,排查了半天。
  • Tag 一旦打了就不要删。删 Tag 会导致历史混乱,尤其是多人协作时。如果打错了,打个新 Tag 覆盖,而不是删除旧的。
  • 版本锁文件要纳入版本控制。锁文件本身要入库,这样才能追溯每次部署用的是哪个版本。我见过有人把锁文件放在 .gitignore 里,结果部署环境各自为政,乱成一团。
  • 部署脚本里不要用 git pull。用 git fetch + git checkout tag,确保部署的代码是确定的。
一个小技巧: 在 CI/CD 流程中,每次构建成功后自动打一个 tag,tag 名包含构建时间和 commit hash。这样出了问题,可以快速定位到是哪个构建版本。

代码管理做到位了,后面的部署流程才能稳。说白了,这就是地基活——地基打不牢,上面盖多高都白搭。