应为不同账号生成独立命名的密钥文件并配置~/.ssh/config,否则默认路径id_rsa会被覆盖导致Permission denied;必须用-f指定路径、-t ed25519、-C加邮箱注释,并在config中为每个Host定义IdentityFile,最后更新git remote URL为对应Host别名。

直接生成多个不同名字的密钥文件,而不是反复覆盖 id_rsa ——这是唯一安全、可追溯、不冲突的做法。
为什么不能只用 ssh-keygen 回车到底
默认路径 ~/.ssh/id_rsa 只能存一把私钥。如果为 GitHub 个人账号生成一次、又为公司 GitLab 账号再执行一次且不指定文件名,后者会直接覆盖前者,导致旧仓库 git push 突然失败,错误是:Permission denied (publickey)。
根本问题不是 Git,而是 SSH 客户端在连接时根本不会看你是谁、用了哪个 git config user.email,它只认 Host 名 + ~/.ssh/config 里配的 IdentityFile。
- 每次生成新密钥必须用
-f显式指定文件名,比如~/.ssh/github_personal - 推荐用
-t ed25519(比 RSA 更快更安全),不用-b 4096 - 注释
-C建议填邮箱,不是为了认证,是为了后期一眼看出这把密钥归属哪个账号
ssh-keygen -t ed25519 -C "me@work.com" -f ~/.ssh/gitlab_work
这条命令就是实际操作中最常写的完整形式。执行后你会得到两个文件:
-
~/.ssh/gitlab_work(私钥,权限必须是600,否则 SSH 拒绝加载) -
~/.ssh/gitlab_work.pub(公钥,复制整行内容到对应平台的 SSH Keys 设置页)
再为另一个账号生成时,换名字、换邮箱、换路径即可,例如:
ssh-keygen -t ed25519 -C "me@personal.org" -f ~/.ssh/github_personal
注意:不要在同一个 ~/.ssh/ 下生成重名文件,ssh-keygen 不会提醒你覆盖,它会静默写入。
生成后必须立刻配置 ~/.ssh/config
光有密钥文件没用,SSH 不会自动挑钥匙。你得告诉它:“当访问 git@gitlab.com 时,用哪把私钥”。靠的就是 ~/.ssh/config 文件里的 Host 块。
示例(请按需修改 Host 名和 IdentityFile 路径):
Host gitlab-work HostName gitlab.com User git IdentityFile ~/.ssh/gitlab_work Host github-personal HostName github.com User git IdentityFile ~/.ssh/github_personal
关键点:
-
Host名(如gitlab-work)是你自己定义的别名,后续所有git remote地址都要用它,比如git@gitlab-work:group/repo.git -
HostName是真实域名,不能少;User通常就是git,但有些自建 Git 服务可能用gituser,得看文档 - 确保
IdentityFile路径是绝对路径,~在 config 里不展开,必须写成/home/you/.ssh/xxx或用$HOME
测试前先确认权限和代理状态
常见失败不是配置错,而是环境没准备好:
- 私钥文件权限必须是
600:chmod 600 ~/.ssh/gitlab_work - 运行
ssh-add -l查看 ssh-agent 是否已加载密钥;如果输出The agent has no identities.,就手动加:ssh-add ~/.ssh/gitlab_work - 测试命令不是
ssh -T git@gitlab.com,而是ssh -T git@gitlab-work(用的是 config 里的 Host 别名!) - 成功响应是:
Hi username! You've successfully authenticated...;失败时若提示Bad owner or permissions,就是权限问题
最后一步:把仓库 remote URL 改成匹配 Host 别名的形式,比如 git remote set-url origin git@gitlab-work:group/repo.git —— 这才是多账户生效的关键动作,不是改 git config user.name。


















