You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Git pre-push钩子中获取与Origin存在差异的文件列表

解决Git pre-push钩子中获取差异文件的两种场景需求

嘿,我刚好碰到过类似的问题,咱们一步步来搞定它!你的需求核心是区分分支是否已推送到远程,然后用不同的diff策略来获取对应文件列表,之前的问题应该是没准确区分这两种场景,导致返回了所有已更改文件。

核心思路

  1. 分支未推送到远程:需要获取本地分支相对于主分支(比如main)的所有提交文件
  2. 分支已存在远程:只需要对比本地分支和远程对应分支的差异文件(也就是本地超前的那些提交里的变更)

完整的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)**的文件,如果你需要包含删除的文件,可以加上D
  • origin/branch..branch:这个范围表示“远程分支之后的本地提交”,也就是本地超前的部分,刚好对应场景2的需求
  • base_branch..current_branch:对于新分支,对比它和主分支的所有差异,就是本地所有提交的文件

测试验证

  1. 新分支场景:创建一个从未推送过的分支,提交几个文件,运行钩子,应该能看到所有提交的文件
  2. 已推送分支场景:先把分支推送到远程,再本地提交新的变更,运行钩子,只会显示这次新提交里的差异文件

这样应该就能完美满足你的两个需求啦!

内容的提问来源于stack exchange,提问作者Matt Stow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:43:22