如何在pre-push钩子中查看待推送提交(含远程分支未创建场景)
解决pre-push钩子中远程分支未创建时的待推送变更获取问题
核心思路:过滤已推送到远程的提交
当远程分支尚未创建时,当前分支中所有未推送到任何远程仓库的内容,就是本次要推送的变更。可以通过Git的内置命令直接过滤出这些本地独有的提交,无需依赖远程分支信息。
1. 获取待推送的提交记录
直接列出所有未推送到远程的提交:
git log --oneline HEAD --not --remotes=*
这个命令会自动排除所有已存在于远程仓库的提交,只保留本地尚未推送的内容,无论远程有没有对应分支,都能准确拿到待推送的提交记录。
2. 获取待推送的变更文件列表
如果只需要变更的文件清单,可以直接对比本地未推送提交的起点与当前HEAD:
# 提取所有未推送提交的哈希 LOCAL_ONLY_COMMITS=$(git rev-list --not --remotes=* HEAD) if [ -n "$LOCAL_ONLY_COMMITS" ]; then # 拿到未推送提交中最早的那个哈希 FIRST_LOCAL_COMMIT=$(echo "$LOCAL_ONLY_COMMITS" | tail -1) # 输出变更文件列表 git diff --name-only "$FIRST_LOCAL_COMMIT" HEAD else echo "No changes to push." fi
不依赖reflog的分支创建起点查找方案
如果确实需要找到当前分支的创建分叉点(即分支从哪个提交衍生而来),可以通过对比当前分支与所有其他本地/远程分支的公共祖先来实现:
# 获取当前分支名 CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) # 收集所有其他本地和远程分支的引用 OTHER_BRANCHES=$(git for-each-ref --format='%(refname)' refs/heads/ refs/remotes/ | grep -v "$CURRENT_BRANCH") # 找到当前分支与所有其他分支的最近公共祖先 BRANCH_START=$(git merge-base --all HEAD $OTHER_BRANCHES) # 处理当前分支是仓库首个分支的情况 if [ -z "$BRANCH_START" ]; then BRANCH_START=$(git rev-list --max-parents=0 HEAD) fi # 查看从分支起点到HEAD的提交 git log --oneline "$BRANCH_START"..HEAD
这个方法完全不依赖reflog,可靠性更高,同时兼容仓库中只有当前一个分支的极端场景。
pre-push钩子中的适配示例
将上述逻辑嵌入pre-push钩子的完整示例:
#!/bin/bash # 获取当前分支 CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) # 获取所有未推送提交 LOCAL_ONLY_COMMITS=$(git rev-list --not --remotes=* HEAD) if [ -z "$LOCAL_ONLY_COMMITS" ]; then echo "No changes to push." exit 0 fi # 提取未推送的最早提交哈希 FIRST_COMMIT=$(echo "$LOCAL_ONLY_COMMITS" | tail -1) # 获取变更文件列表 CHANGED_FILES=$(git diff --name-only "$FIRST_COMMIT" HEAD) echo "Files to push:" echo "$CHANGED_FILES" # 此处可添加自定义逻辑,比如文件格式检查、合规校验等
内容的提问来源于stack exchange,提问作者sfeldmann
相关产品推荐
相关产品推荐

