You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取刚合并到master的分支名?分支对应版本标签生成方案

解决方案:基于分支类型自动生成SemVer版本标签

结合你的分支命名规范和版本标签需求,我整理了一套可落地的方案,包含流水线获取分支名的具体实现,以及自动识别不可行时的最优替代方案:

一、先明确分支与版本升级的对应规则

咱们先把规则定死,避免歧义:

  • fix/xxxpatch 版本升级(比如 v1.0.0 → v1.0.1,修复bug用)
  • feat/xxxminor 版本升级(比如 v1.0.0 → v1.1.0,新增功能用)
  • release/xxxmajor 版本升级(比如 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,这样能确保流水线稳定获取分支信息,还能加代码审查环节,一举两得。
  • 用工具管理版本号:比如semvernpm version这类工具,自动计算版本号,避免手动输入出错。

内容的提问来源于stack exchange,提问作者Souradeep Nanda

火山引擎 最新活动