Git使用ssh协议配置Github远程仓库避免踩坑指南(Windows环境)
在windows下的git中,配置github远程仓库,如选择不需要每次输入密码的ssh协议,有诸多挑战,网上教程往往只给具体步骤(https://blog.csdn.net/buknow/article/details/80325986),而对背后原理避而不谈,导致大量路坑。我这里简单谈一谈。
首先配置git的命令行环境,首选肯定是安装git时附带的Git Bash。但是PowerShell / CMD 其实也可以,但有些地方稍有区别。
配置大体步骤如下
第一步:生成公钥私钥对。
坑1:一定要按照官方教程(1),使用OpenSSH套件(suit) 附带的ssh-keygen命令,而不要去用别的工具,比如putty。因为Github目前只支持Open SSH格式的public key,而Putty目前的版本不能生成OpenSSH格式的公钥。倒是可以生成Open SSH格式的私钥。所以只能使用ssh-keygen命令。这个命令本来只在Linux环境下有,但不知道是安装Git的时候给我附带安装了,还是Windows 10自带了这个命令(2),反正在cmd和git bash环境下都能跑起来。如果操作系统是win10但没有这个命令的朋友,可能需要按照这篇教程安装一下:https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse。
坑2:用ssh-keygen在cmd环境下生成密钥对时,会让你输入最后保存的文件名,但这个保存目录却长得很奇怪:C:\Users\hejin/.ssh/id_rsa,如下图,让人以为会保存到文件夹C:\Users\hejin\.ssh\id_rsa\下,但其实就是保存在命令行的当前目录下。按照我下图中的例子,最后公钥和私钥其实就是保存在了C:\Users\hejin\.ssh\下。
坑3:上图中其实最好是什么文件名都不要输入,直接按enter。因为括号中的C:\Users\hejin\.ssh\id_rsa其实就是默认保存路径,id_rsa其实是文件名。如果在这里输入了文件名,就不会以默认路径默认文件名保存,这样之后就一定要用ssh-add命令手动添加私钥才能连上github,否则就会报错:
git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
第二步:使用Open SSH生成公钥和私钥之后,公钥根据以下教程上传至Github:https://blog.csdn.net/buknow/article/details/80325986。
坑:这点出现上传公钥的地方有些难找外——因为是在personal settings而不是repository settings中,其他没啥大问题。
第三步:而私钥则需要用ssh-add命令配置到ssh agent内,由ssh agent来负责管理所有私钥,git在连接远程仓库时,只需要调用ssh agent来进行验证,并不需要自己管理private key(8)。注:如果在第一步中,公钥私钥已经以默认文件名和默认路已经保存,则不需要用ssh-add命令添加私钥。
Winwdows下putty也有ssh agent的功能,但我不知道怎么让git去用putty的agent。网上教程一般也是用ssh agent关联的ssh-add命令。ssh agent也是open ssh套件中的,本来也是linux下的,现在windows 10也附带了。
这里最坑:
坑1:ssh agent虽然我安装了,但是他的services并不是默认开启的,这点官方教程中也没有提及。如果ssh-agent服务没有enable,运行ssh-add命令后就会提示错误:Error connecting to agent: No such file or directory。参考:https://unix.stackexchange.com/questions/464574/ssh-add-returns-with-error-connecting-to-agent-no-such-file-or-directory/464580。
如何启动ssh-agent服务:到Windows服务管理器里面,找到找到OpenSSH Authentication Agent,把启动类型从“禁用”改为“手动”。如下图
坑2:把ssh-agent服务的启动方式设置为“手动”后,还需要在git bash中运行eval $(ssh-agent -s)或者ssh-agent bash来启动服务。这两个命令什么原理我没搞懂。我感觉自己在服务管理器里面直接手动启动也是可以的,或者直接把启动类型改为“自动”好了。
后面查了,原来是不可以的。。。Git Bash下一定要跑eval $(ssh-agent)。至于为什么一定要加eval,不能直接跑ssh-agent,是因为ssh-agent其实返回的是几个环境变量的设置,但是linux下每个程序只能修改自身环境的环境变量,不能修改系统环境的环境变量,所以需要eval命令来执行ssh-agent命令返回的结果。具体请参考:http://www.snailbook.com/faq/about-agent.auto.html
如果是CMD或者是PowerShell,直接运行ssh-agent就可以。但是一定要把private key放到%userprofile%\.ssh下,并重命名为id_rsa,没有扩展名。否则git pull / push的时候就会提示:
git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
坑3:ssh-add命令如果在git bash下运行,后面的git push / pull等命令也一定要在git bash下运行,不能在cmd或者powershell中运行,否则无效。好像cmd/powershell环境下的ssh-agent和git bash下的ssh-agent是分开的,所以哪边push / pull就要在哪边ssh-add
第四步:也是最后一步,跟着Github上的教程,初始化Git本地git仓库,添加远程库:
git init git commit -m "first commit" git branch -M main git remote add origin git@github.com:kind03/demo2.git git push -u origin main
坑1:但是github没解释git branch -M main这条命令是怎么回事,为什么要把当前brach的名字改为main?还有,按照命令的说明文件,-M是用来更改branch名称的,后边必须跟两个参数:old branch name和new branch name,这里只有一个参数。。。貌似是old branch name可以省略,但是官方文档上始终没有提及这种用法:https://git-scm.com/docs/git-branch
坑2:使用git init初始化本地git仓库后,需要用git config命令添加当前用户邮箱地址,否则会无法commit。这点官方教程也没提及。
git config --local user.name "username"
git config --local user.email "email"
参考:https://blog.csdn.net/weixin_45153794/article/details/105727473
坑3:git remote add origin中的origin,其实就是远程仓库的一个本地变量名而已,可以随便改,一般用origin。官方文档上写的确实不是很清楚:
Add a remote named <name> for the repository at <url>.
就这么一句话,没了。如果一时间没想到我上面说的这种用法,估计怎么想也想不通这句话的含义
参考文档
2. https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_keymanagement
3. https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse
4. https://blog.csdn.net/buknow/article/details/80325986
7. https://git-scm.com/docs/git-branch