提交代码之后,屏幕突然弹出一段红色告警:*** Please tell me who you are.,配合前面那行Author identity unknown,相信不少Git用户都撞见过。我第一次遇到这个报错时以为账号被服务器踢了,又怀疑是网络断连,折腾了快半小时才反应过来——Git根本不关心我从哪个服务器拉代码,它只是因为这台机器上没有配置提交者身份,老老实实地拒绝了这次提交。
简单说,这个报错的意思是:Git不知道你叫什么名字、邮箱是什么,所以无法在提交记录里标注作者。很多从SVN切换过来的同学尤其容易触发,因为SVN是中央服务器统一鉴权,而Git是分布式系统,每次commit都要在本地写清楚“这是谁提交的”。本地没有身份信息,Git宁可报错,也不会替你瞎编一个名字塞进历史里。
这篇文章把这个问题彻底讲透:报错背后的配置层级、标准修复流程、那些“配了还报错”的隐藏原因、以及已经提交的错误作者信息如何补救。不管你是刚安装Git的新手,还是在公司电脑上突然被这个报错拦住的老人,都能在这里找到对应场景的解法。
1. Author identity unknown不是网络问题,是本地身份配置缺失
1.1 完整报错长什么样
我先还原一下实际报错的全貌。比如你刚完成修改,执行:
git commit -m "fix: 修复登录模块的SQL注入问题"正常情况下Git会直接提交,但在这台没有配置过身份的机器上,你看到的是:
*** Please tell me who you are. Run git config --global user.email "you@example.com" git config --global user.name "Your Name" to set your account's default identity. Omit --global to set the identity only in this repository. fatal: unable to auto-detect email address (got 'username@hostname (none)')注意最后一行:fatal: unable to auto-detect email address。Git在找不到配置时,会尝试用系统用户名和主机名去猜一个邮箱,比如username@hostname (none),猜不出来就直接卡住。很多人把注意力放在*** Please tell me who you are.上,其实真正给线索的是最后一行。
1.2 触发报错的几种常见起点
我梳理了一下,这个报错最常见的触发场景就这么几类:
- 刚装好Git,从来没配置过user.name和user.email。
- 新clone了一个仓库,仓库里的
.git/config没有继承全局身份。 - 重装系统、换了新电脑,旧的
~/.gitconfig没迁移过来。 - 使用
sudo git commit,读取的是root用户的配置,而root没有配置身份。 - 环境变量
GIT_AUTHOR_EMAIL、GIT_COMMITTER_EMAIL被设置成了无效值,导致原本好使的配置被覆盖。
还有一类经常发生在公司电脑和个人电脑混用的场景:你手头有多台机器,有的机器配过,有的机器没配过,恰好在没配过的机器上提交,就撞上了。
1.3 Git提交记录里的“作者”到底从哪来
很多人以为Git提交的作者是登录GitHub、Gitee的账号自动带上去的,这是典型误区。Git的commit对象里有author和committer两个字段,提交时会取配置文件里的user.name和user.email填入。如果没有配置,commit命令直接报错退出。
也就是说,这个报错不涉及任何远端服务器,即便你离线提交也一样会触发。我当时排查时先ping服务器、检查SSH key,都是白费功夫。理解这一点,能帮你省下大量排查时间。
2. 动手修之前,先搞清身份配置的三个层级
2.1 system、global、local分别存在哪
Git配置分三个层级,分别对应不同的作用范围。我用一张表整理出来:
| 层级 | 配置文件位置(Windows示例) | 配置文件位置(macOS/Linux示例) | 作用范围 |
|---|---|---|---|
| system | C:\Program Files\Git\etc\gitconfig | /etc/gitconfig | 整台机器所有用户所有仓库 |
| global | %USERPROFILE%\.gitconfig | ~/.gitconfig | 当前用户的所有仓库 |
| local | .git/config(仓库内部) | .git/config(仓库内部) | 仅当前仓库 |
平时我们用的git config --global写入的是global层,不加--global的git config写入的是local层。执行命令时,Git会从这三个地方合并读取配置,最终生效的值由优先级决定。
2.2 用git config --list --show-origin定位当前生效值
修复前先确认现状,别上来就瞎配。最有效的命令是加--show-origin参数:
git config --list --show-origin它会列出所有配置项,并标注每个值来自哪个文件。实际输出类似:
file:"C:/Program Files/Git/etc/gitconfig" core.symlinks=false file:"C:/Program Files/Git/etc/gitconfig" core.autocrlf=true file:"C:/Users/yourname/.gitconfig" user.name=yourname file:"C:/Users/yourname/.gitconfig" user.email=yourname@example.com file:.git/config core.repositoryformatversion=0如果列表里没有user.name和user.email,那就是最普通的没配置问题。如果列表里能查到这两个字段,但提交仍然报错,说明问题没这么简单,直接跳到后面第4章排查。
2.3 优先级规则与“空值覆盖”陷阱
三个层级的优先级是:local > global > system。意思是同一个配置项,仓库里的.git/config说了算,其次是用户级配置,最后才是机器级配置。
这里有个非常隐蔽的坑:local配置里如果存在user.name或user.email,但值是空的(比如clone某些模板仓库或者用IDE自动填充时留下的空字段),它会覆盖掉global里配好的有效值。Git不会因为你global层配了身份就忽略local层的空值。我遇到过一次,全局配置明明白白写着邮箱,仓库里提交就是报错,查了半天才发现是.git/config里的user.email是一个空字符串。
3. 标准修复流程:设置user.name和user.email
3.1 一次性修复到当前用户
最推荐的做法是配到global层,这样当前用户的所有仓库都生效:
git config --global user.name "Zhang San" git config --global user.email "zhangsan@example.com"注意两点:
- Windows的Git Bash里引号不能省,否则带有逗号或特殊字符的值会被截断。
- 邮箱不要写成昵称。很多平台(GitHub、Gitee、GitLab)靠邮箱把提交关联到账号,邮箱写错了,提交记录上不会显示你的头像,也无法关联到你的账号。
3.2 只改当前仓库的local配置
如果你希望某个仓库用独立身份,比如公司仓库用公司邮箱,个人仓库用个人邮箱,就不加--global:
git config user.name "Zhang San" git config user.email "zhangsan@example.com"这样写入的是当前仓库的.git/config,只对这个仓库生效。道理和加不加--global完全对应:加全局参数写用户级配置,不加写仓库级配置。
3.3 设置完怎么验证、怎么自查
配置完成后,先确认一下:
git config user.name git config user.email这两条命令会输出最终生效的值。如果输出正常,说明配置已经就位,再执行commit就不会报错了。如果输出空,说明设置没写进去,或者写到了另一个层级的文件里。
还有一个排查命令值得记:
git config --get user.email--get和直接git config user.email的区别在于,前者在读取到多个值时能更精准地显示命中项,在某些场景下更容易暴露重复配置。我在排错时一般先用--show-origin看来源,再用--get确认最终值。
4. 配置了还是报错?这五个隐藏原因最容易被忽略
4.1 仓库本地配置存在空值
前面已经提过,.git/config里的空值是最大的坑。排查方法很简单:
git config --local --list或者直接打开.git/config:
cat .git/config如果看到类似email =这样的空字段,把它删掉或修正即可:
git config --local --unset user.email然后重新设置正确的值。
4.2 环境变量GIT_AUTHOR_*在悄悄覆盖
Git允许通过环境变量临时指定提交作者,官方定义的变量包括GIT_AUTHOR_NAME、GIT_AUTHOR_EMAIL、GIT_COMMITTER_NAME、GIT_COMMITTER_EMAIL。它们的优先级高于配置文件,一旦被设置成错误值,配置文件再对也没用。
检查方法:
env | grep GIT_Windows PowerShell下用:
dir env:GIT_*如果发现有异常变量,直接清掉:
unset GIT_AUTHOR_EMAIL unset GIT_COMMITTER_EMAIL这种坑特别容易出现在使用了某些自动化脚本、CI工具或者终端代理的环境里。我见过有人配置了全局身份后依然报错,最后发现是安装某个Docker相关工具时往.bashrc里写了一个评估用的GIT_AUTHOR_EMAIL变量,一直覆盖到现在。
4.3 用sudo执行commit读错配置
如果你在Linux或macOS上习惯加sudo执行命令,那Git读取的是/root/.gitconfig,和你自己用户下的配置不是一回事。
可以先确认当前用户:
whoami如果显示root而配置里没有身份信息,要么用root身份配置一次:
sudo git config --global user.name "Zhang San" sudo git config --global user.email "zhangsan@example.com"要么尽量不要用sudo执行Git命令,避免权限和配置混乱。
4.4 引号、换行、编辑器编码把配置内容弄脏了
有的人用git config --global --edit打开编辑器直接改配置。如果在编辑过程中不小心把邮箱后面加了个空格、换行,或者Windows记事本把UTF-8文件存成了带BOM的格式,Git读取配置时可能解析出意外结果。
遇到这种情况,最快的方式是打开配置文件人工检查:
- Windows用户:
notepad %USERPROFILE%\.gitconfig - macOS/Linux用户:
cat ~/.gitconfig
重点检查[user]段落的格式,标准写法是:
[user] name = Zhang San email = zhangsan@example.com如果你的配置里出现email = zhangsan@example.com(末尾多了空格)或者值被折成多行,都会导致解析异常。
4.5 把SSH key和提交者身份混为一谈
还有一个认知层面的高发误区。很多人配了SSH key,机器也能免密拉代码,就以为提交身份也没问题。实际上SSH key负责的是传输通道的认证,解决的是“这台机器能不能访问远端仓库”的问题;而user.name和user.email解决的是“提交记录上写谁的名字”的问题。两者完全独立。
所以你会看到这样的现象:SSH clone正常、pull正常、push正常,但commit就是报Author identity unknown。原因就是机器和服务器之间的通道没问题,但Git还是不知道本地提交者是谁。
5. 已经产生错误提交怎么办
有时候报错并不发生在第一次提交,而是你之前已经用错误身份提交了一部分。等配置好身份后发现历史里一堆“匿名者”提交记录,或者作者信息全是错的,这时候就要分情况处理。
5.1 push之前用amend修复
如果错误提交还没有push到远端,修起来非常轻松:
git commit --amend --reset-author --no-edit解释一下三个参数:
--amend:修改最近一次提交。--reset-author:把作者信息重置为当前配置的身份。--no-edit:不修改提交信息。
执行完后,提交作者就会变成你配置好的身份。注意,这个命令只对最近一次提交生效,如果前面还有多笔错误提交,需要用后面说的方法。
5.2 已push的分支如何修正
已经push到远端的分支,修改提交历史会涉及重写,必须谨慎。如果分支只有你一个人在用,可以amend之后强制推送:
git push --force-with-lease这里推荐--force-with-lease而不是--force,因为它会先检查远端是否有别人新提交的代码,避免覆盖掉别人的工作。算是我踩过坑后养成的习惯:凡是强制推送,一律用--force-with-lease。
如果错误提交不止一条,可以用rebase配合amend批量处理:
git rebase -i HEAD~5在打开的交互界面里,把需要修改作者的提交标记为edit,然后在每个暂停点执行:
git commit --amend --reset-author --no-edit git rebase --continue一套流程走完,所有涉及的提交作者都会被修正。
5.3 批量重写历史提交的工具
如果整条分支的作者信息全部错误,且确认可以安全重写,用git filter-branch可以一次性搞定。示例:
git filter-branch --env-filter ' if [ "$GIT_AUTHOR_EMAIL" = "wrong@example.com" ]; then export GIT_AUTHOR_NAME="Correct Name" export GIT_AUTHOR_EMAIL="correct@example.com" fi ' -- --all这段脚本会遍历所有commit,凡是作者邮箱等于wrong@example.com的提交,都改成新的名称和邮箱。注意,重写历史会改变commit的哈希值,多人协作的分支不要随便用,否则所有人的本地副本都会和远端“分手”。
6. 长期使用:一套配置方案解决多身份混用
配置完身份只是解决了眼前的问题。如果你的工作环境同时有公司GitLab、GitHub、Gitee,或者公司邮箱和个人邮箱需要严格分开,一套动态身份切换方案能让后面省心很多。
6.1 includeIf按目录分流
Git 2.13开始支持includeIf配置。思路是:把不同身份写进不同的配置文件,然后按仓库所在目录自动加载。
举个例子,你约定公司项目统一放在~/work,个人项目放在~/personal。先在~/.gitconfig主文件里写入:
[includeIf "gitdir:~/work/"] path = ~/.gitconfig-work [includeIf "gitdir:~/personal/"] path = ~/.gitconfig-personal然后分别建两个文件。
~/.gitconfig-work:
[user] name = Zhang San email = zhangsan@company.com~/.gitconfig-personal:
[user] name = Zhang San email = zhangsan@gmail.com这样放在~/work目录下的仓库自动用公司邮箱提交,放在~/personal下的仓库自动用个人邮箱提交,不用再手动切来切去。
6.2 Windows和macOS的路径写法差异
gitdir:后面的路径写法和平台关系很大。macOS/Linux直接写~/work/没问题,Windows要注意用正斜杠:
[includeIf "gitdir:C:/work/"] path = ~/.gitconfig-work我见过一个朋友照抄网上的写法,gitdir:里写的是C:\work\,反斜杠被当成转义字符解析,includeIf一直没生效。改成正斜杠后立刻好了。
还有一个细节:gitdir:~/work/末尾的斜杠表示匹配这个目录以及它下面的所有子目录。如果你只关心这一个仓库目录本身,可以去掉末尾斜杠,写gitdir:~/work。按实际需要来就行。
6.3 我的个人配置习惯
分享一套我目前在生产环境使用的方案,供参考:
- 新机器装好Git后第一件事,先配一套兜底global身份,保证任何时候提交都不会被拦。
- 公司项目统一放在
D:/work,个人项目放在D:/personal,通过includeIf区分。 - 所有远端平台的账号邮箱,一定和本地
user.email保持一致,这样提交记录才能正确关联到账号。 - 尽量少用
git config --system,改动系统级配置会影响机器上所有用户,容易给同事挖坑。
这套方案我用了快三年,除了换新电脑时忘了迁移.gitconfig文件浪费了一点时间,其他时候基本没再碰过Author identity unknown这个报错。
最后再分享一个小技巧:每次配置完身份,想确认万无一失,可以直接敲git config --global --list看看user段的内容。如果实在不放心,就在某个测试仓库里git commit --allow-empty -m "test"提交一次,一秒就能验证整个链路是否正常。这个报错本身不复杂,绝大多数情况下就是配置缺失或配置层级混乱,顺着配置来源一层层查,总能找到问题。