一、问题背景

某些项目在 macOS 上通过 IDE 打开时,会不断弹出类似下面的系统授权窗口:

git-credential-osxkeychain wants to use your confidential information stored in "gitlab.example.internal" in your keychain.

这类弹窗通常不是 GitLab 服务端异常,而是本机 Git 在访问 HTTPS remote 时,调用 macOS Keychain 凭据助手读取用户名、密码或 token。

典型本机 Git 配置如下:

git config --system --get credential.helper

输出:

osxkeychain

如果项目 remote 是 HTTPS:

git remote -v

示例输出:

origin  https://gitlab.example.internal/group/project.git (fetch)
origin  https://gitlab.example.internal/group/project.git (push)

那么 IDE 后台执行 fetchstatuspull 等操作时,就可能触发钥匙串访问。


二、初步判断:本机问题还是 GitLab 服务端问题?

排查时不要直接改配置,先收集证据。

1. 检查本机 Git 配置

git config --global --list --show-origin
git config --system --list --show-origin

重点看:

credential.helper=osxkeychain

这说明 Git 会使用 macOS 钥匙串管理 HTTPS 凭据。

2. 扫描本地仓库 remote

可以扫描常见项目目录:

find ~/Projects -path '*/.git/config' -type f -print0 \
  | xargs -0 grep -n 'https://gitlab.example.internal'

如果能看到大量类似配置:

/path/to/project/.git/config: url = https://gitlab.example.internal/group/project.git

说明这些项目打开时都有可能触发 HTTPS 凭据读取。

3. 检查 GitLab 服务端域名配置

如果是 Docker 方式部署 GitLab,可以进入容器检查:

docker exec gitlab grep -nE 'external_url|gitlab_shell_ssh_port|gitlab_ssh_host' /etc/gitlab/gitlab.rb

示例:

external_url 'https://gitlab.example.internal'

再检查生成后的配置:

docker exec gitlab grep -nE 'ssh_host|ssh_port' \
  /var/opt/gitlab/gitlab-rails/etc/gitlab.yml

如果 HTTPS 页面、证书、external_url 都正常,那么弹窗大概率不是 GitLab 服务端故障,而是本机 HTTPS 凭据链路导致。


三、为什么推荐从 HTTPS 改为 SSH?

HTTPS remote 的认证依赖凭据管理器,例如 macOS Keychain。
SSH remote 则使用本地 SSH key 认证,IDE 后台访问时不会再调用 git-credential-osxkeychain

HTTPS remote:

https://gitlab.example.internal/group/project.git

SSH remote:

git@gitlab.example.internal:group/project.git

如果 GitLab SSH 暴露端口不是标准 22,例如 Docker 宿主机使用 3022 映射容器内 22,可以通过 ~/.ssh/config 隐藏端口差异。


四、检查 GitLab SSH 服务端配置

假设 GitLab 运行在 Docker 中:

docker ps

示例输出:

gitlab/gitlab-ce:18.x.x   0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 0.0.0.0:3022->22/tcp

这说明:

宿主机 3022 端口 -> GitLab 容器 22 端口

此时需要在 GitLab 配置中显式声明外部 SSH 端口:

external_url 'https://gitlab.example.internal'

gitlab_rails['gitlab_ssh_host'] = 'gitlab.example.internal'
gitlab_rails['gitlab_shell_ssh_port'] = 3022

修改后执行:

docker exec gitlab gitlab-ctl reconfigure

验证:

docker exec gitlab grep -nE 'ssh_host|ssh_port' \
  /var/opt/gitlab/gitlab-rails/etc/gitlab.yml

预期类似:

ssh_host: gitlab.example.internal
ssh_port: 3022

五、本机生成 GitLab 专用 SSH Key

建议为自建 GitLab 单独生成一把 key,不混用服务器登录 key。

ssh-keygen -t ed25519 \
  -C "user@gitlab.example.internal" \
  -f ~/.ssh/id_ed25519_gitlab_example

如果希望 IDE 后台 fetch 不再弹其他密码提示,可以不设置 passphrase。
如果安全要求更高,也可以设置 passphrase,并配合 ssh-agent 使用。

查看公钥:

cat ~/.ssh/id_ed25519_gitlab_example.pub

示例:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIExamplePublicKey user@gitlab.example.internal

将这行公钥添加到 GitLab:

头像 -> Preferences -> SSH Keys -> Add new key

标题可以写:

MacBook Pro gitlab.example.internal

六、本机配置 SSH Host

如果 GitLab 实际端口是 3022,建议写入 ~/.ssh/config

Host gitlab.example.internal
    HostName gitlab.example.internal
    User git
    Port 3022
    IdentityFile ~/.ssh/id_ed25519_gitlab_example
    IdentitiesOnly yes

这样后续 remote 可以保持简洁:

git@gitlab.example.internal:group/project.git

而不需要每个 remote 都写成:

ssh://git@gitlab.example.internal:3022/group/project.git

验证 SSH 登录:

ssh -T git@gitlab.example.internal

成功时通常会看到:

Welcome to GitLab, @username!

七、单项目试迁移

不要一开始就批量改,先选一个项目验证。

查看当前 remote:

git remote -v

修改 remote:

git remote set-url origin git@gitlab.example.internal:group/project.git

验证:

git remote -v
git fetch --prune origin

如果 fetch 成功,说明 SSH 认证、GitLab 权限、remote 地址都正常。

也可以用更轻量的方式验证:

git ls-remote --heads origin

八、批量迁移本地仓库

确认单项目无误后,再扫描并迁移多个项目。

示例扫描:

find ~/Projects -path '*/.git/config' -type f -print0 \
  | xargs -0 grep -n 'https://gitlab.example.internal'

逐个改:

git -C /path/to/project-a remote set-url origin \
  git@gitlab.example.internal:group/project-a.git

git -C /path/to/project-b remote set-url origin \
  git@gitlab.example.internal:group/project-b.git

验证:

git -C /path/to/project-a ls-remote --heads origin
git -C /path/to/project-b ls-remote --heads origin

九、特殊情况:Submodule 仓库

如果项目里有 submodule,不能只改主仓库的 origin。还需要检查 .gitmodules

cat .gitmodules

HTTPS 示例:

[submodule "modules/example"]
    path = modules/example
    url = https://gitlab.example.internal/group/submodule.git
    branch = main

应改为:

[submodule "modules/example"]
    path = modules/example
    url = git@gitlab.example.internal:group/submodule.git
    branch = main

同步 submodule 配置:

git submodule sync --recursive

验证:

git submodule status --recursive
git config --get submodule.modules/example.url

注意:.gitmodules 是版本化文件,修改后会出现在 Git 工作区中,需要按团队流程提交。


十、如何确认已经没有 HTTPS GitLab remote?

可以全目录扫描:

find ~/Projects -path '*/.git/config' -type f -print0 \
  | xargs -0 grep -n 'https://gitlab.example.internal'

如果没有输出,说明这些仓库的 GitLab remote 已经不再走 HTTPS。

也可以扫描 SSH remote:

find ~/Projects -path '*/.git/config' -type f -print0 \
  | xargs -0 grep -n 'git@gitlab.example.internal'

十一、回滚方式

如果某个项目切换 SSH 后发现权限或流程问题,可以随时改回 HTTPS:

git remote set-url origin https://gitlab.example.internal/group/project.git

如果是 submodule,也需要改回 .gitmodules

url = https://gitlab.example.internal/group/submodule.git

然后同步:

git submodule sync --recursive

十二、附:关闭 GitLab Auto DevOps

如果当前不使用 GitLab Auto DevOps,可以关闭实例级默认开关,避免项目被默认套用 Auto DevOps 流水线。

使用 Rails runner:

docker exec gitlab gitlab-rails runner '
s = ApplicationSetting.current
s.update!(auto_devops_enabled: false)
puts s.auto_devops_enabled
'

验证:

docker exec gitlab gitlab-rails runner '
s = ApplicationSetting.current
puts({
  auto_devops_enabled: s.auto_devops_enabled,
  auto_devops_domain: s.auto_devops_domain
}.inspect)
'

预期:

{:auto_devops_enabled=>false, :auto_devops_domain=>nil}

总结

这类 macOS 钥匙串弹窗,本质上往往不是 GitLab 服务不可用,而是 HTTPS remote 触发了本机凭据助手访问。排查时建议按下面顺序处理:

  1. 确认项目 remote 是否使用 HTTPS。
  2. 确认本机 Git 是否启用了 osxkeychain
  3. 检查 GitLab 服务端 SSH 端口和 clone URL 配置。
  4. 生成专用 SSH key 并绑定到 GitLab 用户。
  5. 先单项目迁移验证,再批量迁移。
  6. 如果有 submodule,同步修改 .gitmodules

迁移到 SSH 后,IDE 后台 fetch、pull、branch refresh 等操作就不再依赖 macOS Keychain,弹窗问题也会自然消失。

标签: macOS, Git, GitLab

添加新评论