开新仓库到现在,我几乎每次都会在创建完仓库后先花两分钟检查一遍Git配置信息。不是因为强迫症,而是太多线上事故的根源,最后都落到了这几行配置上:commit作者不对、换行符把整个文件diff搞成全红、代码push不上去、克隆下来中文文件名变成乱码……这些看起来很玄学的问题,十有八九都是仓库对应的配置信息在捣乱。
Git仓库一旦创建,它身上就会带着一套对应的配置信息,这套配置决定了这个仓库在你机器上怎么跑、提交身份是谁、换行符怎么处理、远端地址指向哪。这篇博文我就把这个话题彻底聊透:仓库配置信息存在哪、每一行是什么意思、创建新仓库后应该怎么设置、遇到问题怎么排查。
1. 先搞清楚:Git仓库的配置信息到底存在哪里
1.1 三级配置体系:system/global/local的优先级与隔离关系
很多人配置Git的时候喜欢一上来就敲 git config --global user.email,然后以为万事大吉。但Git配置并不是只有全局一份,它实际上分三个层级:
- system(系统级):配置文件在Git安装目录下的
/etc/gitconfig,影响这台机器上的所有用户。公司内网统一装机时常用,个人电脑上基本不用动它。 - global(用户级):配置文件在用户主目录下的
~/.gitconfig,影响当前系统用户的所有仓库。这是大多数人日常配置的主战场。 - local(仓库级):配置文件在仓库目录下的
.git/config,只对当前这一个仓库生效。
三者优先级是 local > global > system。也就是说,如果一个配置项在仓库级设置了,就以仓库级为准;仓库级没设置,才去看全局;全局也没有,最后看系统级。
我习惯用一个类比来理解:system是公司行政发的《办公行为规范》,global是你自己的工作效率习惯,local是针对某个项目单独签的补充协议。补充协议的约束力优先于个人习惯,个人习惯优先于公司制度。
这个优先级关系有一个致命坑点:很多人以为设置了全局就够用了,但当你clone一个别人配好的仓库,或者用IDE导入一个老项目时,仓库级配置可能早就存在并且覆盖了你的全局设置。最典型的就是user.name和user.email被仓库级配置成别人或者旧账号,导致你提交的代码算在别人头上。
1.2 仓库级配置文件长什么样?逐行解读.git/config
在任意Git仓库目录下执行 cat .git/config,你会看到类似这样的输出:
ini复制[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git@github.com:username/project.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
逐行拆开看:
repositoryformatversion = 0:Git仓库格式版本。0是当前通用版本,如果你看到非0值,说明这个仓库用了更新的内部格式,老版本Git可能打不开。正常情况不要去动它。filemode = true:是否记录文件的执行权限位变化。Linux/macOS下通常是true,Windows下因为文件系统不区分执行权限,经常会显示false。bare = false:这不是裸仓库。bare仓库通常只用于服务端存放历史,没有工作区。我们日常clone下来的仓库都是false。logallrefupdates = true:记录引用更新日志,方便reflog恢复误删的分支或commit。[remote "origin"]:远端仓库的名字和地址。fetch那一行定义了拉取时远端分支映射到本地refs的规则,正常情况不需要改,但理解它有助于看懂git fetch的行为。[branch "main"]:当前分支与哪个远端分支对应。remote = origin说明main的上游是origin的main,merge = refs/heads/main指定了合并引用路径。这就是为什么你直接git pull能知道去拉哪里的代码。
很多人会忽略一件事:.git/config 是本地生成的,它不会跟着仓库走。你clone一个远程仓库时,这个文件是Git在你本地自动生成的,里面记录的origin地址来自你clone时输入的URL。所以不同人在不同机器上clone同一个远程仓库,各自的.git/config可以完全不同。
1.3 配置信息从哪来:clone、init、GUI工具自动写入的隐藏项
创建仓库常见三种方式,每种方式会生成不同的初始配置:
- git clone:Git会根据clone的URL自动写入
remote origin,然后根据当前分支自动生成branch相关配置。这个仓库直接就绑定
