GIT使用SSH 多账户配置
问题场景
需要同时使用:
- GitHub
- Gitee 码云
要求:零破坏性,完全隔离
核心原理
数据结构:
SSH 密钥对 ←→ SSH Config 路由规则 ←→ Git 远程仓库
路由逻辑:
- SSH 根据目标主机(
github.com
/gitee.com
)自动选择对应密钥 - Git 命令无需任何修改,完全透明
操作步骤
1. 生成 Gitee/GitHub 专用密钥
bash
ssh-keygen -t rsa -b 4096 -C "11956111@qq.com" -f ~/.ssh/id_rsa_gitee -N ""
参数说明:
-t rsa -b 4096
:RSA 算法,4096 位强度-C
:注释(通常填邮箱)-f
:指定文件名(避免覆盖现有密钥)-N ""
:空密码(可选,视安全需求)
输出:
- 私钥:
~/.ssh/id_rsa_gitee
- 公钥:
~/.ssh/id_rsa_gitee.pub
2. 创建 SSH Config 配置
bash
cat > ~/.ssh/config << 'EOF'
# gitbub
Host gitbub.com
HostName gitbub.com
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# Gitee 码云(个人账户)
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/id_rsa_gitee
IdentitiesOnly yes
EOF
关键配置项:
Host
:匹配规则(对应git@gitbub.com
或git@gitee.com
中的主机部分)HostName
:实际连接的主机地址(IP 或域名)IdentityFile
:指定使用的私钥IdentitiesOnly yes
:只使用指定密钥(防止 SSH 尝试所有密钥)
注意:
- Gitee 使用域名,Host 写域名
3. 设置正确权限
bash
chmod 600 ~/.ssh/id_rsa_gitee ~/.ssh/config
为什么:
- SSH 要求私钥和配置文件必须是
600
权限(仅所有者可读写) - 否则 SSH 会拒绝使用,报
permissions are too open
错误
4. 添加主机密钥(可选但推荐)
bash
ssh-keyscan gitbub.com >> ~/.ssh/known_hosts 2>/dev/null
ssh-keyscan gitee.com >> ~/.ssh/known_hosts 2>/dev/null
作用:
- 避免首次连接时的
Host key verification failed
错误 - 相当于预先信任这些主机
注意:
- 公司内网服务器可能无法通过
ssh-keyscan
扫描,首次连接时手动确认即可
5. 添加公钥到 Gitee
5.1 查看公钥
bash
cat ~/.ssh/id_rsa_gitee.pub
5.2 添加到 Gitee
- 访问:https://gitee.com/profile/sshkeys
- 点击 "添加公钥"
- 标题 :
Linux 工作站
(或任意标识) - 公钥 :粘贴公钥全部内容(包括
ssh-rsa
开头到邮箱结尾) - 点击 "确定"
6. 测试连接
bash
# 测试 Gitee
ssh -T git@gitee.com
预期输出:
Hi [你的用户名]! You've successfully authenticated, but GITEE.COM does not provide shell access.
bash
# 测试公司 GitLab(验证现有配置未被破坏)
ssh -T git@gitbub.com
预期输出:
Welcome to GitLab, @[你的用户名]!
如果gitbub测试失败:
- 检查
~/.ssh/id_rsa.pub
是否已添加到gitbub.com - 确认gitbub.com连接正常
日常使用
完全透明,无需任何特殊操作
bash
# Gitee 仓库
git clone git@gitee.com:username/repo.git
cd repo
git add .
git commit -m "update"
git push origin master
# 公司 GitLab 仓库
git clone git@gitbub.com:username/repo.git
cd repo
git add .
git commit -m "fix: 修复bug"
git push origin master
SSH 自动根据主机地址选择密钥,零心智负担。
故障排查
问题 1:Permission denied (publickey)
原因:
- 公钥未添加到远程平台
- SSH Config 配置错误
排查:
bash
# 查看 SSH 详细日志
ssh -vT git@gitee.com
# 检查 config 语法
cat ~/.ssh/config
# 验证密钥权限
ls -l ~/.ssh/id_rsa_gitee
问题 2:Bad owner or permissions on ~/.ssh/config
原因:
- 配置文件权限不对
修复:
bash
chmod 600 ~/.ssh/config
问题 3:仍然使用错误的密钥
原因:
IdentitiesOnly yes
未配置- SSH Agent 缓存了其他密钥
修复:
bash
# 清空 SSH Agent
ssh-add -D
# 确认 config 中有 IdentitiesOnly yes
grep -A4 "Host gitee.com" ~/.ssh/config
最佳实践
1. 密钥命名规范
~/.ssh/id_rsa # 公司 GitLab(已有)
~/.ssh/id_rsa_gitee # Gitee 码云
~/.ssh/id_rsa_github # GitHub(如果需要)
~/.ssh/id_rsa_company_vpn # 公司 VPN
原则:
- 文件名清晰表达用途
- 已有的默认密钥
id_rsa
保持不动(向后兼容) - 新密钥用描述性名称
2. 配置文件组织
bash
# ~/.ssh/config
# ============================================
# 工作相关
# ============================================
Host 10.xx.xx.xx
HostName 10.xx.xx.xx
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# ============================================
# 个人开发
# ============================================
Host gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/id_rsa_gitee
IdentitiesOnly yes
# ============================================
# 服务器跳板机(示例)
# ============================================
Host jumpserver
HostName jump.company.com
User your_username
IdentityFile ~/.ssh/id_rsa_server
Port 2222
原则:
- 分组注释
- 相关配置放一起
- 复杂配置写注释
3. 安全建议
密钥保护:
bash
# 生产环境密钥必须设置密码
ssh-keygen -t rsa -b 4096 -C "email@example.com" -f ~/.ssh/id_rsa_production
# 使用 SSH Agent 避免重复输入密码
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa_production
定期轮换:
- 生产环境密钥每 6-12 个月更换一次
- 离职/设备丢失立即吊销对应公钥
备份:
bash
# 备份私钥到加密存储(如 KeePassXC、1Password)
# 永远不要把私钥提交到 Git 仓库
核心思想
为什么这样设计?
-
好品味:无特殊情况
- 所有远程仓库走统一路由规则
- 无需在 Git 命令里指定密钥参数
-
零破坏性:向后兼容
- 现有配置完全不动
- 只添加新规则,不修改旧规则
-
最简实现:SSH 原生功能
- 无需任何第三方工具
- 无需
ssh-add
动态管理 - 无需环境变量或 shell 脚本
-
数据分离:最小权限原则
- 每个密钥职责单一
- GitLab 密钥无法访问 GitHub(反之亦然)
典型错误(不要这么干):
- ❌ 一个密钥给所有平台(安全风险,密钥泄露影响范围大)
- ❌ 用
GIT_SSH_COMMAND
环境变量(每次都要设置,复杂且易错) - ❌ 在
.gitconfig
里硬编码密钥路径(不同仓库需要不同配置)
特殊说明:IP 地址作为 Host
为什么公司 GitLab 配置中 Host 和 HostName 都是 IP?
bash
Host 10.xx.xx.xx # 匹配规则
HostName 10.xx.xx.xx # 实际连接地址
原理:
- Git URL 是
git@10.xx.xx.xx:cd/oneos/oneos-one.git
- SSH 提取主机部分
10.xx.xx.xx
- 在 config 中查找
Host 10.xx.xx.xx
- 匹配成功,使用对应的
IdentityFile
等价于域名配置:
bash
# 域名示例
Host gitlab.example.com
HostName gitlab.example.com
# IP 示例
Host 10.xx.xx.xx
HostName 10.xx.xx.xx
两者完全一样的逻辑,只是一个用域名,一个用 IP。
参考文档
最后一句话总结:
好的配置应该是透明的。用户不需要知道它的存在,它就能正确工作。
--- 这就是 "好品味" 的体现。