如何让GitHub Action非交互式压缩同名称不同版本的Git提交?
实现GitHub Action自动合并同依赖的版本更新提交
核心思路
通过将历史中同名称依赖的旧版本更新提交标记为squash!/fixup!格式,结合Git的自动压缩功能,把旧提交合并到最新的版本更新提交中。使用squash!可保留旧版本号在提交信息正文,fixup!则仅保留最新版本号。
具体实现步骤
1. 统一提交信息格式
确保新版本更新提交遵循固定模板:
Update $NAME to $VERSION
该格式便于后续通过正则匹配提取依赖名称$NAME。
2. 在GitHub Action工作流中添加自动合并逻辑
在提交新版本变更后,依次执行以下操作:
步骤1:提取当前提交的依赖信息
# 获取最新提交的完整信息 NEW_COMMIT_MSG=$(git log -1 --pretty=%B) # 从提交信息中提取依赖名称(适配"Update $NAME to $VERSION"格式) NAME=$(echo "$NEW_COMMIT_MSG" | awk '{print $2}') # 提取最新版本号 NEW_VERSION=$(echo "$NEW_COMMIT_MSG" | awk '{print $4}')
步骤2:定位历史中的同依赖旧提交
# 查找所有匹配"Update $NAME to *"的旧提交,排除当前刚提交的版本 OLD_COMMITS=$(git log --grep="^Update $NAME to " --invert-grep="^$NEW_COMMIT_MSG$" --pretty=%H)
步骤3:批量修改旧提交的信息格式
使用git filter-branch重写历史提交信息(此操作会修改提交哈希,需确保分支允许强制推送):
if [ -n "$OLD_COMMITS" ]; then # 配置Git身份,避免filter-branch执行报错 git config user.name "GitHub Actions Bot" git config user.email "actions@github.com" # 将匹配的旧提交标记为squash!格式,保留旧版本号在提交正文 git filter-branch --msg-filter " if echo \"\$GIT_COMMIT_MESSAGE\" | grep -q \"^Update $NAME to \"; then echo \"squash! $NEW_COMMIT_MSG\" else echo \"\$GIT_COMMIT_MESSAGE\" fi " HEAD~$(git rev-list --count HEAD ^$(git merge-base HEAD $OLD_COMMITS)) fi
如果不需要保留旧版本号,可将squash!替换为fixup!,合并后仅保留最新提交的信息。
步骤4:自动执行压缩合并
启用Git自动压缩并完成rebase:
# 开启自动压缩功能 git config --global rebase.autosquash true # 从旧提交的共同父节点开始rebase,自动完成合并 if [ -n "$OLD_COMMITS" ]; then git rebase -i --autosquash $(git merge-base HEAD $OLD_COMMITS)^ --no-edit fi
步骤5:推送修改后的历史
在GitHub Action中设置推送权限后,强制推送重写后的分支:
git push origin HEAD --force-with-lease
注意事项
- 重写历史会改变提交哈希,仅建议在独立更新分支或个人分支上执行,避免影响协作分支。
- 需为GitHub Action配置
permissions: contents: write权限,确保能推送修改后的历史。 - 若存在多个同依赖的旧提交,上述逻辑会一次性将所有旧提交合并到最新提交中。
内容的提问来源于stack exchange,提问作者paradroid
相关产品推荐
相关产品推荐

