1. 先别急着改代码pre-receive hook declined 到底卡在哪一层git push的时候看到! [remote rejected] master - master (pre-receive hook declined)第一反应往往是「我代码写错了」其实这个报错跟你的本地代码质量基本没关系。它是服务端在真正写入 refs 之前跑了一个叫pre-receive的钩子脚本脚本返回了非零退出码于是整个推送被拒绝。换句话说代码已经传到了服务端但服务端在「落库」前把它拦下来了。这个钩子能拦你的原因通常就三类权限不够、分支保护规则不让你推、钩子脚本自己校验失败比如提交信息格式、大文件、签名要求。很多人一看到pre-receive hook declined就去搜「git 权限配置」结果发现自己是 owner 还是被拒就是因为只查了权限这一层。我试过在一个多人协作仓库里推一个临时分支明明有写权限还是被pre-receive hook declined挡了三次最后发现是钩子脚本要求提交信息必须带 issue 编号。所以排查顺序很重要先确认 remote 指向哪、再确认分支策略、最后看钩子日志。这篇面向的是正在被这个报错卡住、想快速定位是权限、分支策略还是钩子脚本问题的开发者。你会看到可复制的git remote -v、git config检查命令钩子日志的查看步骤以及把 remote 改到 TaoToken 之后怎么验证推送链路是否恢复。适合对 git 有基础、但没怎么碰过服务端钩子的同学。核心检索词先记住pre-receive hook declined是服务端钩子拒绝不是本地错误git push被拒时排查路径是 remote 地址 → 分支保护 → 钩子日志逐层缩小范围。下面按这个顺序走。2. 把 remote 改到 TaoToken 前先确认推送链路和鉴权方式在动 remote 之前得先搞清楚现在这条推送链路是怎么走的。很多pre-receive hook declined的根因其实是 remote 指向了一个带服务端钩子的仓库而钩子规则你没满足。如果你打算把 remote 切到 TaoToken 的 API 网关来统一管理模型调用相关的代码仓库访问那更要先看清当前配置避免切过去之后还是被同一类规则拦。先看当前 remotegit remote -v输出大概是这样origin https://github.com/yourname/yourrepo.git (fetch) origin https://github.com/yourname/yourrepo.git (push)如果 push 地址和 fetch 地址不一致或者指向了一个你不认识的域名那问题可能就出在这。接着看当前分支和上游git branch -vv git config --get branch.master.remote git config --get branch.master.merge这几条能告诉你本地master到底往哪推、跟哪个远程分支对应。有时候你以为是推origin/master实际配置里写的是别的 remote报错自然对不上。然后看全局和本地的用户信息钩子脚本经常校验提交者邮箱git config --global user.name git config --global user.email git config --local user.email如果本地仓库的user.email是个没注册过的邮箱服务端钩子可能直接拒。这一步很多人忽略。关于 TaoToken 的接入它的 API 地址是https://taotoken.net/api官网在https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content。如果你要把 remote 切到 TaoToken 相关的仓库服务先拿到 API Key在控制台生成https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite。API Keys 管理页在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite。切换 remote 的命令git remote set-url origin https://taotoken.net/api/your-repo.git git remote -v注意TaoToken 的 API 网关主要面向模型调用和 coding 场景仓库推送是否走它取决于你的实际接入方式。如果你只是用 TaoToken 做模型对话或 coding plan那 remote 该指向哪还是指向哪别混为一谈。模型对话入口https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewriteCoding Plan 入口https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。注意改 remote 不会自动解决pre-receive hook declined它只是换了一条推送链路。如果新链路的服务端也有钩子同样可能被拒。所以改完必须验证。3. 可复制配置remote、分支保护和钩子日志三处一起查这一节给可直接复制的配置和命令。排查pre-receive hook declined的核心是三处remote 地址、分支保护规则、服务端钩子日志。前两处本地能查第三处要看服务端。3.1 remote 与鉴权配置先备份当前 remote再改git remote -v remote-backup.txt git remote set-url origin https://taotoken.net/api/your-repo.git git remote -v如果你用 SSH检查 keyssh -T gittaotoken.net用 HTTPS 的话确认 credential helpergit config --global credential.helperWindows 上可能是managermacOS 可能是osxkeychain。如果 credential 缓存了旧密码推送会 401。清掉重来git config --global --unset credential.helper git config --global credential.helper store3.2 分支保护规则检查分支保护是pre-receive hook declined最常见的非权限原因。以 GitLab 为例进项目 Settings → Repository → Protected branches看master或main是不是被保护了、允许谁 push、是否要求 MR。GitHub 在 Settings → Branches → Branch protection rules。本地能查的间接信号git ls-remote --heads origin如果这条命令能列出远程分支说明读权限没问题问题在写权限或钩子。如果连读都失败那是鉴权或网络层的问题。再看本地分支是否落后太多有些钩子要求 fast-forwardgit fetch origin git log --oneline origin/master..master如果输出一大堆说明你本地领先很多提交钩子可能因为「非快进」拒绝。3.3 钩子日志查看服务端钩子日志在服务器上路径通常是# GitLab sudo tail -f /var/log/gitlab/gitlab-rails/production.log sudo grep pre-receive /var/log/gitlab/gitlab-shell/gitlab-shell.log # 自建裸仓库 ls /path/to/repo.git/hooks/ cat /path/to/repo.git/hooks/pre-receive如果是自建仓库直接看钩子脚本内容里面会写清楚拒绝条件。比如#!/bin/bash while read oldrev newrev refname; do if [[ ! $refname ~ ^refs/heads/(master|main|develop)$ ]]; then echo 只允许推送到 master/main/develop exit 1 fi done看到exit 1前面的echo就知道拒绝原因了。GitLab 的钩子日志在gitlab-shell.log里搜pre-receive会打印具体拒绝信息。3.4 一个可复制的 settings 片段如果你用 Cline 或类似工具配合 TaoToken配置里要写全三件套Base URL、Key、Model ID。以 JSON 为例{ baseUrl: https://taotoken.net/api, apiKey: sk-你的key, model: claude-sonnet-4-20250514 }如果是 Codex 的auth.json{ base_url: https://taotoken.net/api, api_key: sk-你的key, model: gpt-4o }这三件套缺一不可。只填 Base URL 不填 Key会 401Key 对了 Model ID 写错会报 model not found。文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。4. 验证推送链路是否恢复从 dry-run 到真实 push改完 remote 和配置别直接git push先用 dry-run 验证git push --dry-run origin masterdry-run 会走完整个协商过程但不真正写入如果钩子会拒这里就能看到。输出类似To https://taotoken.net/api/your-repo.git ! [remote rejected] master - master (pre-receive hook declined) error: failed to push some refs如果 dry-run 通过输出会是To https://taotoken.net/api/your-repo.git abc1234..def5678 master - master然后真实推送git push origin master成功的话Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Writing objects: 100% (3/3), 300 bytes | 300.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0) To https://taotoken.net/api/your-repo.git abc1234..def5678 master - master验证远程 ref 是否更新git ls-remote origin master对比本地git rev-parse master两个 hash 一致就说明推送链路通了。如果你是用 TaoToken 做模型调用验证可以发一个请求确认 API 通curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的key \ -H Content-Type: application/json \ -d {model:claude-sonnet-4-20250514,messages:[{role:user,content:ping}]}返回带choices就说明 API 链路正常。这一步和 git push 是两条链路别混淆。5. 常见报错对照401、local proxy failed、reading choices、OAuth排查pre-receive hook declined时经常连带遇到其他报错。下面按真实报错对照。401 UnauthorizedKey 没填、填错、或过期。检查git config --get remote.origin.url里有没有带用户名密码以及 TaoToken 的 API Key 是否在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite生成。401 和pre-receive hook declined的区别是401 在鉴权层就被拒根本到不了钩子。local proxy failed本地代理配置有问题。检查git config --global --get http.proxy git config --global --get https.proxy env | grep -i proxy如果有代理设置但代理不可用清掉git config --global --unset http.proxy git config --global --unset https.proxyreading choices 报错通常是模型返回体解析失败比如 API 返回了错误 JSON 但客户端按正常结构读choices。检查返回体curl -s -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的key \ -H Content-Type: application/json \ -d {model:claude-sonnet-4-20250514,messages:[{role:user,content:hi}]} | jq .如果返回{error:...}说明请求本身有问题不是choices解析的锅。OAuth 相关报错Claude Code 或类似工具用 OAuth 登录时token 过期会报错。重新走一遍授权或改用 API Key 方式。Claude Code 接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite。CC Switch / Cline MCP / Codex auth.json 三件套只要出现这三个之一配置里必须写全 Base URL、Key、Model ID。缺一个就会报错。CC Switch 的配置片段{ provider: taotoken, baseUrl: https://taotoken.net/api, apiKey: sk-你的key, model: claude-sonnet-4-20250514 }Cline MCP 的配置在settings.json里同样三件套。Codex 的auth.json见 3.4 节。对照表报错层级排查点pre-receive hook declined服务端钩子权限、分支保护、钩子脚本401 Unauthorized鉴权Key、credential helperlocal proxy failed网络http.proxy 配置reading choices响应解析API 返回体结构OAuth 报错授权token 过期、改用 API Key6. 把 remote 切到 TaoToken 后的推送链路验证与长期用法把 remote 切到 TaoToken 之后验证推送链路是否恢复核心是三步dry-run 看钩子是否还拒、真实 push 看 ref 是否更新、ls-remote 对比 hash。这三步走完基本能确定是权限、分支策略还是钩子脚本的问题。如果 dry-run 还是pre-receive hook declined说明新链路的服务端也有钩子得回到第 3 节查钩子日志。如果 dry-run 通过但真实 push 失败多半是并发或 ref 冲突重新 fetch 再推。长期用的话建议把常用配置固化。比如在~/.gitconfig里加[credential] helper store [user] name yourname email youremail.comTaoToken 的 API Key 放在环境变量里别硬编码export TAOTOKEN_API_KEYsk-你的key然后在配置里引用。这样换机器不用改代码。如果你长期做编码和 Agent 任务Coding Plan 比按次调用更划算入口在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite。模型对话验证用https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite。接入文档和排障看https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。最后提醒一句pre-receive hook declined不是本地 git 的错别去git reset或重装 git。按 remote → 分支保护 → 钩子日志的顺序查九成能定位。改 remote 只是换链路钩子规则该满足还得满足。