本文目录导读:

- 核心原则
- 方案一:Git Flow(推荐用于有固定版本的商业应用/库)
- 方案二:GitHub Flow / 主干开发(推荐用于SaaS/持续部署)
- 方案三:功能开关 + 主干开发(推荐的进阶方案)
- 针对PHP项目的具体设计细节
- 总结:一个典型的 PHP 团队工作流
设计PHP代码的分支管理,核心在于根据项目类型(是开源库、商业应用、还是SaaS平台?)、团队规模和发布频率来制定策略。
不存在唯一的“最佳”策略,但有一个最主流、可扩展性最强的起步方案:Git Flow(适合固定版本发布)或 GitHub Flow(适合持续部署)。
下面我为你梳理出几种常见场景下的设计思路和具体操作。
核心原则
- 主分支保护 (Master / Main): 该分支的代码必须随时可部署到生产环境,任何直接往master/develop推代码的行为都应被禁用。
- 原子化提交: 每个提交只做一件事,每个功能一个分支(或一个PR)。
- 自动化: 用 CI/CD (持续集成/持续交付) 自动检查代码规范、自动运行测试、自动部署。
Git Flow(推荐用于有固定版本的商业应用/库)
这是最经典的结构,适合需要同时维护多个版本(如v1.0, v2.0),或开发周期较长(以周/月为单位)的项目。
分支结构与职责:
master: 存放正式发布的代码,每次合并到master自动打Tag(如 v2.0.1),这个Tag就是生产环境的代码版本。develop: 日常开发主干,所有功能分支都从它拉出,最终合并回它。feature/xxx: 功能开发分支。- 从
develop创建。 - 开发完成后合并回
develop。
- 从
release/xxx: 预发布/测试分支。- 从
develop创建(当develop积累了足够多的feature,准备发版时)。 - 只在此分支上进行bug修复、文档、配置文件修改,不添加新功能。
- 测试通过后,合并到
master(并打Tag)和develop`)。
- 从
hotfix/xxx: 紧急热修复分支。- 从
master创建(因为生产环境坏了,需要基于当前生产代码修)。 - 修复完成后,合并到
master(打补丁版本Tag)和develop`。
- 从
PHP场景下的优点: 适合Laravel、Symfony等需要打包成独立版本安装包的商业项目,或者需要同时维护旧版API(V1)、开发新版API(V2)的后端服务。
GitHub Flow / 主干开发(推荐用于SaaS/持续部署)
如果你们是SaaS,代码部署后用户立刻就能用,没有“版本号”的概念,那这个更轻量。脸书、谷歌、Netflix 等大部分互联网公司都在用这个思路的变种。
分支结构与职责(极简):
- 只有一条长期分支:
master(或main)。 - 开发:从
master拉出分支,命名为feature/xxx或fix/xxx。 - 完工:创建 Pull Request (或 Merge Request)。
- 审查与测试:PR 通过自动化测试和Code Review。
- 合并:合并到
master。 - 部署:合并到
master后,立即自动部署到生产环境(或预发布环境)。
PHP场景下的优点: 适合SaaS平台(如Shopify、WordPress.com、Sass后端),如果你使用Envoy、Deployer或纯CI脚本部署,这种方式最流畅。
功能开关 + 主干开发(推荐的进阶方案)
这可以看作是方案二的升级版,它放弃使用分支来隐藏未完成的功能,而是使用代码层面的开关。
核心思想: 所有代码都合并到 master,但通过环境变量或配置文件决定哪些功能对外暴露。
PHP中实现(以Laravel为例):
// 在 Service Provider 或 Controller 中
if (config('features.new-checkout-v2', false)) {
// 调用新的结算逻辑
$this->processCheckoutV2();
} else {
$this->processCheckoutV1();
}
优点:
- 分支几乎不会长期存在。 再大的功能,只要写了开关就能合并,避免“合并地狱”。
- 回滚极其简单。 把开关关掉即可,无需回滚代码。
- 支持灰度发布(金丝雀发布)。 先给10%的用户开新功能,没问题再全量开放。
针对PHP项目的具体设计细节
分支命名规范 (强制)
- 功能:
feature/user-login-revamp、feature/add-payment-gateway - 修复:
fix/null-pointer-exception、fix/order-fetch-timing - 发布:
release/v1.3.2 - 热修复:
hotfix/security-patch-log4j - 优化/重构:
refactor/user-model、chore/deps-update
自动化检查(PHP 特有的)
在每次 PR 合并到 master/develop 之前,CI(如GitHub Actions/GitLab CI)必须自动运行:
- 语法与静态分析:
php -l检查语法。composer dump-autoload --no-dev检查类加载。phpstan analyse --level=max或psalm检查逻辑错误。
- 代码规范:
php-cs-fixer fix --dry-run或PHP_CodeSniffer检查 PSR-12 标准。
- 单元测试与集成测试:
phpunit运行测试,要求覆盖率不能下降。- 与数据库相关的测试:使用测试用数据库,不能直接操作生产或开发数据库。
- Composer依赖审计:
composer audit或local-php-security-checker检查已知漏洞。
- 性能测试(可选):
- 如果涉及ORM查询,可以用
Laravel Telescope或自定义脚本检查N+1问题。
- 如果涉及ORM查询,可以用
环境与分支映射(多环境部署)
| 环境 | 通常映射的分支 | 配置(.env) |
用途 |
|---|---|---|---|
| 本地 (local) | 任意 | .env.local |
开发者自测 |
| 开发 (dev) | develop 或 feature分支部署 |
.env.dev |
联调、内部测试 |
| 测试 (test) | release/xxx |
.env.staging |
QA团队测试、回归 |
| 预发布 (staging) | release/xxx (接近master) |
.env.staging |
模拟生产环境 |
| 生产 (production) | master (打Tag) |
.env.production |
用户使用 |
数据库迁移(PHP 的痛点)
分支管理中最容易出问题的就是数据库 Schema 变更。
策略:
- 永远向前迁移。 所有分支必须在数据库迁移脚本中做到向前兼容(Add column with default NULL, not NOT NULL; Add index with
ALGORITHM=INPLACE, LOCK=NONE)。 - 不要手动修改。 使用 Laravel Migrations、Symfony Doctrine Migrations 管理,迁移文件需要和代码一起进版本控制。
- 部署流程: 先跑
php artisan migrate,再重启 PHP-FPM / Octane。 - 回滚: 对于大规模重构,尽量设计为“可回滚”,即删除一个表和列的操作,放在两个月后的另一个版本中,而不是随重构代码一起合并。
一个典型的 PHP 团队工作流
假设你使用 Git Flow + Laravel:
- 产品经理提出需求,开发者从
develop拉出一个feature/payment-integration。 - 开发者在本地写代码,运行
phpunit --testsuite=feature,并通过phpstan。 - 一切本地通过后,推送到远程,发起合并请求(Merge Request)到
develop。 - CI 自动运行所有测试、代码规范检查、依赖审计。
- 同事Code Review通过后,合并到
develop,代码自动部署到“开发环境”。 - 测试人员报了一堆bug,开发者在
feature/payment-integration上修复,再次发起MR。 - 版本迭代完成,从
develop拉出release/v1.2.0,只修复bug,不加功能。 - QA测试通过后,将
release/v1.2.0合并到master,打上v1.2.0的Tag,CI自动部署到生产环境。 - 线上发现紧急bug,从
master拉出hotfix/crash-on-refund,修复后,直接合并回master和develop。
一句话建议: 如果你的PHP应用是固定版本发布(客户下载安装包),用 Git Flow,如果是持续迭代的SaaS(云服务),用 GitHub Flow + 功能开关。