
为什么我明明提交了代码GitHub 上却显示是一堆乱码一样的名字——这是我被问过最多次的问题之一而答案几乎都指向同一个地方Git 的用户名和邮箱没配好。你可能会想Git 不就是个版本管理工具吗装完能用不就行了还真不是。Git 和 GitHub/GitLab/Gitee 这些平台是两套体系Git 在本地记录每一次提交的作者信息时靠的就是user.name和user.email这两个配置。配置不对你的提交记录要么没法归到你的账号名下要么直接显示成一串看不懂的字符串。对于刚接触 Git 的朋友这一篇把配置用户名邮箱这件事彻底讲透对于已经用了很久 Git 但一直没搞清楚原理的朋友这篇里也有很多能帮上忙的细节。1. 为什么 Git 要单独设置提交人身份1.1 Git 的用户名和平台账号根本是两码事这是 90% 的新手第一反应我在 GitHub 上注册了账号Git 不是装好了就能直接用吗不好意思真不是。Git 是一个分布式版本控制系统它从设计之初就是完全去中心化的。你的每次提交操作都在你本地电脑上完成不依赖任何服务器。为了让提交记录里能体现出谁做了这次修改Git 会在每次提交时把你的user.name和user.email作为作者信息写进提交对象里。这个信息存在每一个 commit 的元数据中永久保留在仓库历史里。而 GitHub/GitLab/Gitee 上的账号是你在托管平台上注册的身份凭证。当你把代码 push 到远程仓库时平台会根据你提交信息里的邮箱去匹配有没有对应的平台账号然后把提交归到你的账号名下。如果你提交时用的邮箱在平台上根本没有注册那这次提交就会显示成一个灰色的、没有头像、点进去没有个人主页的神秘人。举个例子你在 GitHub 上注册的账号是aliceexample.com但本地 Git 配置的邮箱是bobtest.com那么你 push 上去之后GitHub 会认为这是一个陌生人提交的代码。哪怕代码是你写的别人看贡献记录时根本找不到你。如果你用这个配置工作三个月这三个月所有的 commit 都和你没关系。1.2 一个反直觉的坑邮箱写错也能提交成功很多人以为既然邮箱是用来关联账号的那我必须登录验证之后才能提交。这是另一个常见的误解。真实情况是Git 的本地提交根本不联网、不验证、不需要任何凭据。你可以把用户邮箱设置成任何你想设置的字符串哪怕是xxxnonexistent.com提交照样能成功。这也是为什么新手很容易在配置阶段出错却不自知——只要你能正常 commit就误以为自己配置对了直到哪天推送到远程才发现所有提交都挂在了不存在的人名下。我见过一个真实的案例某个开发者在最初学习 Git 时随手把邮箱设置成了adminqq.com并不是他自己的邮箱结果项目越做越大几十个提交全部归属于一个陌生人。后来他想改发现要重写整个提交历史非常麻烦。这类问题一旦累积起来处理成本翻倍增长最好的办法就是在一开始就认真配置。1.3 这篇内容适合谁刚开始学 Git 的新手需要系统性地搞清楚配置逻辑而不是复制粘贴命令就算完事。使用 Git 一段时间却从没注意过提交身份的开发者很多时候你觉得为什么我提交了代码没有小绿点其实就是这里出了问题。需要管理多个身份公司账号个人账号、多平台账号的开发者我会给出几种不同场景下管理身份的方案。2. 配置前的准备先搞清 Git 的三个配置作用域Git 的配置是分层级的理解这一层你才能真正明白配置的来龙去脉而不是靠死记硬背命令。2.1 system / global / local三张配置表Git 的配置项存放在三个不同的位置分别对应三个作用域作用域配置文件名影响范围适用场景--system系统级配置文件Windows 在 Git 安装目录下Linux/Mac 在/etc/gitconfig这台机器上的所有用户很少使用一般只有管理员会碰--global用户级配置文件Windows 一般在C:\Users\你的用户名\.gitconfigLinux/Mac 在~/.gitconfig当前系统用户的所有仓库最常见的配置位置适合设置个人默认身份--local仓库级配置文件在项目目录的.git/config里仅当前仓库给特定项目单独设置身份大部分情况下我们用--global就够了。只有当你需要在不同的项目里使用不同的身份时才需要用到--local。2.2 配置优先级local 打败 global 打败 system这三个配置表的优先级非常明确仓库级配置local 用户级配置global 系统级配置system。这意味着如果你在全局设置了一个叫张三的名字然后在某个特定仓库里用--local设置了李四那么只有在这个仓库里提交代码时才会显示李四其他仓库依然显示张三。这个优先级的设计逻辑很合理全局配置是默认值局部配置是特例。理解了这个规则之后很多诡异的现象就都能解释了。比如最常见的我改了全局用户名但提交时还是显示旧名字——八成是某个仓库的.git/config里有一个 local 配置把全局配置覆盖了。2.3 配置文件到底藏在哪里很多人配完之后想手动打开配置文件看一眼结果找不到文件在哪儿。我直接把常见系统的路径列出来WindowsC:\Users\你的用户名\.gitconfigmacOS / Linux~/.gitconfig即 home 目录下的.gitconfig如果打开找不到文件可能是因为文件后缀或隐藏属性。在 Windows 上.gitconfig默认可能不显示需要在文件资源管理器里打开隐藏的项目选项在 macOS 上.gitconfig这类点开头文件默认被 Finder 隐藏可以用终端命令ls -la ~/.gitconfig查看。还有一种更直接的方法在终端里执行git config --list --show-originGit 会把你当前生效的所有配置项和它们各自的来源文件路径全部列出来。这个命令在排查问题的时候尤其好用。3. 核心操作设置用户名和邮箱的正确姿势3.1 最常用的一行命令配置用户名和邮箱本质上只需要两条命令git config --global user.name 你的名字 git config --global user.email 你的邮箱example.com注意几点细节user.name的值不一定是你的真实姓名也可以是你的网名、昵称、英文名。它会原样显示在提交历史里。user.email最好填写你在远端平台GitHub/GitLab/Gitee上注册时使用的邮箱。如果你的平台账号绑定了多个邮箱那么在Emails设置页面看到的邮箱列表里的任何一个都可以。很多仓库平台支持noreply邮箱例如 GitHub 的用户名users.noreply.github.com这类邮箱专门用于隐藏真实邮箱如果你在意隐私可以直接在平台上生成一个 noreply 地址来用。3.2 设置完之后怎么验证配置完之后可以执行以下命令检查是否生效# 分别查看单个配置项 git config user.name git config user.email # 一次性查看当前仓库所有生效的配置 git config --list如果你只想确认我当前在这个仓库提交代码时会以什么身份提交可以这样git config --show-origin user.name git config --show-origin user.email--show-origin会告诉你这个配置值是从哪个配置文件里读出来的能帮你确认到底是 local 还是 global 生效非常实用。3.3 检查已有配置时最容易犯的错我会反复强调一个点在你设置之前先看一眼当前已有的配置。不是所有人都记得清自己几年前到底配过什么。我见过不止一个开发者在配置之前完全没检查直接执行了设置命令结果发现没用然后又怀疑是不是命令格式写错了折腾半天。其实原因是这个项目目录的.git/config里早就有一个 local 配置优先级比 global 更高你设置的 global 配置被压制了。所以完整的操作顺序应该是# 第一步检查现状 git config --list --show-origin # 第二步设置全局配置 git config --global user.name 你的名字 git config --global user.email 你的邮箱example.com # 第三步验证设置 git config user.name git config user.email如果第一步发现某个仓库有 local 配置且不是你想要的那个可以单独在这个仓库里重新设置 local 配置或者把 local 配置删掉来让全局配置生效。3.4 弄错了怎么改修改、删除和临时覆盖设置这个动作本身是可以反复执行的。想改再执行一次同样的命令、换成新值就行Git 会直接覆盖。想删除某个配置项# 删除全局 user.name git config --global --unset user.name # 删除当前仓库的 user.email git config --local --unset user.email还有一个很实用的小技巧临时覆盖。如果你只是临时要替别人提交一次代码不想改动任何配置文件可以这样git -c user.name临时替人 -c user.emailtempexample.com commit -m 临时提交-c参数可以在命令级别临时指定配置值只对这次命令生效不会写入任何配置文件。这个技巧在紧急帮同事处理事情时特别好用用完不需要恢复现场。4. 实战中的高频坑中文用户名、多账号和提交历史4.1 用户名为中文导致的显示乱码问题有些同学把自己的user.name设置成了中文比如张三。这在 Git 里是允许的完全能正常提交。但随之而来的问题通常出现在显示环节在用git log查看提交历史时中文名字显示正常但在某些终端或 IDE 里可能显示成转义字符\345\274\240\344\270\211这样的八进制编码。这个问题通常不是因为user.name的设置有问题而是因为 Git 默认对非 ASCII 字符进行了转义。解决办法是修改另一个配置项git config --global core.quotepath false这个配置项默认是true会转义非 ASCII 字符设为false后输出内容中的中文包括文件名和作者信息就不会被转义直接显示为可读的中文。4.2 多仓库多身份怎么给不同项目设置不同作者很多人在工作中会遇到这种情况公司在 GitLab 上有企业账号个人在 GitHub 上有私人仓库希望提交后台能正确区分。最直接、最暴力的方式是在每个需要特殊身份的仓库里执行git config local user.name 公司名 git config local user.email 公司邮箱company.com因为 local 优先级最高所以在这个仓库提交时会无视 global 配置使用 local 配置的身份。这种做法简单直接适合项目数量少的场景。如果项目很多频繁切换会很痛苦这个我在第 6 节会给出更进阶的自动化方案。4.3 已提交的历史记录怎么改作者名如果你已经提交了一堆代码但发现作者信息全是错的要怎么改这里要看具体的情况。场景一只改最近一次提交的作者信息git commit --amend --authorNew Name new-emailexample.com --no-edit--no-edit表示只改作者不改提交信息。这招只对最新的一次提交有效因为 git 协议里不能直接改历史 commit。场景二批量修改历史提交的作者信息这就比较麻烦了因为 Git 的提交对象包含父提交的哈希值改动任何一次历史提交会导致它之后所有提交的哈希值发生变化。这意味着所有协作成员本地仓库历史和远程不一致需要强制推送并让大家重新拉取。如果在公共分支上操作会严重影响其他人。如果是个人仓库、或者确认没有其他协作者可以使用git filter-branch老方法或git filter-repo推荐的新方法来批量修改。以git filter-repo为例需要先安装git filter-repo --mailmap my_mailmap.txtmailmap 文件的格式大致是New Name new-emailexample.com Old Name old-emailexample.com实际操作起来比较重所以最理性的建议还是尽早把身份配置对避免产生不可挽回的历史包袱。如果已经出现这个问题先评估影响范围再决定要不要重写历史。4.4 换了电脑 / 换了 IDE 后提交身份丢失这也是个高频痛点。你在一台新电脑上装了 Gitclone 了项目改完代码 commit 之后发现提交者变成了一个陌生名字。根本原因就是新电脑上的 Git 是全新安装的没有设置过--global配置Git 会默认使用系统用户名和主机名生成一个作者信息比如Administrator AdministratorDESKTOP-123456看起来就像丢了身份。同样地有些 IDE比如 VS Code 的 Git 集成会让你在界面上填写用户名/邮箱很多人填了之后以为配置已经写入 Git其实 IDE 只是把它保存在自己的设置里没有真正写入 Git 的配置文件。真正提交时Git 读的还是~/.gitconfig或项目.git/config里的值。所以无论是换电脑、换 IDE 还是用了新的项目管理工具第一步永远是回到终端里输入git config --list先检查当前 Git 认不认识你再开始干活。5. 本地身份配置和远程认证两件常被搞混的事5.1 身份配置不等于认证凭据这是我在带新人时反复强调的一个概念区分user.name和user.email只负责署名不负责验明正身。当你执行git push时Git 需要向远程服务器证明你有权限推送代码这是通过认证机制完成的。常见的有两种HTTPS 凭据通常是用户名密码或 access token由系统凭据管理器保存。SSH 密钥通过公钥和私钥配对完成认证。也就是说你本地配置的用户名邮箱和推送时使用的认证凭据完全是两套系统。你完全可以在本地把自己署名成任何人但在 push 时需要提供真实的访问凭据才能推送成功。反之你有权限推送代码但本地身份配置不正确提交照样会画在别人的名下。5.2 TortoiseGit 配置用户名密码和命令行配置不冲突用 Windows 且喜欢图形界面的开发者经常会用到 TortoiseGit。很多人的疑问是我在 TortoiseGit 里填了用户名和密码是不是就不用配命令行 Git 了答案是TortoiseGit 的设置里保存的凭据通常指的是远程仓库的认证凭据HTTPS 用户名和密码/token对应的是上面说的认证环节而不是署名环节。它和你用命令行的git config设置的用户名邮箱是两码事。如果你在 TortoiseGit 里设置了用户名密码TortoiseGit 在推送时就可以不再询问凭据。但提交代码时作者信息依然来自 Git 配置文件里的user.name/user.email。所以正确姿势是命令行配置身份TortoiseGit 配置凭据缓存两者配合互不替代。5.3 Git 的凭据缓存机制实操当你使用 HTTPS 方式推送代码时Git 默认会要求你每次输入用户名和密码现在很多平台用 access token 代替密码。为了省去重复输入的麻烦可以开启凭据助手# 开启凭据缓存默认缓存 15 分钟 git config --global credential.helper cache # 自定义缓存时间比如缓存 1 小时 git config --global credential.helper cache --timeout3600 # 或者直接把凭据明文保存到本地文件Windows 上是 .git-credentials git config --global credential.helper store在 Windows 上如果你安装了 Git for Windows 的默认版本它通常会自动使用manager-core这个凭据管理器把凭据存进 Windows 凭据管理器里安全性比store明文存文件要好很多。6. 进阶方案多账号多身份的管理配置6.1 includeIf 条件加载按目录自动切换身份如果你同时维护公司项目和个人项目手动在每个仓库里设置 local 配置会非常啰嗦。Git 从 2.13 版本开始支持includeIf条件配置可以根据仓库所在的目录路径自动加载不同的配置文件。思路是这样的在~/.gitconfig里写一个includeIf规则指定如果仓库路径匹配某个目录就额外加载另一个配置文件。在那个被加载的配置文件里设置对应的用户名和邮箱。假设你的公司项目都放在~/work/目录下个人项目都放在~/personal/目录下首先编辑~/.gitconfig[user] name 你的个人昵称 email personalexample.com [includeIf gitdir:~/work/] path ~/.gitconfig-work [includeIf gitdir:~/personal/] path ~/.gitconfig-personal然后分别创建两个配置文件~/.gitconfig-work内容[user] name 张三公司 email zhangsancompany.com~/.gitconfig-personal内容[user] name 阿三 email personalexample.com这样只要你的仓库克隆在~/work/目录下进入后 Git 会自动使用公司身份在~/personal/目录下的仓库则用个人身份。简直是一劳永逸。需要提醒的是gitdir:后面的路径写法是相对于你的 home 目录的~符号在这里代表 home 目录。路径匹配是前缀匹配所以目录结构要提前规划好。6.2 公司账号和个人账号并存时的建议在实际工作中至少要注意两个细节公司邮箱和个人邮箱不要混用。有些公司的 Git 服务器只认内部邮箱用个人邮箱提交会导致提交记录关联不到员工身份甚至某些严格的 CI/CD 流程会直接拒绝没有内部邮箱的提交。区分不同远端平台。如果你同时使用 GitHub、Gitee 和公司 GitLab建议在~/.gitconfig的[user]段设置你的主力账号身份然后用目录隔离的方式管理次要身份。这样即使你忘记配置最后兜底的默认身份也是正确的。6.3 一个小技巧把配置提交进 dotfiles 仓库很多老鸟会把自己的~/.gitconfig、shell 配置等统一放进一个 dotfiles 仓库用 GitHub 管理。这样换新电脑的时候一条命令就能把所有配置拉下来。如果你对这个感兴趣可以把自己的.gitconfig纳入版本管理以后迁移环境会非常舒服。配置完这些之后还有一个容易被忽略的小习惯新 clone 一个仓库后第一时间检查一下当前仓库的 user.name 和 user.email 是否符合预期再开始动手写代码。我认识的一些资深开发者甚至会在 shell 的提示符里显示当前仓库的提交身份避免在不同项目之间切换时产生身份错乱。用一句简单的话总结就是配置用户名和邮箱这件事本质上是给 Git 的每一次提交签名早点配好、配对后面能省下的麻烦远超你现在的预期。