🛠️ 为什么配置 ~/.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

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

相关推荐
VT.馒头26 分钟前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript
css趣多多37 分钟前
一个UI内置组件el-scrollbar
前端·javascript·vue.js
C澒1 小时前
前端整洁架构(Clean Architecture)实战解析:从理论到 Todo 项目落地
前端·架构·系统架构·前端框架
C澒1 小时前
Remesh 框架详解:基于 CQRS 的前端领域驱动设计方案
前端·架构·前端框架·状态模式
Charlie_lll1 小时前
学习Three.js–雪花
前端·three.js
onebyte8bits1 小时前
前端国际化(i18n)体系设计与工程化落地
前端·国际化·i18n·工程化
C澒2 小时前
前端分层架构实战:DDD 与 Clean Architecture 在大型业务系统中的落地路径与项目实践
前端·架构·系统架构·前端框架
BestSongC2 小时前
行人摔倒检测系统 - 前端文档(1)
前端·人工智能·目标检测
0思必得02 小时前
[Web自动化] Selenium处理滚动条
前端·爬虫·python·selenium·自动化
Misnice2 小时前
Webpack、Vite、Rsbuild区别
前端·webpack·node.js