如何在Git pre-push钩子中获取与Origin存在差异的文件列表
解决Git pre-push钩子中获取差异文件的两种场景需求
嘿,我刚好碰到过类似的问题,咱们一步步来搞定它!你的需求核心是区分分支是否已推送到远程,然后用不同的diff策略来获取对应文件列表,之前的问题应该是没准确区分这两种场景,导致返回了所有已更改文件。
核心思路
- 分支未推送到远程:需要获取本地分支相对于主分支(比如
main)的所有提交文件 - 分支已存在远程:只需要对比本地分支和远程对应分支的差异文件(也就是本地超前的那些提交里的变更)
完整的pre-push钩子脚本
把下面的内容保存为.git/hooks/pre-push,记得给它加执行权限(chmod +x .git/hooks/pre-push):
#!/bin/bash # 获取当前本地分支名 current_branch=$(git rev-parse --abbrev-ref HEAD) # 定义远程仓库名(默认是origin,如果你用了其他名字可以改这里) remote_name="origin" # 判断当前分支是否已推送到远程 if git ls-remote --exit-code "$remote_name" "$current_branch" >/dev/null 2>&1; then # 场景2:分支已存在远程,对比本地分支和远程分支的差异 echo "获取本地超前于远程的差异文件:" git diff --name-only --diff-filter=ACMRT "$remote_name/$current_branch..$current_branch" else # 场景1:分支未推送到远程,对比本地分支与默认基础分支(这里用main,你可以改成你的主分支名,比如master) base_branch="main" echo "获取本地分支相对于$base_branch的所有提交文件:" git diff --name-only --diff-filter=ACMRT "$base_branch..$current_branch" fi # 如果需要阻止推送,可以在这里添加判断逻辑,比如文件不符合规则时返回非0 # exit 0
关键细节解释
git ls-remote --exit-code:用来检查远程是否存在当前分支,退出码0表示存在,非0表示不存在--diff-filter=ACMRT:只筛选出**添加(A)、复制(C)、修改(M)、重命名(R)、类型变更(T)**的文件,如果你需要包含删除的文件,可以加上Dorigin/branch..branch:这个范围表示“远程分支之后的本地提交”,也就是本地超前的部分,刚好对应场景2的需求base_branch..current_branch:对于新分支,对比它和主分支的所有差异,就是本地所有提交的文件
测试验证
- 新分支场景:创建一个从未推送过的分支,提交几个文件,运行钩子,应该能看到所有提交的文件
- 已推送分支场景:先把分支推送到远程,再本地提交新的变更,运行钩子,只会显示这次新提交里的差异文件
这样应该就能完美满足你的两个需求啦!
内容的提问来源于stack exchange,提问作者Matt Stow
相关产品推荐
相关产品推荐

