凭证 helper 锁住,pull / push 全失败

git pull 或 push 时反复弹出密码提示或报 403 / 401,明明凭证正确却始终认证失败,甚至凭证 helper 进程锁住导致操作卡死。本文给出清理缓存凭证、重置 helper 配置的完整修复方案。

你在 CI 环境或者换了新 Mac 后,执行 git pullgit push 时一直提示输入用户名和密码,输入后报 403 或直接静默失败。又或者本机的 git-credential-osxkeychain 在升级 macOS 后死锁,每次 push 都卡在认证步骤几十秒后超时。这类问题的根源通常不在代码本身,而在于凭证 helper 的配置错误、缓存过期的 token、或者 helper 进程本身的状态问题。

常见原因

1. 缓存的 Personal Access Token 已过期或被撤销

GitHub/GitLab 的 PAT(Personal Access Token)有有效期,过期后凭证 helper 里存储的旧 token 依然被自动发送,服务端返回 401,但终端没有明确提示 token 过期,只显示认证失败。

怎么判断git credential fill 然后输入 protocol=httpshost=github.com 加回车两次,若输出的 password 字段是旧 token,去 GitHub Settings > Developer settings 确认该 token 是否还有效。

2. macOS Keychain 里有多个同名凭证互相冲突

在 macOS 上多次配置 GitHub 凭证(比如换过账号、换过 token)后,Keychain 里可能有多个 github.com 条目,Git 取到了其中一个旧的或错误的,导致认证失败但也不报具体哪个条目有问题。

怎么判断:打开「钥匙串访问」(Keychain Access),搜索 github.com,若有多个条目,说明存在冲突。

3. 凭证 helper 进程(如 git-credential-manager)僵死

Git Credential Manager(GCM)在认证流程中打开浏览器窗口进行 OAuth,但浏览器没有响应或者 OAuth callback 端口被占用,导致 GCM 进程挂起,后续所有 git 操作都卡在等待 GCM 响应。

怎么判断ps aux | grep credential 若有长时间运行的 git-credential-manager 进程(运行时间超过 1 分钟),说明进程挂起了。

4. SSH 和 HTTPS 混用导致 helper 配置失效

仓库的 remote URL 是 https://github.com/org/repo.git,但 SSH key 已配置好,开发者以为用的是 SSH,实际走的是 HTTPS,凭证 helper 接管了认证,而 HTTPS 的 token 不在 helper 里。

怎么判断git remote -v 查看 remote URL,若以 https:// 开头,走的是 HTTPS 认证,不会使用 SSH key。

5. 企业 SSO 要求对 PAT 进行 SAML 授权

GitHub Enterprise Cloud 的组织开启了 SSO 后,PAT 必须经过 SAML 授权才能访问该组织的仓库。未授权的 PAT 在 push/pull 时返回 403,错误信息通常是「The ‘Authorization’ request header field is not allowed」。

怎么判断:访问 GitHub Settings > Developer settings > Personal access tokens,查看 PAT 是否有 SSO 授权的「Configure SSO」按钮和已授权的组织列表。

6. 凭证 helper 配置指向了不存在的程序路径

git config --global credential.helper /usr/local/bin/git-credential-osxkeychain,但该路径在系统更新后已移动到 /usr/bin/git-credential-osxkeychain,导致 helper 调用失败,Git 回退到无凭证状态,每次都重新询问。

怎么判断git config --list | grep credential.helper 获取 helper 路径,which git-credential-osxkeychain 确认实际路径,对比是否一致。

最短修复路径

Step 1:清除所有缓存凭证,重新认证

# macOS — 删除 Keychain 里的 GitHub 凭证
git credential-osxkeychain erase <<EOF
protocol=https
host=github.com
EOF

# Linux — 清除 libsecret 存储的凭证
git credential reject <<EOF
protocol=https
host=github.com
EOF

# 使用 GCM — 清除指定 host 的凭证
git credential-manager erase <<EOF
protocol=https
host=github.com
EOF

Step 2:重新生成 PAT 并存入 helper

在 GitHub/GitLab 生成新 PAT(GitHub 推荐使用 Fine-grained token,选择合适的权限),然后:

git push  # 会弹出凭证输入
# username: 你的 GitHub 用户名
# password: 粘贴新的 PAT(不是账号密码)

Step 3:修复 macOS Keychain 多条目冲突

# 查看所有 github.com 凭证条目
security find-internet-password -s github.com

# 删除旧条目(逐条)
security delete-internet-password -s github.com -a <account-name>

Step 4:修复 helper 路径配置

# 查看当前配置
git config --global credential.helper

# 修复路径(macOS)
git config --global credential.helper osxkeychain

# 使用 GCM(跨平台推荐)
git config --global credential.helper /usr/local/share/gcm-core/git-credential-manager

# 确认 helper 可执行
which git-credential-osxkeychain

Step 5:为 GitHub Enterprise SSO 授权 PAT

在 GitHub.com 登录后,进入 Settings > Developer settings > Personal access tokens,找到使用的 PAT,点击「Configure SSO」,为对应组织点击「Authorize」,再重新 push。

Step 6:若怀疑 GCM 进程卡死,强制终止

pkill -f git-credential-manager
# 再次尝试 git pull

预防建议

  • 使用 GitHub CLI(gh auth login)管理认证,它处理 token 刷新和 SSO 授权比手动管理 PAT 更可靠,且支持多账号切换。
  • 为 PAT 设置足够长的有效期(90 天或 1 年),并在日历里设置提前 2 周的到期提醒,避免突然失效阻断工作。
  • SSH 认证比 HTTPS + PAT 更稳定,不存在 token 过期问题。如果仓库支持 SSH,改用 git@github.com:org/repo.git 的 remote URL。
  • CI 环境使用专用的 Deploy Key 或 GitHub App installation token,而不是个人 PAT,避免个人账号改密后 CI 全线失败。
  • 配置凭证 helper 时验证路径:git config --global credential.helper && which $(git config --global credential.helper) 确认 helper 可执行。
  • 在团队 wiki 里记录 SSO 组织授权步骤,新成员入职时经常会遇到这个问题。

常见问答 (FAQ)

Q: git config credential.helper store 把密码明文存在文件里安全吗? A: 不安全。store helper 把凭证以明文存在 ~/.git-credentials,任何能读取该文件的进程都能拿到 token。推荐使用 osxkeychain(macOS)或 GCM(跨平台),凭证存储在系统的加密密钥库里。

Q: 同一台机器需要同时用两个 GitHub 账号怎么配置? A: 使用 SSH + 多个 SSH key 最简单:在 ~/.ssh/config 里配置两个 Host 别名(如 github-workgithub-personal),对应不同的 IdentityFile,remote URL 使用别名 git@github-work:org/repo.git

Q: GCM 打开了浏览器但我在没有 GUI 的服务器上,怎么办? A: export GCM_CREDENTIAL_STORE=plaintext 或者 git config --global credential.credentialStore plaintext,让 GCM 使用文件存储而不是 GUI 流程。或者改用 GIT_CREDENTIAL_INTERACTIVE=false 跳过交互,配合 PAT 环境变量使用。

Q: GitHub Actions 里如何避免 credential 问题? A: 使用 GITHUB_TOKEN(自动生成,有效期为 job 运行时间)或配置 secrets.MY_PAT,通过 git config url."https://x-access-token:${{ secrets.MY_PAT }}@github.com/".insteadOf "https://github.com/" 注入认证。

相关阅读

标签: #git #version-control #排查