一台电脑两个github账号问题
Table of Contents
提交项目到github示例
这是一个从初始化一个git项目到提交到github的实例演示
# 创建一个learn-git文件夹并进入该文件夹
mkdir ~/Code/learn-git && cd ~/Code/learn-git
# 在learn-git文件夹内执行git初始化(会在learn-git文件夹下生成一个名为“.git”的隐藏文件夹)
git init
# 在learn-git文件夹下添加一个文件
echo "This is a test!" > test.txt
# 把test.txt文件添加到git暂存区
git add test.txt
# 把该文件提交到本地仓库
git commit -m "first commit"
# 添加远程仓库地址(在github创建“learn-git”项目,得到这个地址)
git remote add origin https://github.com/zhangsan/learn-git.git
# push到远程仓库(-u把origin设置为上游)
git push -u origin main
在2021年8月13日之前,在你执行git push -u origin main
这句推送代码命令时,它会弹出让你输入github的账号密码,验证通过后才能上传。
然后输出以下内容(事实上这个并不会发生,原因往下看)
枚举对象中: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 227 字节 | 227.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
To https://github.com/zhangsan/learn-git.git
* [new branch] main -> main
分支 ‘main’ 设置为跟踪来自 ‘origin’ 的远程分支 ‘main’。
但是很遗憾,即使你输入正确的账号密码,它也不会上传,而是会出现以下提示
remote: Support for password authentication was removed on August 13, 2021.
出现上述提示的原因,是因为github在2021年8月13日移除了对账号密码的支持,理由是安全性不高,所以从这一天开始,github就无法通过账号密码来认证上传代码了。
在github添加公钥
github禁止了账号密码后,只能通过公私钥对来认证了,也就是说,https协议的github仓库链接,你只能用来下载代码,如果你想上传代码,必须使用ssh协议的链接
创建公私钥对:
首先要创建一对公私钥对,我相信能研究本文的同学肯定都已经有公私钥对了,在你电脑的~/.ssh/
文件夹下,应该是会有一个“id_rsa”(私钥)和“id_rsa.pub”(公钥)。
如果没有,请用以下命令创建(运行后无论提示什么,一路按回车即可)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_4096 -C "abc123@gmail.com"
注:记得把“abc123@gmail.com”换成你的邮箱,不是必须要github登录邮箱,它只是个标记而已,不会用于验证邮箱。
以上命令最终会在你的~/.ssh/
文件夹下生成两个文件: id_rsa_4096和id_rsa_4096.pub。
其中带.pub
结尾的就是公钥(pub是public的意思),我们需要把公钥添加到github中,这样github就能通过公钥来与我们本地的私钥来加密传输数据了(公钥加密的数据只有对应的私钥能解,私钥签名的数据只有公钥验证数据是否被篡改)。
把公钥添加到github:
登录github后,点击右上角头像→Settings→点击左侧边栏的“SSH and GPG keys”→点击右侧的“New SSH Key”
把前面生成的公钥“id_rsa_4096.pub”中的内容复制粘贴到下边框中,如果是mac,用以下命令就可以直接复制到剪贴板了,文件都不需要打开
cat ~/.ssh/id_rsa_4096.pub | pbcopy
添加完成后,在你电脑客户端运行以下命令
ssh -T git@github.com
如果一切正常,它会输出以下内容,告诉你你已成功被认证
Hi xxx! You’ve successfully authenticated, but GitHub does not provide shell access.
关于前面的ssh命令的解释
我们知道ssh user@host
是可以登录一台服务器的,比如ssh zhangsan@192.168.1.2
,但为什么ssh -T git@github.com
不会登录呢?因为-T
!
ssh有-t
和-T
选项,这两个t都是Terminal(终端,在这里指伪终端,pseudo terminal)的意思,在命令(不止是ssh命令)中经常有一个不成文的规则,当两个选项相同,一个大写,一个小写时,一般小写表示“是”,而大写正好相反,表示“否”,所在在这里,这个大写的-T
表示不分配伪终端,当我们用ssh登录Linux远程主机时,它都会让我们输入账号密码,我们输入账号密码后,就“登录”进去了,这个其实就是分配了一个“伪终端”,而我们通过ssh连接github、gitee等,其实是没有权限操作它的服务器的,所以它也不可能给我们分配终端的,所以需要用-T
来指定不分配伪终端。
假如不用-T
或用-t
(默认就是-t
),也就是你希望github服务器给你分配伪终端,它会输出如下提示,当然是不可能给你提供终端的啦,毕竟人家又不是给你用服务器
PTY allocation request failed on channel 0
通过公私钥对来上传
通过公私钥上传,必须使用ssh协议地址,而不能是https协议地址,因为公私钥上传本质上就是ssh传输,当然就得用ssh协议地址了。
在github创建一个仓库后,我们可以选择是用HTTPS还是SSH地址
从上图中可以看到,SSH地址是git@github.com
开头的,其实它就是user@host
,本质上就相当于github的服务器上创建了一个名为“git”的用户,然后你使用这个用户来向github服务器通过ssh协议传输数据。
现在我们可以来解决本文开头上传不了的问题。
首先要把github仓库链接改为git协议的
git remote set-url origin git@github.com:xiebruce/learn-git.git
然后再来push,就能正常push了
git push -u origin main
两个github账号问题
了解了前面的知识,现在终于来到本文的主题了,这里虽然举例了两个账号问题,但3个以上也是一样的方法,另外也不一定要是github,gitee等也是相同的原理。
我们来看看git协议的github仓库链接,在本例中,其实“xiebruce”就是github的用户名,通过这个用户名,github完全可以知道这是在上传到哪个用户下的哪个项目中
git@github.com:xiebruce/learn-git.git
所以一台电脑两个github账号的问题按道理是不存在的。但实际上,由于github不允许添加相同的公钥,所以如果你用相同的公钥去另一个账号添加公钥,它会报公钥已经添加(已存在),反正就是无法添加成功(没有显示出来)。
如果公钥没有添加成功就执行push操作,就会报以下错误
ERROR: Repository not found.
fatal: Could not read from remote repository.Please make sure you have the correct access rights
and the repository exists.
再创建一个公私钥对:
由于github不允许两个账号添加相同的公钥,我们必须再创建一对新的公私钥对,才能把新的公钥添加到另一个github账号上
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_4096_02 -C "abc123@gmail.com"
注:记得把“abc123@gmail.com”换成你的邮箱,不是必须要github登录邮箱,它只是个标记而已,不会用于验证邮箱。
创建成功后,还是按前面说的方法把创建的公钥的内容添加到另一个github账号中。
然后就能git push
了吗?当然不能!因为公私钥认证,需要私钥对应公钥,默认的私钥名称就是id_rsa
,所以当你只有一个默认私钥的时候,不需要指定,ssh协议会自动读取~/.ssh/id_rsa
这个私钥来与github中添加的公钥作为一对来进行数据加密传输。
但是现在不同了,现在你有两个账号,假设之前那个账号还是会自动使用~/.ssh/id_rsa
私钥,那新的账号呢?它是不可能会自动使用你的新私钥的,因为你的新私钥不是默认名称,它还是会找默认名称的私钥,也就是原来的私钥,这样一来跟你在github另一个账号上添加的公钥根本就对不上,自然也就不可能传输数据了。
于是你可能会想,它默认会使用~/.ssh/id_rsa
私钥,我们不能让它“不默认”吗?我们指定让它使用哪个私钥不就行了吗?对!确实是可以指定使用哪个私钥的。
由于这本质上是ssh传输,所以我们指定私钥是在ssh的配置文件中指定的,ssh的默认配置文件是~/.ssh/config
添加以下配置
# 个人github
Host personal
HostName github.com
PreferredAuthentications publickey
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
# 工作github
Host work
HostName github.com
PreferredAuthentications publickey
User git
IdentityFile ~/.ssh/id_rsa_4096
IdentitiesOnly yes
如上所示,两段配置只有两个值不同,Host
和IdentityFile
,Host指是上传的地址(对于ssh user@192.168.1.2
来说,“192.168.1.2”就是Host值),只不过这个值可以用ip也可以用域名,也可以完全不是域名,总之就是一个标识,用于区分用。
我们前面的git仓库链接是这样的
git@github.com:xiebruce/learn-git.git
现在改了Host值,就要变成这样
git@personal:xiebruce/learn-git.git
当我们push数据时,“personal”会匹配上~/.ssh/config
中的Host personal
,匹配上就会读取它下边的配置,最终又用回真正的HostName,即“github.com”。
而work也一样,work的写成这样,那么匹配上Host work
后,它也会用它下边的配置,发现没,此时它的IdentityFile
指向的私钥地址就不是前面那个了,而是我们新生成的
git@work:zhangsan/learn-git.git
所以,通过这种在~/.ssh/config
文件中添加配置,手动指定使用哪个私钥来配合github上添加的公钥的方法,就可以达到“同一台电脑用两个github账号”的方法。
两个github账号用户名问题
如果你按以上的方法,确实可以使用两个账号了,但是用户名却是相同的,因为它默认会使用你github配置文件(~/.gitconfig
)中的用户名,注意这个用户名不是github登录用户名,而是git commit
要显示是谁提交的,这个“谁”就是我说的用户名。
git commit
提交用户的用户名,可以通过以下命令设置,但这样设置的是全局的
git config --global user.name 用户名
git config --global user.email 邮箱
由于全局只能有一个用户名,所以如果你希望两个github账号中的项目git commit
的用户名不一样,你可以对项目进行单独设置
git config --local user.name 用户名
git config --local user.email 邮箱
