首页 > 技术文章 > git账户切换bug(trouble shooting)

geektcp 2020-02-03 19:23 原文

分享一个git的bug追踪过程

严格的说这算是git的一个不完善的地方,或者说是个bug

 

问题

在一台电脑上,有多个git用户,要进行切换时,总是提交不了,提示没有权限:

D:\git>git push
remote: Permission to geektcp/packetsender.git denied to xxxx. 
fatal: unable to access 'https://github.com/geektcp/packetsender.git': The requested URL returned error: 403

这个问题非常烦人。有强迫症或者代码洁癖的开发人员自然有体会。

首先绝对不是密码不对;

也不是git安装版本的问题;

而且git安装目录没有缓存文件;

跟git项目下隐藏目录.git也无关。

 

如果电脑上之前用过一个账户一段时间,并且使用下面这条命令保存过密码:

git config --global credential.helper store

 

当你要换另外一个用户clone代码,并且提交时,就会一直出现这个问题。

不管是用git push 这个命令,还是用idea的提交按钮,都会必现。

 

这个时候,如果用下面的命令不保存密码:

git config --global --unset credential.helper

这时每次提交都需要输入账户和密码,可以正常提交,权限是正常的,但是每次都要输入账号密码。

 

Trouble Shooting

这个问题非常容易让开发人员误以为是账号缓存没有清理干净,于是使用下面命令进行设置:

git config --global  user.name xxxx
git config --global  user.email xxxx@xxx.com

实践表明,这是徒劳的!

 

搜索网上的一些解决方案,说是windows的凭据问题,删除凭据即可,我不确信win8即以上系统是否可以通过这个方法解决;

但我确定,win7系统肯定不行!

 

事实上,问题的关键在于:

git config --global credential.helper store

这条命令做了什么?

这条命令其实是把git账号/密码/github.com,缓存到磁盘上。

格式如下:

https://userA:passwordA@github.com

https://userB:passwordB@github.com

 

仔细看,这个缓存压根没有具体的git项目的详细路径。

实际上,git是如何命中缓存的呢?

git是根据密码来命中缓存的。

比如说:

git config --global  user.name userA
git config --global  user.email userA@xxx.com

git config这个命令只能缓存账号和邮箱,不能对密码进行指定缓存。

 

根本原因

关键在于,当你push的时候,git会根据你输入的密码,去找到缓存的磁盘文件中找到对应的账号。

比如输入密码为passwordA时,会找到userA,因为有下面的记录。

https://userA:passwordA@github.com

 

当你的多个用户,且密码是同样的时候,就会出现下面的缓存:

https://userA:passwordA@github.com

https://userB:passwordA@github.com

 

这个时候,如果你想用userB登录,但是由于userA所在这条缓存记录在前面,密码一样的情况下,先命中磁盘文件缓存的userA,

于是git用userA和passwordA进行登录,接下来就是网络认证的事情,当然是没有权限的,因为那个项目可能只有userB有权限。

 

在win7系统上,这个缓存用的是绝对路径,比如Administrator用户的路径是:

C:\Users\Administrator\.git-credentials

解决方案就是:把这个文件删除,或者编辑这个文本文件,删除里面你要清理的那条缓存并保存文件,问题就解决了。

 

by the way,都2020年了,赫赫有名的git,它缓存文件里的密码竟然是明文的!

现在这个坑货问题已经彻底解决。

 

推荐阅读