问题的发生和解决【简短过程和最终解决方法】
按理说这个不算什么严格的难题,但由于最终的解决比较“怪”,在解决的过程中,我就称之为抽风,不知道抽什么风出现这个报错。
基本过程是这样的:
一个使用了很久gitee个人笔记库,今天打算进行一下提交(本身提交频率不高,做一个备份用),可突然发生下面的提示,如下,使用 git push
时的报错内容:
也就是最常见的,git@gitee.com: Permission denied (publickey). 问题。
说它常见,是因为这个问题一般都是由于 ssh 公私钥的验证出现问题,最简单的方式是:重新生成ssh密钥,将公钥添加到 gitee 或 github 配置中的ssh公钥中,用于正确的验证权限,实现git仓库的拉取推送。
但此处却无法依照此方法解决,中途过程中,也使用了:在 ssh 目录下添加 config 文件,指定单独的密钥 的解决办法。但是仍然不行。【真抽风】
此外,包括设置后,每次都是重新打开 git bash ,以及后面的重启电脑,都不能解决。
最后的最后,解决办法是:
删除当前本地仓库对应的远程仓库地址,重新添加一次远程仓库的地址!
注意,通过 git remote
查看远程仓库是有地址的,只需删除后重新添加才能解决!重新添加后无需任何操作,直接 git push
即可。
问题信息全文(查找好多资料关于这个信息的提示都是截图,没有文字的内容,因此此处特地贴出来):
$ git push git@gitee.com: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
下面对该问题的解决,已及另外两个正确的解决办法,做一个详细记录和总结。
本次问题的解决【方法一:删除本地的远程仓库地址,并重新添加】
由于所有的方法都尝试了,后面都怀疑 gitee 的 ssh公钥 管理有问题,添加没有起作用。而且非常确定远程仓库是存在的【不仅之前一直在用,而且网站进入 gitee 也能看到远程库】
无奈之下,只能新建一个空的库,在本地重新添加并推送。
新建一个远程库推送测试
如下,新建一个 mytest 的测试空库。
注:上面不需要勾选 “初始化仓库”,此处虽然勾选,但是由于没有选择语、.gitignore等信息,最终仍然是一个 空的仓库。
创建后进入仓库,会有初始化本地和远程仓库连接的提示。
在本地 git init
初始化一个本地库,创建readme文件 touch README.md
,并添加和提交修改。
然后,git remote add origin https://gitee.com/findmoon/mytest.git
添加本地库的远程仓库,执行推送 git push -u origin master
。
推送成功!
git push 中的-u
选项全称为--set-upstream
,即设置上游的远程仓库地址。此后可以省略为git push
。我们在使用 git push 时,经常会遇到
git push --set-upstream origin master
的提示,通常按照提示,设置当前本地仓库的分支与远程仓库分支的关联即可,后续就可以直接使用git push
简写方式推送。关于
--set-upstream
的说明,可以参考这篇 git push时提示--set-upstream。
尝试删除原有远程仓库地址的关联,并重新添加
由于上面重新创建和添加的远程仓库,推送管理没有问题,于是尝试,重新关联一下报错仓库对应的远程仓库,看看能不能解决。
git remote
查看远程仓库
$ git remote
origin
另:使用 git remote --get-url <remote_repo_name>
可以查看该远程库对应的url地址。
$ git remote get-url origin
https://gitee.com/findmoon/xxx.git
git remote remove <name>
移除远程仓库的关联
$ git remote remove origin
移除成功,不会有任何提示。
git remote add <name> <repo_url>
再次添加对远程仓库的关联
$ git remote add origin https://gitee.com/findmoon/xxx.git
执行完添加成功。
- 执行推送。设置 upstream:
git push --set-upstream
或git push -u
,可以看到设置并推送成功
$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin master
$ git push --set-upstream origin master
info: detecting host provider for 'https://gitee.com/'...
info: detecting host provider for 'https://gitee.com/'...
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 216 bytes | 108.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.2]
To https://gitee.com/findmoon/xxx.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
后续发生变更,执行 git push
均没有问题。
远程仓库不存在时的报错提示是什么?(not found)
原本的报错提示中,有关于仓库是否存在的信息 the repository exists
。于是,可以看一下远程仓库不存在会报错什么。
如下,在 gitee 删除一个与本地关联的远程仓库test,本地再次执行 git push
:
$ git push
info: detecting host provider for 'https://gitee.com/'...
remote: [session-91484d9d] 404 not found!
fatal: repository 'https://gitee.com/findmoon/test.git/' not found
配置 ssh 目录下的 config 文件【方法二】
这里介绍一个关于 Permission denied (publickey) 问题,比较标准的解决办法。即:在 ssh 目录下创建并配置 config 文件。
在 码云(Gitee.com)帮助文档 中 Windows下由于SSH配置文件的不匹配,导致的Permission denied (publickey)及其解决方法 里面有介绍到。
这个帮助文档似乎也挺难找的。
可以看到,可能出现这个问题的原因在于,Windows平台不原生支持ssh,只能使用 git bash openssh、putty 等工具实现ssh连接。如果同时连接了不同的平台,比如码云和 github 等。如果不同的连接或不同的工具,各自生成自己的密钥,导致已有的密钥文件被覆盖或移动,就会导致连接时出现 Permission denied (publickey) 的问题。
说白了就是,密钥文件的不存在或者存储位置不一致(导致无法找到对应的ssh密钥),无法验证ssh连接。
所以,要确保ssh密钥文件不会变动! 或者,确保使用相同的密钥。
如果使用多个密钥时,可以在 默认的ssh目录下 创建 config 文件,并在启动配置正确的ssh私钥所在位置,使ssh连接正确匹配和验证。
默认的ssh目录 为:C:\Users\<user_name>\.ssh
。如果配置 config,可以该目录下创建,并新建一个 .ssh
目录,里面存放 gitee 上使用的ssh密钥文件。
则 config 文件配置可以为如下:
Host git.oschina.net
HostName git.oschina.net
User git # gitee网站的用户名
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
经测试,host也可以使用 gitee.com
,IdentityFile
文件路径推荐使用绝对路径,并且指定的私钥文件或路径,并不一定是.ssh/id_rsa,比如,将 gitee 使用的私钥,放在 .ssh
的 gitee\
目录下:
Host gitee.com
HostName gitee.com
User username # gitee网站的用户名
IdentityFile C:\Users\win7hostsver\.ssh\gitee\id_rsa
PreferredAuthentications publickey
指定的私钥路径不正确,使用 git 时,会提示路径不存在等相关信息。
如上,PreferredAuthentications
参数,用于指定连接时首选的认证方式,默认即为公钥,可选的值有:publickey,password publickey,keyboard-interactive
。详细可参考 Windows下Git多账号配置,同一电脑多个ssh-key的管理 中的介绍。
(重新)生成 SSH 密钥对,并配置 gitee/github 中的公钥【方法三】
Permission denied (publickey) 问题的发生,一般都是没有配置 gitee/github 中的公钥,或者找不到本地私钥文件。也就是,这个问题,正统的做法是:生成 SSH 密钥,并将公钥添加到 gitee/github 中,就解决了(重新打开git命令行工具,执行git连接或拉取推送)。
生成ssh密钥
打开 gitbash 终端,使用 ssh-keygen
命令,重新生成 ssh 密钥。
如下,在 gitbash 中输入如下命令:
ssh-keygen -t rsa -C "my_gitee_ssh_key"
-t:即 type
,表示 ssh 密钥的类型,通常选择 rsa 加密。
-C:即 comment
,当前生成的 ssh 密钥相关的评论信息,可以把它当成一个标识当前 key 的名称或说明。
输入该命令后,一路回车即可,唯一需要注意的是,选择 ssh 密钥保存位置,可以根据需要指定(指定的目录一定要存在,否则无法生成)。
如下图所示
上图修改了默认的密钥保存路径为 .ssh 下的 gitee 目录中。为了保证 gitbash 连接登陆 gitee 时,能够找到密钥,需要在默认的 .ssh 目录下,配置 config 文件(如前文所述。如果是保存默认的密钥路径,则不需要此步骤)
Host gitee.com
HostName gitee.com
User findmoon
IdentityFile C:\Users\win7hostsver\.ssh\gitee\id_rsa
PreferredAuthentications publickey
可以查看 gitee 目录下的公钥,打开 id_rsa.pub 公钥文件,并复制公钥。
添加ssh公钥到gitee
gitee 的ssh公钥添加地址为 https://gitee.com/profile/sshkeys
也可以登陆 gitee,在右上角“设置”中,找到 “SSH公钥” ,既可以打开了。下所示:
将复制的公钥添加进入即可
推荐 解决码云出现git@gitee.com: Permission denied (publickey).
关于 ssh-add 指定密钥位置
ssh-add 命令可以用来指定 ssh 密钥的位置,比如 linux 系统下,最常用的指定位置的命令为 ssh-add ~/.ssh/id_rsa
。
查看当前的密钥位置:
$ ssh-add
Identity added: /c/Users/win7hostsver/.ssh/id_rsa (123456789@qq.com)
指定其他密钥位置(windows 下 git bash 中):
ssh-add /c/Users/win7hostsver/.ssh/gitee/id_rsa
Git: How to solve Permission denied (publickey) error when using Git? 其中的答案对该问题有很好的解答,推荐看看。
第一次连接时的 Are you sure you want to continue connecting (yes/no/[fingerprint])?
问题
如果是使用 ssh-keygen 重新或第一次生成密钥和添加公钥的gitee,使用 git 首次连接 gitee 时,可能会提示: Are you sure you want to continue connecting (yes/no/[fingerprint])?
此时,输入 yes 即可(不输入 yes,无法正确连接和正常使用)。它会生成 known_hosts 文件,用于对某个主机连接过程中的公钥进行简单的安全验证。具体可见 What is the known_hosts File for ssh in Linux?
最后,为啥没用github?
因为,因为网速...,用 github 有时网速急的让人难受。不要问,问就是所有搜到的加速github访问的方法都用了,没有一个(长久)有效的(除了vpn...【也会不稳定】)
解决问题的过程中,把所有ssh密钥都删除重新生成了,还要添加公钥到 github 中...
附:【请教】关于 ssh -T git@gitee.com
报错
在解决问题后,不知道为什么执行 ssh -T
仍然报错 Permission denied (publickey)
如下:
$ ssh -T git@gitee.com
git@gitee.com: Permission denied (publickey).
不过,git push 等操作还是正常的。原因不知,求教大神!
注:问题解决后的推送过程似乎有些不同,如下:
$ git push info: detecting host provider for 'https://gitee.com/'... info: detecting host provider for 'https://gitee.com/'... Enumerating objects: 212, done. Counting objects: 100% (212/212), done. Delta compression using up to 8 threads Compressing objects: 100% (129/129), done. Writing objects: 100% (129/129), 7.48 MiB | 3.21 MiB/s, done. Total 129 (delta 13), reused 0 (delta 0), pack-reused 0 remote: Resolving deltas: 100% (13/13), completed with 10 local objects. remote: Powered by GITEE.COM [GNK-6.2] To https://gitee.com/findmoon/privatenote 9ab0b93..738a9e6 master -> master $ git status On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean