Git 分支管理实战:feature/release/hotfix 怎么用才不乱
"直接在 main 上改"的爽,会在第一次上线出问题时连本带利还回来。
带过三个人的小团队后我彻底想明白:分支模型不是越多越好,是和团队规模、发布节奏匹配才不乱。这篇给你一套从个人项目到十人团队都能落地的分支规范,外加线上出事故时的 hotfix 救火流程------这套流程我们真用过,从发现 bug 到修复上线 25 分钟。
一、先选对模型:别抄大厂的作业
| 模型 | 分支数 | 适合 | 代价 |
|---|---|---|---|
| main + feature(简化流) | 2 种 | 个人项目、1~5 人小团队 | 需要纪律:main 随时可发布 |
| Git Flow | 5 种 | 版本化发布、多版本并行维护 | 分支多、合并地狱 |
| GitHub Flow | 2 种 | 持续部署的 Web 服务 | 依赖强的 CI/CD |
| Trunk-Based | 1+短命分支 | 高频发布、强特性开关 | 对自动化要求高 |
我的建议:5 人以下直接用 main + feature。Git Flow 那套 develop/release 分支是为"几个月发一个版本"设计的,你现在一周发好几次,纯属给自己加流程税。
二、分支命名与生命周期
命名规范的价值在于一眼看懂这个分支是谁、干什么、能不能删:
text
feature/登录支持手机验证码
feature/issue-42-order-refund # 带工单号,方便追溯
fix/login-redirect-loop
hotfix/20260918-payment-500
release/v1.4.0 # 仅版本化发布团队需要
三条铁律:
- 分支寿命不超过 3 天。超过三天还没合的 feature,说明拆得太大了------拆小。分支活越久,合并冲突越痛,这是指数关系。
- main 永远可发布。任何时刻从 main 拉代码出来都能直接跑,这是所有流程的基石。
- 合并即删 。本地
git branch -d+ 远端git push origin --delete,留着只会污染git branch -a列表。
三、日常流程:feature 分支怎么走
bash
# 1. 从最新 main 切出
git checkout main && git pull --rebase
git checkout -b feature/order-export
# 2. 开发中,小步提交
git add -p && git commit -m "feat: 导出订单支持 csv 格式"
# 3. main 有更新时,rebase 到最新(保持线性历史)
git fetch origin
git rebase origin/main
# 4. 推送 + 开 PR
git push -u origin feature/order-export
两个高频争议,说清我的立场:
merge 还是 rebase? feature 分支内同步 main 用 rebase(历史干净、好回溯);合并进 main 用 merge --no-ff 或 Squash merge (保留"这是一个完整功能"的边界,回滚时 git revert -m 1 一次退整个功能,而不是逐个 commit 找)。
bash
# 回滚整个已合并的功能分支
git revert -m 1 <merge-commit-hash>
冲突怎么解才不慌? rebase 遇到冲突,一次只解一个 commit,解完 git add . && git rebase --continue。发现解错了别硬扛,git rebase --abort 回到 rebase 前,一切如初------rebase 前先 git branch backup/order-export 存个引用,永远有后悔药。
四、线上救火:hotfix 标准流程
线上炸了,别在慌乱中直接改 main。标准动作五步:
bash
# 1. 从 main(线上跑的代码)切 hotfix 分支
git checkout main && git pull
git checkout -b hotfix/20260918-payment-500
# 2. 最小修复,只动和事故相关的代码
git commit -m "fix: 支付回调空指针,增加判空"
# 3. PR 加急合并进 main(review 不能省,哪怕是 5 分钟看一眼)
# 4. 部署 main,观察监控
# 5. 同步回开发分支,否则下个版本 bug 复发
git checkout develop # 或最新的 feature 分支
git cherry-pick <hotfix-commit-hash>
第 5 步是最容易漏的。我见过团队 hotfix 合了 main 忘了同步 develop,两周后新版本带着同一个 bug 又上线一次,被骂了两次。如果你的平台支持,在 PR 模板里加一行"此修复是否需要 backport?"
事故后还有一件事:写 5 行 postmortem------什么坏了、影响多久、根因、怎么修的、怎么防。贴在 PR 里,这比流程本身更能防止下次事故。
五、分支保护:靠自觉是不行的
在 GitHub/GitLab 上给 main 开保护规则,五分钟设置,一劳永逸:
| 规则 | 作用 |
|---|---|
| Require pull request | 禁止直接 push main |
| Require 1 approval | 至少一个人看过 |
| Require status checks | CI 不绿不许合 |
| Require linear history | 禁止 merge commit 乱入(可选) |
| Allow force push: 关闭 | 防止误操作抹掉历史 |
个人项目至少开第一条和 CI 检查------main 上的代码必须是验证过的,这条纪律值回所有设置时间。
六、三个真实场景复盘
场景 1:feature 分支落后 main 一周,冲突 40 个文件
错误做法:硬着头皮 merge,解两小时,解出逻辑错误。正确做法:以后每 1~2 天 rebase 一次 main;这次先 git merge --no-commit --no-ff origin/main 预演冲突量,太大就找写冲突方一起解------冲突是两个人的代码在打架,一个人解容易解错对方的意图。
场景 2:"我本地好好的,测试环境就是不对"
八成是分支不一样。养成习惯:切分支前 git status && git branch --show-current,部署脚本里打印当前 commit(git rev-parse --short HEAD),出问题一眼对上版本。
场景 3:误把密码 commit 上去推到了远端
改密码第一,清理历史第二(git filter-repo 或 BFG),第三才是重写历史强推。顺序别反------历史已经泄露了,密码换掉才是止损。强推前通知所有人 rebase,不然团队会在你强推后把带密码的分支又推回来。
七、总结
分支管理的本质是控制"未合并工作"的规模:分支越小、寿命越短,风险越小。你的行动清单:给 main 开保护、feature 分支按天拆小、每天 rebase 一次 main、hotfix 记得 cherry-pick 回开发线。做到这四条,你团队的 Git 就已经超过大多数团队了。