Files
zhuangang/topics/devops/git/scenarios/hotfix-and-leaked-secret.md
T

4.7 KiB
Raw Blame History

id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week
id title type domain stack tags level prerequisites est_hours related week
devops.git.scenario.hotfix-and-leaked-secret 线上紧急修复和密钥误提交:热修复分支、cherry-pick、清理历史和轮换密钥 scenario devops
git
cicd
热修复
cherry-pick
密钥泄露
历史清理
安全
intermediate
devops.git.merge-rebase-recovery
1.5
devops.git.interview
devops.cicd.pipeline
8
15

线上紧急修复和密钥误提交:热修复分支、cherry-pick、清理历史和轮换密钥

业务背景与问题

团队按“release 分支发版”的方式工作:main 上已经合入了下个版本的多个功能(未测试完),线上运行的是 release/1.4。周五下午出现两件事:

  1. 线上 1.4 版本有一个金额计算的 bug,需要马上修复,但不能把 main 上未测试的功能带上线。
  2. 有同事把含有大模型 API Key 的 .env 文件提交并推送到了远程仓库。

约束

  • 热修复要在一小时内上线,而且下个版本也必须包含这个修复。
  • 仓库在公司内部平台上,有十几个人已经拉取过包含密钥的提交。

方案设计

热修复

  1. 从线上版本的标签 / release 分支创建 hotfix/amount-rounding;
  2. 修复 + 补测试,走合并请求和 CI,合入 release/1.4,打标签 v1.4.1 发布;
  3. 把修复提交 cherry-pick 到 main(或从 release 合并回 main),保证下个版本不会“复活”这个 bug。

密钥泄露——顺序很重要:

  1. 第一时间轮换密钥:在模型服务商控制台作废旧 Key、生成新 Key,并更新部署环境的密钥配置。只要密钥进过远程仓库,就必须当作已经泄露,清理历史不能代替轮换。
  2. 检查旧 Key 的调用记录,确认是否有异常使用。
  3. 删除文件并加入 .gitignore;提供 .env.example。
  4. 评估是否需要清理历史:用 git filter-repo 从所有历史中移除文件,强制推送,通知所有人重新克隆;托管平台上的缓存、合并请求、fork 中可能仍有副本,需要联系平台管理员。
  5. 预防:提交前钩子扫描密钥(本仓库的 tools/check_sensitive.py),CI 中也执行密钥扫描。

关键代码

# 热修复
git switch -c hotfix/amount-rounding v1.4.0
# ……修改代码、补测试……
git commit -am "fix(order): 金额四舍五入改为银行家舍入前先转换为分"
# 合并请求合入 release/1.4 后打标签
git tag -a v1.4.1 -m "热修复:金额计算"
git push origin v1.4.1
# 带回 main
git switch main && git cherry-pick <修复提交哈希>

# 密钥:先轮换!然后再处理仓库
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "chore: 移除误提交的 .env,并忽略该文件"
# 需要清理历史时(会改写所有提交哈希,需要团队协调):
git filter-repo --path .env --invert-paths
git push --force --all && git push --force --tags

git filter-repo 需要单独安装,用法以官方说明为准:https://github.com/newren/git-filter-repo 。在临时仓库里练习 cherry-pick、revert、reflog 的脚本见 examples/git-lab。

取舍

做法 优点 缺点
只轮换密钥 + 删除文件 快、不影响团队 旧密钥仍留在历史里(已作废,风险可控)
轮换 + 清理历史 历史中不再有密钥 所有提交哈希改变,所有人要重新克隆;平台副本仍需单独处理
只清理历史不轮换 —— 错误做法:密钥可能已被复制

热修复用 cherry-pick 还是“release 合并回 main”:cherry-pick 精确,只带修复;合并回 main 能保证 release 上所有改动都回到 main,但可能带来冲突。团队约定一种即可。

易错点

  • 热修复只改了 release 分支,忘了带回 main:下个版本 bug 又出现。
  • 从 main 拉热修复分支:把未测试的功能带上线。
  • 以为“删除文件再提交一次”密钥就安全了:历史里仍然有。
  • 先花半天清理历史再轮换密钥:轮换应该是第一步。
  • 强制推送清理后的历史却没通知团队:有人基于旧历史推送,又把文件带回来。

面试怎么讲

“线上版本出 bug 时,我从线上的标签拉热修复分支,修复并补测试后合入 release 分支打补丁版本发布,再 cherry-pick 回 main,避免把 main 上未测试的功能带上线。还处理过密钥误提交:第一步是作废并轮换密钥,检查调用记录;然后删除文件、加入 .gitignore,加上提交前的密钥扫描。是否清理历史要评估成本,清理时用 filter-repo 并通知团队重新克隆。”