如何获取刚合并到master的分支名?分支对应版本标签生成方案
解决方案:基于分支类型自动生成SemVer版本标签
结合你的分支命名规范和版本标签需求,我整理了一套可落地的方案,包含流水线获取分支名的具体实现,以及自动识别不可行时的最优替代方案:
一、先明确分支与版本升级的对应规则
咱们先把规则定死,避免歧义:
fix/xxx→ patch 版本升级(比如 v1.0.0 → v1.0.1,修复bug用)feat/xxx→ minor 版本升级(比如 v1.0.0 → v1.1.0,新增功能用)release/xxx→ major 版本升级(比如 v1.0.0 → v2.0.0,重大版本迭代用)
二、流水线中获取合并分支名的实现方法
主流CI工具都能实现这个需求,这里给你GitHub Actions和GitLab CI的具体例子:
GitHub Actions 场景
如果团队是用PR合并到master,那直接通过事件变量就能拿到源分支名;如果有直接push的情况(不推荐,但也兼容),可以从提交历史追溯:
jobs: auto-tag-version: runs-on: ubuntu-latest steps: - name: 拉取全量代码与提交历史 uses: actions/checkout@v4 with: fetch-depth: 0 # 必须拉全量历史才能追溯分支 - name: 获取合并进来的分支名 id: get-branch run: | # PR合并场景:直接取PR的源分支 if [ "${{ github.event_name }}" = "pull_request" ]; then echo "branch_name=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT else # 直接push场景:从最近的合并提交里找源分支 BRANCH_NAME=$(git log --merges -1 --pretty=format:"%P" | xargs git log --pretty=format:"%D" | grep -v master | head -n1 | sed 's/.*origin\///') echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT fi - name: 判断版本升级类型 id: bump-type run: | BRANCH="${{ steps.get-branch.outputs.branch_name }}" if [[ $BRANCH == fix/* ]]; then echo "type=patch" >> $GITHUB_OUTPUT elif [[ $BRANCH == feat/* ]]; then echo "type=minor" >> $GITHUB_OUTPUT elif [[ $BRANCH == release/* ]]; then echo "type=major" >> $GITHUB_OUTPUT else echo "::error::不支持的分支格式:$BRANCH" exit 1 fi - name: 生成版本标签并推送 uses: anothrNick/github-tag-action@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DEFAULT_BUMP: ${{ steps.bump-type.outputs.type }}
GitLab CI 场景
GitLab CI对PR(合并请求)有专属变量,直接用就行;直接push的话同样从合并提交里提取:
auto-tag-version: stage: deploy only: - master script: - | # 获取合并分支名 if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" ]; then BRANCH_NAME=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME else # 直接push场景:解析最近合并提交的描述 MERGE_COMMIT=$(git log --merges -1 --pretty=format:"%H") BRANCH_NAME=$(git show $MERGE_COMMIT --pretty=format:"%b" | grep -E "^Merge branch '.*'" | sed -E "s/Merge branch '(.*)' into.*/\1/") fi # 判断版本升级类型 if [[ $BRANCH_NAME == fix/* ]]; then BUMP_TYPE=patch elif [[ $BRANCH_NAME == feat/* ]]; then BUMP_TYPE=minor elif [[ $BRANCH_NAME == release/* ]]; then BUMP_TYPE=major else echo "错误:不支持的分支格式 $BRANCH_NAME" exit 1 fi # 计算并推送新版本标签 CURRENT_TAG=$(git describe --abbrev=0 --tags 2>/dev/null || echo "v0.0.0") NEW_TAG=$(semver bump $BUMP_TYPE $CURRENT_TAG) git tag $NEW_TAG git push origin $NEW_TAG before_script: - apt-get update && apt-get install -y semver # 安装版本号计算工具
三、如果无法获取分支名的最优 fallback 方案
要是遇到特殊情况(比如squash合并导致分支信息丢失、CI环境限制)拿不到分支名,推荐两个靠谱的替代方案:
方案1:提交信息约定 + 自动解析
强制要求所有合并到master的PR标题或提交信息带指定前缀:
fix: 修复XXbug→ 对应patch升级feat: 新增XX功能→ 对应minor升级release: 发布v2.0版本→ 对应major升级
流水线里直接解析最新提交的信息:
# 获取最新提交的标题 COMMIT_TITLE=$(git log -1 --pretty=format:"%s") if [[ $COMMIT_TITLE == fix:* ]]; then BUMP_TYPE=patch elif [[ $COMMIT_TITLE == feat:* ]]; then BUMP_TYPE=minor elif [[ $COMMIT_TITLE == release:* ]]; then BUMP_TYPE=major else echo "错误:提交标题缺少必填前缀,请按照规范提交" exit 1 fi
这个方案不受合并方式影响,只要团队遵守提交规范就非常可靠,适合所有CI环境。
方案2:手动触发版本升级
如果自动识别确实有困难,可以在流水线里加一个手动确认步骤(比如GitLab的manual job、GitHub Actions的workflow_dispatch),让维护人员选择要升级的版本类型。虽然需要人工介入,但最稳妥,适合分支命名偶尔不规范的场景。
四、额外小建议
- 强制通过PR合并:禁止直接push到master,这样能确保流水线稳定获取分支信息,还能加代码审查环节,一举两得。
- 用工具管理版本号:比如
semver、npm version这类工具,自动计算版本号,避免手动输入出错。
内容的提问来源于stack exchange,提问作者Souradeep Nanda




