第四章:版本控制:Git与CI/CD的初恋

从git init到git flow,搭建自动化代码发布流水线。

说实话,我见过太多运维同事把Git当成一个“备份工具”在用。每天就是git add、git commit、git push三板斧。这其实挺可惜的。Git真正的威力,在于它能把你的代码发布流程变得像流水线一样丝滑。今天我们就聊聊,怎么让Git和CI/CD谈一场“初恋”。

4.1 从git init开始:你的第一个仓库

每个项目都始于一个简单的命令:git init。但你真的理解它在做什么吗?

mkdir my-ops-project
cd my-ops-project
git init

执行完这三行,你的项目就拥有了一个隐藏的.git目录。这里面存着所有的版本历史。我个人习惯在项目一开始就初始化仓库,哪怕只有一行README。为什么?因为后面你随时可以回退到任何一个状态。

小技巧: 我建议你在git init之后,立刻创建一个.gitignore文件。把那些不需要版本控制的文件(比如日志、临时文件、密码配置)提前排除掉。我曾经因为忘记加.gitignore,把几百MB的日志文件推到了仓库里,那叫一个酸爽。

4.2 分支策略:别再用master一条道走到黑

很多新手喜欢所有代码都往master分支上推。这其实是个坏习惯。你想想看,如果线上出了bug,你正在修复,结果同事把未测试的新功能也推上来了,怎么办?

我推荐使用Git Flow模型。它把分支分成了几类:

分支类型 命名规则 用途
主分支 master/main 生产环境代码,只允许合并,不允许直接提交
开发分支 develop 日常开发集成,所有功能分支从这里拉出
功能分支 feature/xxx 开发新功能,完成后合并到develop
发布分支 release/x.x.x 准备发布时从develop拉出,只修bug,不添功能
热修复分支 hotfix/xxx 紧急修复线上bug,从master拉出,修复后合并回master和develop

嗯,这里要注意:热修复分支是直接从master拉出来的。为什么?因为线上问题等不及你从develop走一遍流程。我曾经有一次线上服务挂了,就是因为等develop的测试流程,多耽误了半小时。

4.3 搭建CI/CD流水线:让机器替你干活

手动部署?那是上个时代的事了。现在我们要做的是:代码一推,自动测试、自动构建、自动部署。说白了,就是把“人肉运维”变成“自动化运维”。

我以GitLab CI为例,展示一个典型的流水线配置:

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

unit-test:
  stage: test
  script:
    - echo "运行单元测试..."
    - pytest tests/

build-image:
  stage: build
  script:
    - echo "构建Docker镜像..."
    - docker build -t my-app:$CI_COMMIT_SHORT_SHA .
    - docker push registry.example.com/my-app:$CI_COMMIT_SHORT_SHA

deploy-staging:
  stage: deploy
  script:
    - echo "部署到测试环境..."
    - kubectl set image deployment/my-app my-app=registry.example.com/my-app:$CI_COMMIT_SHORT_SHA
  only:
    - develop

deploy-production:
  stage: deploy
  script:
    - echo "部署到生产环境..."
    - kubectl set image deployment/my-app my-app=registry.example.com/my-app:$CI_COMMIT_SHORT_SHA
  only:
    - master
  when: manual

看到when: manual了吗?这是生产环境部署的“安全锁”。只有你手动点击确认,才会真正执行。我见过太多因为自动部署到生产环境而翻车的事故了。

核心逻辑: 每次代码推送到develop分支,自动触发测试和构建,并部署到测试环境。只有推送到master分支,并且你手动确认后,才会部署到生产环境。这就是“门禁”机制。

4.4 避坑指南:我踩过的那些坑

做CI/CD这么多年,我踩过的坑能写一本书。这里挑几个最常见的:

  • 分支保护没开:我曾经允许任何人直接推送到master。结果有一天,一个实习生不小心把未测试的代码推上去了,线上直接挂了半小时。从那以后,我强制开启了分支保护,只有通过Merge Request才能合并。
  • 测试环境与生产环境不一致:测试环境用的是MySQL 5.7,生产环境是8.0。结果测试通过,上线就报错。我现在要求所有环境的依赖版本必须完全一致,用Docker镜像来保证。
  • 密钥硬编码:有人把数据库密码直接写在代码里,然后推到了公开仓库。嗯,后果你懂的。现在我用CI/CD的变量功能,把密钥存在系统里,代码里只引用变量名。
警告: 永远不要在代码里硬编码任何敏感信息!使用CI/CD的Secret Variables功能,或者用Vault这样的密钥管理工具。

4.5 知识体系:一张图看懂Git与CI/CD

下面这张SVG图,展示了从代码提交到生产部署的完整流程。你可以把它当作本章的“知识地图”。

Git与CI/CD流水线架构图 开发者 git push Git仓库 Webhook触发 CI/CD流水线 测试环境部署 Docker镜像构建 镜像仓库 手动确认 生产环境部署 分支策略 • master → 生产环境 • develop → 测试环境 • feature/* → 功能开发 安全门禁 • 代码审查(MR) • 自动化测试 • 手动确认部署

这张图里,你看到的是从“开发者提交代码”到“生产环境部署”的完整链路。每个环节都有对应的分支策略和安全门禁。说白了,就是让机器帮你做那些重复的、容易出错的事情,而你只需要关注代码质量和业务逻辑。

4.6 实战:搭建一个最小化的CI/CD流水线

理论说完了,我们来点实际的。假设你有一个简单的Python Web应用,怎么用GitLab CI搭建流水线?

  1. 创建仓库并初始化git init,然后推送到GitLab。
  2. 编写.gitlab-ci.yml:定义test、build、deploy三个阶段。
  3. 配置Runner:GitLab需要Runner来执行任务。你可以用共享Runner,也可以自己搭建。
  4. 设置环境变量:把数据库密码、API密钥等敏感信息存到CI/CD的Variables里。
  5. 测试流水线:随便改个文件,推送到develop分支,看看流水线是否自动触发。
我的经验: 第一次搭建流水线时,别追求完美。先让“代码推送→自动测试→自动构建”这个最小闭环跑通。后面再慢慢加部署、加通知、加安全扫描。一口吃不成胖子。

嗯,Git和CI/CD的“初恋”就聊到这里。记住,版本控制不是终点,自动化才是。当你看到代码一推,流水线自动跑起来,测试通过,镜像构建成功,然后一键部署到生产环境——那种感觉,真的很爽。

专注资料整理