别再“一把梭”了:我靠 Git 分支策略躲过三次生产事故
别再“一把梭”了:我靠 Git 分支策略躲过三次生产事故
刚工作那会儿,我们团队只有一个人负责发布,用的还是最原始的“一把梭”模式:所有人往 main 分支直接推,发版时打个 tag,完事。听起来很荒唐,但当时业务量小,居然也这么跑了一年多。
直到有一次大促前,我和另一个同事同时往 main 推了代码。他的功能是“优惠券核销”,我的是“订单导出”。两个功能毫无关联,但我的代码里不小心引入了一个空指针,导致应用启动失败。结果就是——整个发布卡住,优惠券核销也上不去,运营在旁边急得跳脚。那天晚上我加班到凌晨两点,一边回滚一边想:这锅背得真冤,但问题根源明明是流程。
后来我们痛定思痛,引入了 Git Flow 的简化版,并严格执行。几年下来,这个策略至少帮我躲过了三次生产事故,每次回想都觉得后怕。
第一次:功能未测完,但紧急修复必须上线
某天下午,客服系统发现一个支付金额显示错误的 Bug,需要立刻修复。但当时 main 分支上还有我正在开发的“会员积分”功能,只写了一半,根本跑不起来。如果是以前,我只能硬着头皮把半成品代码注释掉,或者本地 stash 后手动挑提交。但那次,我们因为用了 develop 作为集成分支,生产对应 main,紧急修复直接从 main 拉出 hotfix 分支。我花 10 分钟修完 Bug,合并回 main 和 develop,单独发布 main。而我的半成品代码安然躺在 develop 上,完全不受影响。那次之后我明白:环境隔离不是浪费时间,是给紧急操作留出的安全通道。
第二次:代码评审拦住了“隐形炸弹”
我们规定,任何功能合并进 develop 都必须走 Merge Request(MR),且至少两人评审。有一次我写了一个“订单自动取消”的定时任务,自测没问题就提交了 MR。同事评审时指出:取消逻辑里没有校验订单状态,如果订单已经支付,定时任务可能会把它误取消。这个 Bug 在测试环境极难触发,因为测试数据都是新订单。但评审拦住了它。如果直接推 main,这绝对是个生产事故。从那以后,我再也不嫌 MR 麻烦,反而主动要求别人多看看我的代码——多一双眼睛,就少一个深夜告警。
第三次:回滚只需一秒钟
最惊险的一次,我们上线了一个“商品推荐”功能,发布后一切正常。但两小时后,监控系统发现数据库 CPU 飙升到 90%。我们怀疑是新功能的某个慢查询导致的,需要立刻回滚。因为发布时我们打了一个 Git tag,并且发布流程支持一键回滚到上一个 tag。运维同学点了一下按钮,系统瞬间回到上一个版本,CPU 立刻降下来。事后复盘,确实是推荐算法里漏了一个索引。但如果没有分支和 tag 策略,回滚意味着重新拉代码、打包、部署,至少十几分钟——对于当时的流量,十几分钟足够让数据库彻底挂掉。
这三次经历让我彻底信服:好的分支策略不是形式主义,是团队的交响乐指挥。它让每个人的工作互不干扰,让紧急修复有专用通道,让代码评审成为质量关卡,让回滚变成一键操作。
现在,我们团队的规则很简单:
main:永远对应生产环境,受保护,禁止直接推送。develop:集成测试环境,功能完成后合并至此。feature/*:个人功能分支,从develop拉取,完成后 MR 回develop。hotfix/*:紧急修复,从main拉取,修复后同时合并main和develop。
每次有新同事加入,我都会花半小时讲这套流程,并告诉他们:Git 分支不是给自己分的,是给团队买的保险。今天多花一分钟遵守规范,未来可能少熬一整夜。
如果你现在的团队还在“一把梭”,不妨从明天开始,先保护 main 分支,再引入 develop。不用一步到位,但每一步都算数。毕竟,我们写代码是为了创造价值,不是为了半夜被叫起来救火。
- 点赞
- 收藏
- 关注作者
评论(0)