解决git报错[remote rejected] HEAD -> master (pre-receive hook declined):从pre-receive钩子到TaoToken推送链路排查 1. 从一次真实的 push 被拒说起pre-receive hook declined 到底是什么git push敲下去终端刷出一行红字remote: error: GH006: Protected branch update failed for refs/heads/master. remote: error: At least 1 approving review is required by reviewers with write access. ! [remote rejected] HEAD - master (pre-receive hook declined) error: failed to push some refs to gitgithub.com:xxx/xxx.git这段报错里最容易被忽略、也最关键的是括号里的pre-receive hook declined。它不是 Git 客户端的问题也不是网络断了而是服务端在真正写入 ref 之前用一个叫 pre-receive 的钩子脚本把你的推送拦下来了。理解这一点排查方向就不会跑偏——问题在远端仓库的规则不在你本地那台机器。pre-receive 钩子是 Git 服务端在接收推送时执行的第一个钩子。它拿到的是本次推送涉及的所有 ref 更新列表脚本可以逐条检查只要有一条不满足规则就整体拒绝返回非零退出码客户端看到的就是pre-receive hook declined。GitHub、GitLab、Gitee、自建 GitLab 都会用它来实现分支保护、提交信息校验、大文件拦截、签名校验等。所以这个报错的本质是服务端规则说「这次推送不合规」。常见触发场景有几类目标分支被设为保护分支要求 PR/MR 合并而非直接 push当前账号没有该分支的写权限提交信息不符合规范比如要求关联 issue 号推送里包含超过大小限制的文件仓库处于某种锁定或只读状态。很多人第一反应是「4 小时前还好好的怎么突然就不行了」。这种「突然」通常对应三种变化分支保护规则被管理员新加或调整你的账号权限被改动远端多了一个你本地没有的提交导致非快进推送被拒。最后一种尤其常见——别人或你自己在网页端往 master 提交了 README、改了配置你本地还停在旧位置push 时既不是快进、又撞上保护规则双重拦截。这篇内容就按一条完整链路来走先定位服务端钩子为什么拒绝再检查本地 remote 与认证配置最后用 TaoToken 统一 Key/API 通道验证整条推送链路是否通畅。每一步都给可复制的命令和配置片段照着做能定位到具体原因而不是靠猜。适合谁看刚接触 Git 协作、被保护分支规则卡住的新手在团队仓库里突然推不上去、需要快速定位的开发者以及想把认证和 API 通道统一管理、避免到处散落 Key 的人。下面从服务端钩子日志开始拆。2. 定位服务端钩子拒绝原因分支保护、权限与提交规范怎么查排查pre-receive hook declined的第一步是搞清楚到底是哪条规则拒绝了你。好消息是主流平台都会把拒绝原因写在remote:开头的行里只是很多人被最后那行remote rejected带偏了注意力。先把完整报错读一遍。2.1 读懂 remote 前缀的提示行以 GitHub 为例典型提示分几种remote: error: GH006: Protected branch update failed for refs/heads/master. remote: error: Required status check ci/build is expected.remote: error: GH013: Repository rule violations found for refs/heads/main. remote: error: - Cannot create ref refs/heads/main without a pull request.remote: error: You are not allowed to push code to protected branches on this project.GitLab 的提示风格不同但同样在remote:行里remote: GitLab: You are not allowed to push code to protected branches on this project. remote: error: hook declined to update refs/heads/master看到Protected branch、not allowed、pull request、status check这些词基本就能确定是分支保护或权限问题。看到commit message、issue、signed这类词则是提交规范或签名校验。把这些行复制出来单独看比盯着最后一行有用得多。2.2 用 git 命令确认远端状态与本地差异在改任何配置之前先确认本地和远端的关系# 查看当前分支与远端跟踪关系 git status -sb # 查看远端地址 git remote -v # 拉取远端最新状态但不合并 git fetch origin # 对比本地 master 与远端 master 的差异 git log --oneline --left-right --graph master...origin/master如果git log显示远端有本地没有的提交右侧有标记说明你的推送不是快进推送。这时候即使没有保护规则也可能被拒。先合并或变基# 方式一合并远端改动 git pull origin master --rebase # 方式二如果历史确实无关允许合并无关历史 git pull origin master --allow-unrelated-histories--allow-unrelated-histories这个参数在「本地仓库和远端仓库各自独立初始化过」时特别有用比如你在本地git init建了仓库远端也建了一个带 README 的仓库两边历史没有共同祖先普通 pull 会报refusing to merge unrelated histories。加上这个参数就能把远端那个 README 合并进来再一起 push。2.3 查看服务端钩子日志自建 GitLab 场景如果你用的是自建 GitLab服务端钩子日志能直接告诉你拒绝原因。登录服务器后# GitLab 的 pre-receive 相关日志 sudo gitlab-ctl tail gitlab-rails/production.log | grep -i pre-receive # 查看具体仓库的钩子执行记录 sudo ls -l /var/opt/gitlab/git-data/repositories/group/project.git/hooks/ # 查看 Gitaly 日志中的 push 拒绝记录 sudo gitlab-ctl tail gitalyGitLab 的 pre-receive 钩子通常由gitlab-shell调用日志里会记录push_access_check的结果。如果看到GitAccess::UnauthorizedError或ProtectedBranch::PushError就对应权限或保护分支问题。GitHub 这类托管平台看不到服务端日志但可以在仓库的Settings → Branches里查看分支保护规则在Settings → Actions里看是否有 required status checks。规则页面会明确列出要求 PR、要求审批数、要求状态检查通过、限制推送人员。对照报错里的关键词基本能锁定是哪条。2.4 权限与提交规范检查权限问题表现为你能 clone、能 fetch但 push 被拒。确认方式# 查看当前认证身份GitHub ssh -T gitgithub.com # 查看 Git 配置的用户信息 git config --list | grep user # 查看远端 URL 用的是 SSH 还是 HTTPS git remote get-url origin如果远端是 HTTPS认证走的是 token 或账号密码如果是 SSH走的是密钥。两者权限来源不同。团队仓库里常见的情况是你的账号只有 read 权限或者被移出了 write 组。提交规范方面有些仓库的 pre-receive 钩子会校验 commit message 格式比如要求feat: xxx或必须包含#123这样的 issue 号。检查最近提交git log --oneline -10如果格式不符合仓库约定用git commit --amend修改最近一条或用git rebase -i批量修改历史提交信息。改完再 push。到这里服务端侧的拒绝原因基本能定位。接下来处理本地 remote 与认证配置这部分是很多人忽略的「第二现场」。3. 本地 remote 与认证配置可复制的 git remote 配置片段服务端规则没问题push 还是失败问题往往出在本地 remote 地址或认证方式上。这一节给可直接复制的配置片段并说明每段的作用。3.1 检查并修正 remote 地址# 查看当前 remote git remote -v # 如果地址写错或协议不对先删除再添加 git remote remove origin git remote add origin gitgithub.com:yourname/yourrepo.git # 或者直接修改 URL git remote set-url origin gitgithub.com:yourname/yourrepo.gitSSH 和 HTTPS 两种协议的选择会影响认证方式。SSH 需要本地有密钥并已添加到平台HTTPS 需要 token。团队里如果统一用 SSH就别混用 HTTPS否则容易出现「同一个仓库别人能推你不能推」。3.2 认证配置SSH 密钥与 HTTPS tokenSSH 方式确认密钥已加载# 查看本地密钥 ls -al ~/.ssh # 测试连接 ssh -T gitgithub.com # 如果密钥没加载加入 ssh-agent eval $(ssh-agent -s) ssh-add ~/.ssh/id_ed25519HTTPS 方式建议用 token 而非密码并且不要把 token 明文写进 remote URL。可以用 credential helper 缓存# 启用凭证缓存macOS git config --global credential.helper osxkeychain # Linux 用 store 或 cache git config --global credential.helper cache --timeout36003.3 用统一 Key/API 通道管理认证TaoToken 配置片段当你在多个仓库、多个工具之间切换时认证信息散落各处很容易混乱。TaoToken 提供统一的 Key 与 API 通道把模型调用和编码工具的认证收敛到一处。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。下面给一份可复制的配置片段。以常见的编码工具配置为例把 Base URL、Key、Model ID 三件套写全{ base_url: https://taotoken.net/api, api_key: sk-你的TaoTokenKey, model: claude-sonnet-4-20250514 }如果你用的是 Claude Code 这类工具配置通常落在 settings 文件里。路径和字段名按工具实际约定来核心是三件套齐全{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的TaoTokenKey, ANTHROPIC_MODEL: claude-sonnet-4-20250514 } }Codex 类工具的auth.json也是同样的思路把 base URL、key、model 写清楚{ base_url: https://taotoken.net/api, api_key: sk-你的TaoTokenKey, model: gpt-5-codex }Cline 这类支持 MCP 的工具配置里同样需要 Base URL、Key、Model ID 三件套缺一不可。Key 的获取在控制台的 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。注意Key 属于敏感信息不要提交进 Git 仓库。把配置文件加入.gitignore或用环境变量注入。3.4 把配置纳入版本管理时的注意事项如果你确实需要把工具配置纳入仓库比如团队共享用占位符而非真实 Key# .gitignore 里排除真实配置 echo settings.local.json .gitignore echo .env .gitignore提交一份settings.example.json真实 Key 由每个人本地填。这样既共享了结构又不泄露凭证。本地 remote 和认证配置理清后就可以做一次完整的推送验证确认整条链路通畅。4. 验证推送链路一次成功 push 的完整动作与结果配置改完需要一次干净的验证来确认链路通了。这一节给完整的验证动作序列以及每一步的预期结果。4.1 推送前的自检清单# 1. 确认在正确的分支 git branch --show-current # 2. 确认工作区干净 git status # 3. 拉取远端最新避免非快进 git fetch origin git log --oneline -3 origin/master # 4. 确认本地领先远端的提交 git log --oneline origin/master..HEAD如果第 3 步显示远端有新提交先 rebase 或 mergegit pull --rebase origin master4.2 执行推送并观察输出git push origin master成功时的输出类似Enumerating objects: 12, done. Counting objects: 100% (12/12), done. Delta compression using up to 8 threads Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 1.23 KiB | 1.23 MiB/s, done. Total 7 (delta 3), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (3/3), completed with 2 local objects. To github.com:yourname/yourrepo.git a1b2c3d..e4f5g6h master - master关键看最后一行master - master没有rejected说明推送成功。如果还是被拒回到第 2 节重新读remote:提示行。4.3 用 TaoToken 通道验证 API 链路推送成功后如果你同时用 TaoToken 做模型调用或编码辅助可以顺手验证 API 通道是否通。用 curl 发一个最小请求curl -X POST https://taotoken.net/api/v1/messages \ -H Content-Type: application/json \ -H x-api-key: sk-你的TaoTokenKey \ -H anthropic-version: 2023-06-01 \ -d { model: claude-sonnet-4-20250514, max_tokens: 64, messages: [{role: user, content: ping}] }预期返回一段 JSON包含content字段和模型回复。如果返回 401说明 Key 不对或没带上返回 404检查 base URL 是否写成了https://taotoken.net/api而不是别的路径。模型对话入口在 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 可以在网页端直接验证 Key 是否可用。4.4 一次完整链路的验证结果把上面的动作串起来一次成功的验证应该满足检查项命令预期结果分支正确git branch --show-current输出 master 或你的目标分支工作区干净git statusnothing to commit远端已同步git fetch origin无报错本地可对比推送成功git push origin master出现master - masterAPI 通道通curl 请求返回模型回复 JSON五项都过说明从本地提交到远端接收、再到 API 通道整条链路是通的。任何一项失败对应到前面章节排查。5. 本篇常见报错排查401、local proxy failed、reading choices、OAuth实际排查中除了pre-receive hook declined本身还会撞上几个高频报错。这一节逐个对照真实报错给排查路径。5.1 401 Unauthorizedremote: HTTP Basic: Access denied fatal: Authentication failed for https://github.com/xxx/xxx.git/或 API 调用时{error:{type:authentication_error,message:invalid x-api-key}}401 的核心是认证信息不对。Git 推送场景下检查 token 是否过期、是否被撤销、是否有 repo 权限。API 场景下检查 Key 是否复制完整、是否带了多余空格、请求头字段名是否正确Anthropic 风格用x-api-keyOpenAI 风格用Authorization: Bearer。TaoToken 的 Key 在控制台 API Keys 页面重新生成后旧 Key 立即失效记得同步更新所有配置。5.2 local proxy failedError: local proxy failed to start: listen tcp 127.0.0.1:xxxx: bind: address already in use或工具启动时报failed to connect to local proxy这类报错是本地代理端口被占用或代理进程没起来。排查# 查看端口占用 lsof -i :端口号 # 杀掉占用进程 kill -9 PID # 或换一个端口如果是工具内置的本地代理检查配置文件里的端口设置避免和已有服务冲突。注意这里说的是工具自身的本地转发端口不是网络层面的代理两者概念不同排查时别混淆。5.3 reading choices 相关报错Error: reading choices: unexpected end of JSON input或failed to parse response: invalid character e looking for beginning of value这类报错通常出现在 API 响应解析阶段说明返回的内容不是预期的 JSON。常见原因base URL 配错请求打到了网页而非 API 端点Key 无效导致返回了 HTML 错误页模型 ID 写错导致服务端返回错误结构。排查顺序先用 curl 直接请求看原始返回是什么确认 base URL 是https://taotoken.net/api确认 model 字段是有效值。原始返回是 HTML基本就是 URL 或认证问题。5.4 OAuth 相关报错Error: OAuth token exchange failed或invalid_grant: The provided authorization grant is invalid, expired, or revokedOAuth 报错多出现在用账号授权登录的工具里。token 过期或被撤销是主因。处理方式重新走一次授权流程或在控制台重新生成凭证。如果工具同时支持 API Key 和 OAuth优先用 API Key配置更直接排查也更简单。TaoToken 的接入文档里有各工具的配置示例对照检查字段名和路径。5.5 排查通用思路把上面几类报错归纳成一条通用路径先看报错关键词属于哪一类认证、网络、解析、授权再定位到对应的配置项最后用最小请求验证。不要一上来就改一堆配置一次只改一个变量改完立即验证这样才能知道是哪个改动生效了。6. 把推送链路和 API 通道统一管理起来回到最初那个报错。pre-receive hook declined看起来吓人拆开就是三层服务端规则拒绝、本地与远端不同步、认证配置不对。按本文的顺序走一遍——先读remote:提示行定位规则再用git fetch和git log确认同步状态然后检查 remote 地址和认证方式最后做一次完整推送验证——绝大多数情况都能定位到具体原因。几个实操中值得记住的点。第一--allow-unrelated-histories是处理「本地和远端各自初始化」的利器但用之前先确认远端那个多出来的文件比如 README确实要合并进来别把无关内容带进历史。第二分支保护规则是团队协作的常态遇到时优先走 PR/MR 流程而不是想办法绕过绕过规则往往意味着权限配置有问题。第三认证信息集中管理能省很多事把 Base URL、Key、Model ID 三件套统一到一处工具之间切换时不用重复填。如果你在多个编码工具之间切换想统一 Key 和 API 通道可以从控制台生成一个 Key然后在各工具的配置里引用同一个 Base URL。长期做编码和 Agent 任务的可以了解 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。需要直接验证模型效果的用模型对话入口最快https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入细节和字段说明在文档里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。最后留一个实用习惯每次 push 被拒先把完整报错从头到尾读一遍尤其是remote:开头的行。Git 已经把原因告诉你了只是它藏在最后一行rejected的前面。