新装一台机器——开发机也好、服务器也好——想 clone、pull、push 你的 GitHub 仓库时,常会卡在认证。先理清什么时候需要认证:
- 只读 clone 公开仓库 → 不用认证,直接拉;
- 访问私有仓库(clone / pull / push) → 要认证;
- 向任何仓库 push(哪怕是公开仓库) → 也要认证。
也就是说,除了「拉公开仓库」,机器要对仓库做任何带权限的操作都得先有「身份」。配一次,之后这台机器就能正常 clone / pull / push 了。
主线:身份有两条路——SSH 密钥 或 Token(PAT),区别在于「这把钥匙能开多少扇门、能干什么」。
原理:公钥私钥怎么验证身份
下面两种 SSH 方式都基于一对密钥,先把它怎么验证身份说清楚:
- 私钥:留在你机器上(
~/.ssh/里),绝不外传; - 公钥:可以公开,交给 GitHub 登记。
它们是「非对称」的——用私钥算出的签名,只有配对的公钥能验证;而从公钥推不出私钥。验证流程大致是:
- 你事先把公钥登记到 GitHub(账号的 SSH keys,或仓库的 Deploy keys);
- 连接时你的机器发起 SSH,表示「我持有某公钥对应的私钥」;
- GitHub 用登记的公钥出一道随机「考题」(challenge);
- 你的机器用私钥对考题签名,把结果发回;
- GitHub 用公钥验证这个签名——验得过,就证明你确实握有配对的私钥,身份成立,放行。
你的机器 GitHub
│ ① 我持有某公钥对应的私钥 │
│ ───────────────────────────────▶ │
│ ② 随机考题 challenge │
│ ◀─────────────────────────────── │
│ ③ 用「私钥」签名考题,发回 │
│ ───────────────────────────────▶ │
│ ④ 用登记的「公钥」验签 → 放行 │
关键点:私钥从头到尾没离开过你的机器,网络上传的只是「用私钥算出的证明」。所以即使全程被监听,也偷不到私钥——这就是为什么公钥能随便公开、私钥必须保密。
方式一:SSH 密钥(账号级,最通用)
一把绑在你 GitHub 账号上的密钥,你名下所有仓库、clone / pull / push 全都能用,适合你自己常用的开发机。
① 生成密钥(一路回车即可):
ssh-keygen -t ed25519 -C "my-laptop"
它会问你保存路径(回车用默认 ~/.ssh/id_ed25519)和密码(回车 = 不设)。生成两个文件:id_ed25519(私钥,保密)和 id_ed25519.pub(公钥)。
-t ed25519:密钥类型,比老的 RSA 更短更安全,现在的推荐;-C "my-laptop":一段注释/标签,纯粹方便日后辨认,不影响功能。
② 把公钥加到账号:
cat ~/.ssh/id_ed25519.pub # 复制这串
GitHub → Settings → SSH and GPG keys → New SSH key → 粘贴。
③ 用 SSH 地址操作(默认名字的密钥 SSH 会自动使用,无需额外配置):
git clone [email protected]:ldddi/your-repo.git
ssh -T [email protected] # 验证:看到 "Hi ldddi!" 就通了
- 优点:配一次,覆盖你所有仓库和所有操作;
- 缺点:权限大——机器一旦失守,你所有仓库都暴露。所以服务器上更适合下面的只读 Deploy Key。
方式二:Deploy Key(只绑单个仓库,服务器/CI 首选)
一把只对一个仓库生效、还能设成只读的 SSH 密钥。适合 VPS 拉某个项目来部署——权限最小,机器被攻破也只影响这一个仓库的读取。
① 在那台机器上生成(同样一路回车):
ssh-keygen -t ed25519 -C "deploy-my-blog"
② 公钥加到「仓库」(不是账号):GitHub → 进入该仓库 → Settings → Deploy keys → Add deploy key → 粘贴 ~/.ssh/id_ed25519.pub。只是拉代码就别勾 “Allow write access”(保持只读最安全)。
③ 用 SSH 地址 clone / 切换远程:
git clone [email protected]:ldddi/my-blog.git
# 之前用 https clone 过的,改成 SSH:
git remote set-url origin [email protected]:ldddi/my-blog.git
进阶:一台机器要拉多个私有仓库
一把 Deploy Key 只能绑一个仓库,而默认名字 id_ed25519 一台机器只有一份。所以多个仓库时,要给每个仓库单独生成一把、用 -f 指定不同文件名:
ssh-keygen -t ed25519 -C "deploy-blog" -f ~/.ssh/key-blog -N ""
ssh-keygen -t ed25519 -C "deploy-repoA" -f ~/.ssh/key-repoA -N ""
(这里 -f 指定文件名、-N "" 设空密码,正是为了区分多把 key、且免交互。)
但自定义名字的 key,SSH 默认不会主动去用(它只认 id_ed25519 这类默认名)。所以要在这台机器上(不是 GitHub)编辑 ~/.ssh/config,告诉它「连哪个仓库用哪把 key」:
# 文件在拉代码的机器上:~/.ssh/config
Host github-blog # 自定义别名,随便起
HostName github.com
User git
IdentityFile ~/.ssh/key-blog # 这个别名用这把私钥
IdentitiesOnly yes
Host github-repoA
HostName github.com
User git
IdentityFile ~/.ssh/key-repoA
IdentitiesOnly yes
Host github-blog:一个别名——因为两个仓库都在 github.com,靠别名区分该用哪把 key;HostName/User git:实际连的还是 github.com、用户名固定git;IdentityFile:这个别名用哪把私钥;IdentitiesOnly yes:只用这把,别去试机器上其它 key(避免连错/被拒)。
clone 时把地址里的 github.com 换成你的别名:
git clone git@github-blog:ldddi/my-blog.git # 注意是 github-blog 不是 github.com
单仓库时用默认名字
id_ed25519即可,SSH 自动会用,不用折腾这个 config。
方式三:Personal Access Token(PAT,走 HTTPS)
不想用 SSH、或在 CI 里跑,就用 Token 走 HTTPS:
- GitHub → Settings → Developer settings → Fine-grained token,限定到指定仓库 + 给所需权限(只拉给
Contents: Read,要推送给Read and write); - clone:
git clone https://<TOKEN>@github.com/ldddi/your-repo.git
- 优点:权限可细到「某仓库只读」;适合 CI、纯 HTTPS 环境;
- 缺点:Token 会过期,要妥善保存、定期轮换。
怎么选
| 方式 | 能访问 | 能干什么 | 适合 |
|---|---|---|---|
| 账号 SSH 密钥 | 你所有仓库 | clone / pull / push | 自己的开发机 |
| Deploy Key | 单个仓库 | 默认只读(可开写) | 服务器 / CI 拉单个仓库 |
| PAT(HTTPS) | 可细粒度限定 | 按授予的权限 | CI、HTTPS 环境 |
小结
- 只读拉公开仓库不用认证;私有仓库、以及任何 push 都要;
- 自己的开发机 → 账号 SSH 密钥,一次配好、全仓库全操作通吃;
- 服务器拉单个仓库部署 → 只读 Deploy Key,权限最小、最安全;
- CI / HTTPS 环境 → PAT。