GitHub Action中如何修改触发工作流的提交且不重复触发
实现方案
首先明确Git的基础逻辑:已经推送到远程的提交只要修改内容,提交哈希一定会变更,不存在不产生新提交对象、直接修改原有已推送提交内容的操作。你要的「修改文件后不新增独立提交、不重复触发Action」的效果可以通过「追加修改到当前提交+跳过CI触发」的方式实现,具体步骤如下:
1. 配置工作流基础权限与检出参数
首先修改GitHub Action工作流yaml文件,满足提交修改的前置要求:
- 给
actions/checkout步骤加fetch-depth: 0参数,拉取完整Git历史,不要使用默认的浅克隆配置 - 给工作流开放仓库内容写入权限,在yaml顶层添加:
permissions: contents: write
2. 调整原有脚本执行顺序
你原来的脚本先打标签再改文件的逻辑顺序存在问题,要调整为「计算新版本→替换文件版本号→追加修改到当前提交→推送更新后的提交→打标签→构建推送镜像」,同时修复原有sed命令变量不生效的问题,修改后的完整脚本如下:
# 配置Git提交身份,使用GitHub官方提供的bot账号即可 git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git fetch --tags serviceVersions='' declare -A versionMap # 用字典存储每个服务对应的新版本,避免后续重复计算 for serviceToRelease in ${SERVICES_RELEASE[@]}; do latestRev=$(git tag --list --sort=-committerdate "*$serviceToRelease*" | head -n 1) version=$(echo $latestRev | sed -nre 's/^[^0-9]*(([0-9]+\.)+[0-9]+).*/\1/p') newVersion=$(echo "${version%.*}.$((${version##*.}+1))") versionMap[$serviceToRelease]=$newVersion # 替换文件中的版本号:sed必须用双引号才能解析shell变量,同时排除.git目录避免误改内部文件 grep -rli "$version" . --exclude-dir=.git | xargs -i@ sed -i "s/$version/$newVersion/g" @ serviceLowerCase=$(echo $serviceToRelease | sed -e 's/\(.*\)/\L\1/') serviceVersions="${serviceToRelease}-${newVersion} ${serviceVersions}" done # 将所有版本修改追加到触发本次Action的提交上,保留原提交信息,加[skip ci]标记避免重复触发工作流 git add . git commit --amend -m "$(git log -1 --pretty=%B) [skip ci]" # 用force-with-lease安全强制推送更新后的提交,避免覆盖他人同时段推送的代码 git push --force-with-lease origin ${{ github.ref_name }} # 提交推送完成后再打标签、构建镜像,保证标签绑定在包含最新版本号的提交上 for serviceToRelease in ${SERVICES_RELEASE[@]}; do newVersion=${versionMap[$serviceToRelease]} serviceLowerCase=$(echo $serviceToRelease | sed -e 's/\(.*\)/\L\1/') git tag $serviceToRelease-$newVersion git push origin --tags docker build -t $serviceLowerCase -f ./components/$serviceToRelease/Dockerfile ./components/$serviceToRelease docker tag $serviceLowerCase tag/repo:$serviceLowerCase-$newVersion docker push tag/repo:$serviceLowerCase-$newVersion done
3. 避免重复触发Action的说明
上面脚本里在提交信息末尾加的[skip ci]是GitHub原生支持的跳过工作流触发标记,推送后GitHub不会为这个更新后的提交重新触发Action,完全满足不重复运行的要求。
如果你不想修改提交信息,也可以去掉这个标记,在工作流的job层加判断条件,过滤掉bot账号触发的运行:
jobs: your-release-job: runs-on: ubuntu-latest if: ${{ github.actor != 'github-actions[bot]' }} # 只处理非bot账号触发的push事件 steps: # 原有业务步骤
注意事项
- 原sed命令用单引号包裹替换规则时,shell不会解析里面的
$version、$newVersion变量,会直接按字符串匹配,必须换成双引号才能正常替换版本号 - grep搜索文件时必须加
--exclude-dir=.git,否则会遍历Git内部存储文件导致脚本报错 - 打标签操作必须放在提交推送完成之后,否则标签会绑定到旧的、没有更新版本号的提交上,导致代码和标签版本不一致
- 强制推送优先用
--force-with-lease,比直接--force更安全,不会意外覆盖其他人在Action运行期间推送到分支的提交
内容的提问来源于stack exchange,提问作者Tlaloc-ES
相关产品推荐
相关产品推荐

