git worktree通过为每个分支创建独立工作目录实现多分支并行开发,配合标准化清洗的分支名生成对应测试域名(如test-feature-login.example.com),再结合.env文件、nginx map路由与docker容器命名,达成分支到测试环境的自动映射。

git worktree + 环境变量文件实现分支到测试环境映射
直接用 git checkout 切换分支来部署测试环境,会污染当前工作区、干扰开发节奏,且无法并行验证多个分支。正确做法是用 git worktree 为每个分支创建独立目录,再配合环境变量文件(如 .env.test)绑定对应测试服务器配置。
关键不是“怎么配”,而是“怎么让分支名自动决定环境地址”。例如:feature/login 分支应自动指向 https://test-login.example.com,hotfix/db-timeout 指向 https://test-hotfix.example.com。
- 在每个
worktree目录下放一个.env文件,内容只写API_BASE_URL=https://test-$(basename $(git rev-parse --abbrev-ref HEAD) | sed 's/\//-/g').example.com - 构建脚本中不硬编码域名,而是读取
API_BASE_URL环境变量(前端可由VUE_APP_API_BASE_URL或REACT_APP_API_BASE_URL注入) - 避免在
.gitignore中忽略.env—— 它必须被 Git 跟踪,否则不同分支的配置就无法随分支切换而生效
CI/CD 流程中如何安全提取分支名并注入测试环境
GitLab CI 或 GitHub Actions 的 $CI_COMMIT_REF_NAME 或 $GITHUB_HEAD_REF 是可靠来源,但直接拼接进 URL 存在注入风险。比如分支名含 ..、/、空格或特殊字符时,可能破坏 Nginx 配置或 DNS 解析。
更稳妥的做法是做标准化清洗:
Conventional Commits v1.0.0 分支、工作树命名及提交信息规范,适用于 GitHub 与 GitLab 项目,用于创建分支和命名工作树等场景。
- 用正则替换所有非字母数字字符为短横线:
echo "$CI_COMMIT_REF_NAME" | sed 's/[^a-zA-Z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//;s/-$//' - 限制长度(如最多 24 字符),防止 DNS 标签超长:
cut -c1-24 - 强制小写,避免大小写敏感问题:
tr 'A-Z' 'a-z' - 最终生成的域名建议加固定前缀,如
test-$(cleaned_branch).example.com,避免与生产域名冲突
测试服务器反向代理如何按分支名路由请求
Nginx 不支持直接根据上游服务名动态解析后端地址,但可以用 map 指令把分支名映射成后端 IP 或容器名。前提是你的测试服务器能识别请求中的分支标识 —— 这通常靠 Host 头或自定义 Header 实现。
- 在 Nginx 入口层,用
map $host $backend_target匹配test-feature-login.example.com→feature-login:3000 - 每个
worktree启动的 Docker 容器必须用分支名作为 service name(如docker run --name feature-login ...) - 不要依赖
localhost:同一台机器上多个worktree容器必须监听不同端口,或统一走 Docker 内网 DNS -
map表需 reload 才生效,不适合高频新建分支场景;推荐改用 Consul + Fabio 或 Traefik 的自动服务发现
容易被忽略的权限与清理陷阱
很多人以为 git worktree remove 就万事大吉,其实它只是删掉 .git/worktrees/xxx 元数据,对应目录里的文件、node_modules、Docker 容器、Nginx server block 都还在。
- 删除前务必先停容器:
docker stop $(basename $(realpath ../feature-login)) - 手动删 Nginx 配置片段(如
/etc/nginx/sites-enabled/test-feature-login),否则 reload 会失败 -
worktree目录若含未提交修改,git worktree remove会拒绝执行 —— 此时得先git -C ../feature-login status确认,别靠主仓库git status判断 - SSH 部署脚本里不能用
~路径:不同worktree下的~指向用户家目录,不是当前项目路径,要用$(pwd)或绝对路径
真正麻烦的从来不是“怎么配通”,而是“谁来保证每次新增分支都同步更新 Nginx 配置、容器名、DNS 记录和监控项”。自动化脚本必须覆盖从 git worktree add 到 nginx -s reload 的全链路,漏一环,测试环境就不可靠。










