核心原则:把身份问题拆成五层
多账号的关键不是“GitHub 账号切换”,而是让每次 SSH 连接都有明确入口,让每次 Git 提交都有明确作者。
id_ed25519_github_work
github-work
git@github-work:OWNER/REPO.git
github-personal、github-work、github-client 指向同一个 github.com。
[email protected]:... 就会走默认账号;写别名才会走对应密钥。
git config。
命名先定好,后面就不乱
推荐把“账号用途”写进私钥名和 Host 名。命名越朴素,长期维护越稳定。
| 用途 | 私钥文件 | SSH Host | 克隆地址形态 |
|---|---|---|---|
| 个人账号 | id_ed25519_github_personal |
github-personal |
git@github-personal:OWNER/REPO.git |
| 工作账号 | id_ed25519_github_work |
github-work |
git@github-work:OWNER/REPO.git |
| 客户账号 | id_ed25519_github_client |
github-client |
git@github-client:OWNER/REPO.git |
示例邮箱请替换为对应 GitHub 账号邮箱。真实私钥口令不要写进脚本、笔记、教程或仓库,建议放进密码管理器。
Windows:用 PowerShell 建立多账号 SSH 路由
Windows 默认建议把密钥放在当前用户的 .ssh 目录。自定义目录也可以,但要把 IdentityFile 和权限一起处理好。
id_ed25519 不要急着删,给新账号生成新密钥即可。
-f 后面写私钥文件路径,不需要加 .pub。
ssh -T 返回的 USERNAME 必须是你期望的账号。
生成密钥
Get-ChildItem "$env:USERPROFILE\.ssh"
New-Item -ItemType Directory -Force "$env:USERPROFILE\.ssh"
ssh-keygen -t ed25519 -C "[email protected]" -f "$env:USERPROFILE\.ssh\id_ed25519_github_personal"
ssh-keygen -t ed25519 -C "[email protected]" -f "$env:USERPROFILE\.ssh\id_ed25519_github_work"
如果你希望放在自定义目录,例如 D:\git-ssh:
New-Item -ItemType Directory -Force "D:\git-ssh"
ssh-keygen -t ed25519 -C "[email protected]" -f "D:\git-ssh\id_ed25519_github_personal"
ssh-keygen -t ed25519 -C "[email protected]" -f "D:\git-ssh\id_ed25519_github_work"
启动 agent,复制公钥
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
ssh-add "$env:USERPROFILE\.ssh\id_ed25519_github_personal"
ssh-add "$env:USERPROFILE\.ssh\id_ed25519_github_work"
ssh-add -l
Get-Content "$env:USERPROFILE\.ssh\id_ed25519_github_work.pub" | Set-Clipboard
然后进入对应 GitHub 账号:Settings -> SSH and GPG keys -> New SSH key。每个账号各贴自己的公钥。
写入 SSH config
New-Item -ItemType Directory -Force "$env:USERPROFILE\.ssh"
New-Item -ItemType File -Force "$env:USERPROFILE\.ssh\config"
notepad "$env:USERPROFILE\.ssh\config"
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_personal
IdentitiesOnly yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_work
IdentitiesOnly yes
自定义目录时,Windows 的 SSH config 建议使用正斜杠:
Host github-work
HostName github.com
User git
IdentityFile D:/git-ssh/id_ed25519_github_work
IdentitiesOnly yes
验证账号
ssh -T git@github-personal
ssh -T git@github-work
成功时会看到类似 Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.。确认每个 Host 显示的是预期账号。
macOS:把密钥交给钥匙串
macOS 的重点是 AddKeysToAgent yes 和 UseKeychain yes,让系统钥匙串保存私钥口令。
生成密钥
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_github_personal
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_github_work
如果想放在 ~/git-ssh:
mkdir -p ~/git-ssh
chmod 700 ~/git-ssh
ssh-keygen -t ed25519 -C "[email protected]" -f ~/git-ssh/id_ed25519_github_personal
ssh-keygen -t ed25519 -C "[email protected]" -f ~/git-ssh/id_ed25519_github_work
保存口令并复制公钥
eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_github_personal
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_github_work
ssh-add -l
pbcopy < ~/.ssh/id_ed25519_github_work.pub
旧系统如果不支持 --apple-use-keychain,可以尝试 ssh-add -K ~/.ssh/id_ed25519_github_work。
推荐 config
test -f ~/.ssh/config && echo "config exists" || echo "config missing"
touch ~/.ssh/config
chmod 600 ~/.ssh/config
nano ~/.ssh/config
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_personal
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_work
IdentitiesOnly yes
AddKeysToAgent yes
UseKeychain yes
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519_github_*
chmod 644 ~/.ssh/*.pub
ssh -T git@github-personal
ssh -T git@github-work
Linux:权限是稳定性的底线
Linux 路线和 macOS 接近,但更要注意 ~/.ssh、私钥和 config 的权限。
生成密钥并添加到 agent
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_github_personal
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519_github_work
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_github_personal
ssh-add ~/.ssh/id_ed25519_github_work
ssh-add -l
自定义目录示例:
mkdir -p /data/git-ssh
chmod 700 /data/git-ssh
ssh-keygen -t ed25519 -C "[email protected]" -f /data/git-ssh/id_ed25519_github_work
ssh-add /data/git-ssh/id_ed25519_github_work
复制公钥和配置 Host
xclip -selection clipboard < ~/.ssh/id_ed25519_github_work.pub
# Wayland:
wl-copy < ~/.ssh/id_ed25519_github_work.pub
# 没有剪贴板工具:
cat ~/.ssh/id_ed25519_github_work.pub
Host github-personal
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_personal
IdentitiesOnly yes
AddKeysToAgent yes
Host github-work
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_work
IdentitiesOnly yes
AddKeysToAgent yes
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config
chmod 600 ~/.ssh/id_ed25519_github_*
chmod 644 ~/.ssh/*.pub
ssh -T git@github-personal
ssh -T git@github-work
日常使用:看 remote,也看提交邮箱
认证账号和提交作者是两套系统。推送失败时检查 SSH;提交身份不对时检查 Git config。
~/.ssh/config 里的 Host 别名。
# 个人账号
git clone git@github-personal:OWNER/REPO.git
# 工作账号
git clone git@github-work:OWNER/REPO.git
git config user.name "Your Name"
git config user.email "[email protected]"
git config --get user.name
git config --get user.email
已有仓库改用另一个账号
git remote -v
git remote set-url origin git@github-work:OWNER/REPO.git
git fetch
确认当前仓库到底连到哪里
git remote -v
ssh -T git@github-work
git config --show-origin --get user.email
可选增强:按目录自动切换提交身份
如果个人项目和工作项目固定放在不同目录,可以让 Git 根据路径自动加载不同的作者信息。
[user]
name = Personal Name
email = [email protected]
[includeIf "gitdir:~/code/work/"]
path = ~/.gitconfig-work
[user]
name = Work Name
email = [email protected]
Windows 也可以使用类似写法,路径建议用正斜杠:
[includeIf "gitdir:C:/Users/YourName/code/work/"]
path = C:/Users/YourName/.gitconfig-work
includeIf 只负责提交作者身份,不负责 SSH 认证。SSH 认证仍然由 remote URL 里的 Host 别名决定。
第三个账号、自建 Git 服务,也是一套逻辑
新增账号时重复三件事:生成新私钥,把公钥加到对应账号,在 SSH config 新增 Host。
Host github-client
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github_client
IdentitiesOnly yes
git clone git@github-client:OWNER/REPO.git
如果使用公司或客户自建 Git 服务,Host 是本机别名,HostName 才是真实服务器域名。
Host client-git
HostName ssh.example-git.net
User git
IdentityFile ~/.ssh/id_ed25519_client_git
IdentitiesOnly yes
常见问题排查:先定位是哪一层错了
不要从头重配。先看错误信息,再判断是仓库路径、账号权限、密钥加载、Host 别名还是提交身份。
OWNER/REPO 是否正确、私有仓库是否授权、remote 是否误用 github.com。
ssh-add -l、公钥是否贴到正确账号、IdentityFile 路径是否存在。
[email protected]:OWNER/REPO.git,改成 Host 别名。
ssh-agent,macOS 看钥匙串,Linux 看当前 shell 是否有 agent。
ssh-add -l
ssh -vT git@github-work
git remote -v
git config --show-origin --get user.email
Windows 私钥权限过宽
如果看到 UNPROTECTED PRIVATE KEY FILE、Bad permissions,说明私钥文件继承了过宽 ACL,OpenSSH 会忽略它。
$key = "E:\codeIDE\github-ssh-id_ed25519\id_ed25519_juice520"
icacls $key
如果出现 NT AUTHORITY\Authenticated Users、BUILTIN\Users、Everyone,可以收紧权限:
$key = "E:\codeIDE\github-ssh-id_ed25519\id_ed25519_juice520"
$me = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
takeown /F $key
icacls $key /inheritance:r
icacls $key /remove:g "NT AUTHORITY\Authenticated Users" "BUILTIN\Users" "Everyone"
icacls $key /grant:r "$($me):(R)"
icacls $key
ssh-add "E:\codeIDE\github-ssh-id_ed25519\id_ed25519_juice520"
如果目录本身也继承了过宽权限,把目录一起收紧:
$dir = "E:\codeIDE\github-ssh-id_ed25519"
$me = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
icacls $dir /inheritance:r
icacls $dir /remove:g "NT AUTHORITY\Authenticated Users" "BUILTIN\Users" "Everyone"
icacls $dir /grant:r "$($me):(OI)(CI)(F)"
最小可用清单
做到下面六点,多账号长期并存就会非常稳定。
- ✓每个账号有独立私钥,例如
~/.ssh/id_ed25519_github_work。 - ✓GitHub 对应账号里添加了这把私钥的
.pub公钥。 - ✓
~/.ssh/config有独立 Host,例如github-work。 - ✓
ssh -T git@github-work显示正确 GitHub 用户名。 - ✓仓库 remote 使用
git@github-work:OWNER/REPO.git。 - ✓仓库内
git config user.email是该账号希望展示的提交邮箱。