![Git 推送被拒:[remote rejected] master - master (pre-receive hook declined) 排查与 TaoToken 配置实践](http://pic.xiahunao.cn/yaotu/Git 推送被拒:[remote rejected] master - master (pre-receive hook declined) 排查与 TaoToken 配置实践)
1. 从一次真实的推送失败说起pre-receive hook declined 到底是什么! [remote rejected] master - master (pre-receive hook declined)这行报错几乎每个用 Git 做团队协作的人都撞见过。它的字面意思是你的本地提交已经打包发到了远端但远端在真正写入仓库之前运行了一个叫pre-receive的服务端钩子这个钩子返回了非零退出码于是整个推送被拒绝。注意关键词是「服务端」——问题不在你的git add、git commit也不在你的网络而在远端仓库的规则或钩子脚本。很多人第一次遇到会本能地去查本地配置改git config、重装 Git、换 SSH key折腾半天发现毫无用处。原因很简单pre-receive hook declined是远端主动拒绝本地几乎无法绕过。你要做的是搞清楚远端为什么拒绝而不是在本地反复重试。这个报错最常见的三类触发场景第一目标分支是受保护分支protected branch比如 GitLab 默认把master/main设为保护分支只允许 Maintainer 及以上角色直接推送第二仓库配置了服务端钩子脚本比如提交信息格式校验、禁止大文件、禁止直接推 master第三你的账号在该项目里权限不足或者推送用的凭证根本不是你以为的那个账号。本文会按「先定位、再修复、后联调」的顺序把整条排查链路拆开讲清楚。前半部分是纯 Git 排障给出可以直接复制的命令后半部分讲一个容易被忽略的点——当你把推送流程和 API 鉴权联调放在一起时如何用 TaoToken 统一通道管理 endpoint 和 Key避免凭证混乱导致的二次踩坑。适合正在被这个报错卡住、想一次性搞明白的开发者。2. 逐层定位从 remote 配置到服务端钩子日志的完整排查链路排查的核心思路是「由近及远」先确认你推的到底是哪个远端、哪个分支再确认远端规则最后看服务端日志。下面按顺序来。2.1 先确认 remote 和分支别推错地方第一步永远是确认你面对的是哪个仓库。很多「权限不足」其实是推到了一个自己没权限的 fork 或者旧地址。# 查看当前所有远端及其地址 git remote -v # 查看当前分支和跟踪关系 git branch -vv # 查看即将推送的内容会去哪里 git push --dry-run origin mastergit remote -v会打印origin对应的 fetch/push 地址。如果 push 地址和你以为的不一致比如指向了上游主仓库而不是自己的 fork那报错就说得通了。--dry-run是个好东西它模拟推送但不真正写入能提前暴露大部分拒绝原因。2.2 判断是不是保护分支GitLab 和 GitHub 都会在服务端对保护分支做拦截拦截时抛出的正是pre-receive hook declined。判断方法GitLab 路径是项目 → Settings → Repository → Protected branches看master是否在列表里以及Allowed to push是哪个角色。GitHub 路径是 Settings → Branches → Branch protection rules。如果你没有管理员权限看不到这些设置那就用行为反推新建一个普通分支推上去试试。git checkout -b feature/test-push git push -u origin feature/test-push如果普通分支能推、master不能推基本可以锁定是保护分支规则。这是最小复现验证动作比翻设置页更快。2.3 看服务端钩子日志如果你有服务端访问权限自建 GitLab、Gitea、裸仓库钩子日志是最终答案。GitLab 的钩子日志一般在# GitLab 自建环境查看某项目的钩子执行日志 sudo gitlab-rails console # 或在 shell 里直接看仓库的 hooks 目录 ls -l /var/opt/gitlab/git-data/repositories/namespace/project.git/custom_hooks/裸仓库bare repo的pre-receive脚本通常在hooks/pre-receive你可以直接读它看它校验了什么cat /path/to/repo.git/hooks/pre-receive常见校验逻辑包括提交信息必须匹配某个正则、禁止推送超过 N MB 的文件、禁止非管理员推 master。读到脚本报错原因就一目了然。2.4 权限与凭证核对如果钩子脚本没有明显拦截逻辑那大概率是权限问题。确认你推送用的账号# 查看当前 Git 使用的用户名和邮箱 git config user.name git config user.email # SSH 方式下测试认证到远端的实际账号 ssh -T gityour-git-hostssh -T返回的欢迎信息里通常会带上你的账号名对照项目成员列表看角色是否够。HTTPS 方式下凭证可能被系统钥匙串缓存成了旧账号需要清掉重输。3. 可复制配置修复推送 把 API endpoint 统一到 TaoToken定位清楚后修复动作分两块Git 侧恢复推送以及把联调用的 API 通道统一管理避免凭证散落各处。3.1 Git 侧的最小修复配置如果是保护分支最稳妥的做法是走合并请求Merge Request而不是去关保护。新建分支推送git checkout -b fix/pre-receive-issue git add . git commit -m fix: resolve pre-receive hook declined git push -u origin fix/pre-receive-issue推送成功后到远端发起 MR由有权限的人合并。如果你确实是管理员且业务允许也可以临时在设置里把master从保护分支移除但推完记得加回去。如果报错来自提交信息校验钩子按钩子要求的格式重写最近一次提交git commit --amend -m feat: 符合钩子规范的提交信息 git push origin master3.2 用 TaoToken 统一 API 通道推送流程恢复后很多项目会紧接着做接口联调。这时候如果每个服务各自配 endpoint 和 Key很容易出现「推送用 A 账号、调接口用 B Key」的混乱排查成本翻倍。我的做法是把模型调用的 endpoint 统一收敛到 TaoToken 通道Base URL 固定为https://taotoken.net/apiKey 在控制台统一生成管理。以常见的 OpenAI 兼容配置为例配置文件比如项目里的config.json或环境变量文件这样写{ base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model: claude-sonnet-4-5, timeout: 60 }如果你用的是 Claude Code 这类工具配置项名称可能是ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY值同样指向 TaoToken 的 API 地址和你在控制台生成的 Key。三件套务必写全Base URL、Key、Model ID缺一个都会在联调时报鉴权或模型不存在错误。Key 的生成入口在控制台的 API Keys 页面建议按项目或环境分别建 Key方便出问题时快速定位是哪个环节的凭证。模型 ID 的准确写法可以在模型对话页面确认避免手写拼错。4. 验证请求确认推送恢复且 API 联调成功修复动作做完必须验证不能靠「看起来好了」。推送侧验证# 再次 dry-run确认不再被拒 git push --dry-run origin master # 真正推送并观察输出 git push origin master成功时你会看到类似To remote abc1234..def5678 master - master的输出没有remote rejected。如果走的是 MR 流程去远端确认 MR 已创建、CI 开始跑。API 侧验证用 curl 直接打一次请求确认 endpoint 和 Key 生效curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的TaoToken密钥 \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-5, messages: [{role: user, content: ping}] }返回里带choices字段且内容正常说明通道打通。如果返回 401说明 Key 不对或没带上如果返回模型不存在说明 Model ID 写错了。这一步能提前把联调阶段的问题暴露出来而不是等业务代码跑起来才发现。5. 本篇常见错排查对照真实报错逐条解决排障时最怕报错信息看不懂。下面把几个高频报错和对应原因列清楚。! [remote rejected] master - master (pre-receive hook declined)服务端钩子拒绝优先查保护分支和钩子脚本参考第 2 节。remote: You are not allowed to push code to this project权限不足确认账号角色或改用 MR 流程。401 UnauthorizedAPI 联调时Key 缺失、过期或拼写错误。检查Authorization头是否带上了Bearer前缀Key 是否从控制台正确复制。local proxy failed/ 连接超时本地网络或代理配置问题检查环境变量里的HTTP_PROXY/HTTPS_PROXY是否指向了不可用的地址清掉后重试。reading choices相关报错通常是响应体解析失败多半是 endpoint 路径写错少了/v1或返回的不是预期 JSON。用第 4 节的 curl 先验证原始返回。OAuth相关报错凭证类型不匹配比如用 OAuth token 去走 API Key 的鉴权头。确认你用的是哪种凭证配置项别混用。排查时记住一个原则先看报错原文再对照上面归类不要凭感觉改配置。每改一处用最小命令验证一次避免多个变量同时变动导致无法定位。6. 把推送和鉴权都收敛到统一通道pre-receive hook declined本身不复杂复杂的是它背后牵扯的权限、钩子、凭证三件事。我的经验是Git 侧尽量走分支 MR别硬刚保护分支API 侧把 endpoint 和 Key 统一到 TaoToken 通道Base URL 固定https://taotoken.net/apiKey 按环境分开管理。这样推送和联调两条线各自清晰出问题时能快速判断是 Git 权限还是 API 鉴权。如果你正在做长期编码或 Agent 类项目需要频繁调用模型可以在控制台把 Key 和用量管理起来配合 Coding Plan 做长期规划只是临时验证模型效果用模型对话页面直接试更快。接入细节和配置项说明都在接入文档里遇到鉴权问题优先对照文档核对三件套是否写全。