🛠️ 为什么配置 ~/.ssh/config 后,Sourcetree 就能正常推送了?

💡 出现的问题

我在 macOS 上开发 HarmonyOS 应用,使用 Sourcetree 管理 Git 代码,并通过 SSH 推送到 Gitee 仓库:

scss 复制代码
git@gitee.com:jc/testDemo.git

一切看起来都配置好了:

  • 已生成 Ed25519 SSH 密钥(带 passphrase)
  • 公钥已添加到 Gitee
  • 终端中 ssh -T git@gitee.com 测试成功
  • 终端中 git push 也能正常推送

但唯独 Sourcetree 一点击"推送",就报错

scss 复制代码
git@gitee.com: Permission denied (publickey).
fatal: Could not read from remote repository.

这让我非常困惑:为什么终端能推,Sourcetree 却不行?


🔍 查找问题根源:GUI 应用无法访问 SSH 密码

我的私钥 ~/.ssh/id_ed25519带密码(passphrase)保护的

当 SSH 客户端使用它时,必须提供这个密码才能解锁。

  • 在终端中 :我运行过 ssh-add ~/.ssh/id_ed25519,密码被缓存在 ssh-agent 中,所以 git push 成功。
  • 在 Sourcetree 中 :作为 GUI 应用,它无法访问终端的 ssh-agent,也无法弹出密码输入框 → 直接失败。

这就是典型的 "macOS GUI 应用与 SSH 密钥权限隔离" 问题。


✅ 突破口:配置 ~/.ssh/config

为了解决这个问题,我在 ~/.ssh/config 文件中添加了以下内容:

bash 复制代码
Host gitee.com
  IdentityFile ~/.ssh/id_ed25519
  AddKeysToAgent yes
  UseKeychain yes

并执行了一条关键命令:

javascript 复制代码
ssh-add -K ~/.ssh/id_ed25519

奇迹发生了:Sourcetree 立刻可以正常推送了!

那么,这一切是怎么发生的?


📚 ~/.ssh/config 是什么?

~/.ssh/config 是 OpenSSH 客户端的用户级配置文件,用于为不同主机(Host)定义连接参数。

它的作用类似于"SSH 的路由规则"------当你连接某个服务器时,SSH 会自动读取该文件,应用对应的设置。

例如:

  • 指定私钥路径
  • 设置别名(如 Host myserver → 实际连 user@192.198.1.100
  • 启用代理、端口转发等高级功能

在 macOS 上,它还有一个隐藏超能力:与系统钥匙串(Keychain)集成。


🔑 关键配置项解析

1. Host gitee.com

  • 表示:当连接 gitee.com 时,应用以下规则
  • 注意:这里写的是 gitee.com,不是 git@gitee.com,也不是完整 URL

2. IdentityFile ~/.ssh/id_ed25519

  • 明确指定使用哪个私钥文件
  • 避免 SSH 自动尝试多个密钥(如 id_rsa, id_ecdsa 等),提高效率和确定性

3. AddKeysToAgent yes

  • 如果密钥尚未加载到 ssh-agent自动加载
  • 确保密钥始终可用

4. UseKeychain yes(macOS 特有!)

  • 核心魔法所在!
  • 告诉 OpenSSH:把 passphrase 存储在 macOS 系统钥匙串(Keychain)中
  • 之后任何应用(包括 Sourcetree、VS Code、IDEA)在需要时,都能通过系统安全机制自动获取密码

🔐 ssh-add -K:把密码存进钥匙串

普通 ssh-add 只是把密钥加载到内存中的 ssh-agent,重启后就没了。

-K 参数是 macOS 特有的扩展

javascript 复制代码
ssh-add -K ~/.ssh/id_ed25519

它的作用是:

  1. 将密钥加入 ssh-agent
  2. 同时把 passphrase 写入 macOS 钥匙串(Keychain)
  3. 下次系统启动或 SSH 需要该密钥时,自动从钥匙串取出密码解锁

💡 你可以打开 "钥匙串访问" App,搜索 ssh,就能看到一条名为
SSH: /Users/xxx/.ssh/id_ed25519 的记录!


🔄 整个工作流程(Sourcetree 推送时)

  1. Sourcetree 执行 git push → 触发 ssh git@gitee.com
  2. SSH 客户端读取 ~/.ssh/config,匹配到 Host gitee.com
  3. 使用指定的私钥 ~/.ssh/id_ed25519
  4. 发现私钥有 passphrase,于是查询 macOS 钥匙串
  5. 从钥匙串中自动获取 passphrase,解锁私钥
  6. 完成 SSH 认证,推送成功 ✅

整个过程无需人工干预,GUI 应用也能像终端一样使用带密码的 SSH 密钥!


✅ 为什么这个方案如此优雅?

优势 说明
一次配置,永久生效 重启电脑后依然有效
所有 GUI 工具通用 Sourcetree、VS Code、WebStorm、Terminal 均受益
安全性高 passphrase 由系统级钥匙串保护,不暴露在脚本或环境变量中
符合 macOS 设计哲学 利用系统原生安全机制,而非 hack 方式

🛠️ 操作步骤总结(供读者复现)

  1. 确保已生成 SSH 密钥(带 passphrase)

    perl 复制代码
    ssh-keygen -t ed25519 -C "your@email.com"
  2. 将公钥添加到 Gitee/GitHub

  3. 创建或编辑 ~/.ssh/config

    javascript 复制代码
    nano ~/.ssh/config

    添加:

    bash 复制代码
    Host gitee.com
      IdentityFile ~/.ssh/id_ed25519
      AddKeysToAgent yes
      UseKeychain yes
  4. 将密钥加入钥匙串

    bash 复制代码
    ssh-add -K ~/.ssh/id_ed25519
    # 输入你的 passphrase
  5. 重启 Sourcetree(完全退出再打开)

  6. 愉快地推送吧! 🎉


📌 补充:多账号支持

如果你有多个 Gitee/GitHub 账号,可以这样配置:

bash 复制代码
# Gitee 个人账号
Host gitee-personal
  HostName gitee.com
  User git
  IdentityFile ~/.ssh/id_ed25519_personal
  UseKeychain yes
  AddKeysToAgent yes

# GitHub 工作账号
Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  UseKeychain yes
  AddKeysToAgent yes

然后远程地址改为:

kotlin 复制代码
git remote set-url origin git@gitee-personal:username/repo.git

希望这篇博客能帮到更多开发者!如果你觉得有用,欢迎点赞、收藏、转发 💙

相关推荐
967716 分钟前
初始web server的认识1---webserver的用途和工作流程
前端
叫我:松哥27 分钟前
基于神经网络算法的多模态内容分析系统,采用Flask + Bootstrap + ECharts + LSTM-CNN + 注意力机制
前端·神经网络·算法·机器学习·flask·bootstrap·echarts
vx_bisheyuange33 分钟前
基于SpringBoot的知识竞赛系统
大数据·前端·人工智能·spring boot·毕业设计
搂着猫睡的小鱼鱼36 分钟前
签名逆向与浏览器自动化 / 动态渲染抓取京东评论信息
前端·javascript·自动化
wangbing11251 小时前
ES6 (ES2015)新增的集合对象Set
前端·javascript·es6
nvd111 小时前
企业级 LLM 实战:在受限环境中基于 Copilot API 构建 ReAct MCP Agent
前端·copilot
Dragon Wu1 小时前
TailWindCss cva+cn管理样式
前端·css
烤麻辣烫1 小时前
Web开发概述
前端·javascript·css·vue.js·html
Front思2 小时前
Vue3仿美团实现骑手路线规划
开发语言·前端·javascript
徐同保2 小时前
Nano Banana AI 绘画创作前端代码(使用claude code编写)
前端