Git 按目录自动区分提交账号

如果一台电脑上同时维护公司项目和个人项目,最容易遇到的问题就是 Git 提交账号混用:公司仓库不小心使用了个人邮箱,或者个人项目被提交成了公司账号。

Git 支持通过全局配置中的 includeIf,根据仓库的 Git 目录路径自动加载不同的配置文件。配置完成后,只要仓库放在约定的目录下,就可以自动使用对应的 user.name 和 user.email,不需要为每个仓库单独执行 git config --local。

一、适用场景

下面以两个目录为例:

1
2
$HOME/company-workspace/     公司项目,使用公司账号
$HOME/personal-workspace/ 个人项目,使用个人账号

只要实际 Git 仓库位于这两个目录之下,就可以分别命中对应的账号配置:

1
2
3
4
5
$HOME/company-workspace/project-a/.git
$HOME/company-workspace/gitlab/project-b/.git
$HOME/company-workspace/team/project-c/.git

$HOME/personal-workspace/blog/.git

需要注意,company-workspace 和 personal-workspace 本身不需要是 Git 仓库,它们只是用于归类的父目录。执行验证命令时,必须进入下面的某个具体仓库。

二、配置文件结构

建议将默认配置和不同目录下的账号配置拆开:

1
2
3
4
5
6
7
8
9
10
$HOME/
├── .gitconfig
├── .gitconfig-company
├── .gitconfig-personal
├── company-workspace/
│ └── project-a/
│ └── .git/
└── personal-workspace/
└── blog/
└── .git/

其中:

  • ~/.gitconfig 保存默认账号和公共 Git 配置;
  • ~/.gitconfig-company 只保存公司账号;
  • ~/.gitconfig-personal 只保存个人账号;
  • includeIf 负责根据仓库路径加载额外配置。

三、配置全局 .gitconfig

编辑全局配置文件:

1
vim ~/.gitconfig

可以使用下面的模板:

1
2
3
4
5
6
7
8
9
10
11
12
[user]
name = your-name
email = personal@example.com

[core]
excludesfile = ~/.gitignore_global

[includeIf "gitdir:~/company-workspace/"]
path = ~/.gitconfig-company

[includeIf "gitdir:~/personal-workspace/"]
path = ~/.gitconfig-personal

各项配置的含义如下:

配置 作用
[user] 默认提交账号;没有命中目录规则时使用
gitdir:~/company-workspace/ Git 目录位于公司工作目录下时命中
gitdir:~/personal-workspace/ Git 目录位于个人工作目录下时命中
path 命中规则后加载的附加配置文件

条件末尾的 / 很重要。它表示匹配该目录及其下层目录中的 Git 仓库,因此下面这些仓库都可以命中公司规则:

1
2
3
~/company-workspace/project-a/.git
~/company-workspace/gitlab/project-b/.git
~/company-workspace/team/project-c/.git

如果你的实际目录不是这两个名称,将示例中的路径替换为自己的目录即可。配置中的路径应与仓库真实位置保持一致。

四、配置公司和个人账号

创建公司账号配置文件:

1
vim ~/.gitconfig-company

内容示例:

1
2
3
[user]
name = your-name
email = company@example.com

创建个人账号配置文件:

1
vim ~/.gitconfig-personal

内容示例:

1
2
3
[user]
name = your-name
email = personal@example.com

如果个人账号与 ~/.gitconfig 中的默认账号完全相同,.gitconfig-personal 可以省略。不过保留独立文件有两个好处:一是目录规则更直观,二是以后切换个人邮箱时只需要修改一个地方。

五、验证公司仓库

先进入一个真实存在的公司 Git 仓库,而不是只进入父目录:

1
cd ~/company-workspace/gitlab/project-b

5.1 确认仓库和 Git 目录

1
2
git rev-parse --show-toplevel
git rev-parse --absolute-git-dir

第一条命令显示工作区根目录,第二条命令显示 Git 实际使用的目录。后续排查 includeIf 是否命中时,应以第二条命令输出的路径为准。

5.2 查看最终生效的账号

1
2
git config user.name
git config user.email

预期结果类似:

1
2
your-name
company@example.com

5.3 查看配置来自哪个文件

1
2
git config --show-origin --get user.name
git config --show-origin --get user.email

也可以同时查看配置来源、作用域和加载顺序:

1
2
git config --show-origin --show-scope \
--get-regexp '^user\.(name|email)$'

可能看到:

1
2
global  file:/Users/your-name/.gitconfig          user.email personal@example.com
global file:/Users/your-name/.gitconfig-company user.email company@example.com

同一个配置项出现两次是正常的。后加载的公司配置会覆盖默认邮箱,所以最终生效的是:

1
company@example.com

六、验证个人仓库

进入个人仓库后重复验证:

1
2
3
4
5
6
7
cd ~/personal-workspace/blog

git rev-parse --show-toplevel
git rev-parse --absolute-git-dir
git config user.name
git config user.email
git config --show-origin --get user.email

预期使用个人账号:

1
2
your-name
personal@example.com

如果仓库不在任何条件目录下,则会回退到 ~/.gitconfig 中的默认账号。

七、确认 Git 实际准备使用的身份

仅查看 git config user.email 通常已经足够,但下面的命令更接近 Git 创建提交时使用的身份:

1
2
git var GIT_AUTHOR_IDENT
git var GIT_COMMITTER_IDENT

公司仓库中可能得到类似结果:

1
2
your-name <company@example.com> 1756051200 +0800
your-name <company@example.com> 1756051200 +0800

其中:

  • GIT_AUTHOR_IDENT 是作者身份;
  • GIT_COMMITTER_IDENT 是提交者身份;
  • 时间戳和时区来自当前环境。

还可以查看最近一次已经存在的提交:

1
git log -1 --format='Author: %an <%ae>%nCommitter: %cn <%ce>'

不过这条命令查看的是历史提交,不代表当前配置。修改账号配置后,已有提交不会自动改变,应该以 git var 的结果确认下一次提交将使用的身份。

八、常见问题排查

8.1 在父目录中验证,规则没有命中

下面这种验证方式不可靠:

1
2
cd ~/company-workspace
git config user.email

如果 company-workspace 本身不是 Git 仓库,Git 无法确定当前仓库对应的 .git 路径,也就无法按预期触发 includeIf。

正确做法是进入具体仓库:

1
2
cd ~/company-workspace/gitlab/project-b
git config user.email

8.2 使用 --global 得到的不是最终账号

1
git config --global user.email

这个命令只读取全局作用域,适合查看或修改默认配置,不适合作为某个仓库最终提交身份的唯一判断依据。

在具体仓库中,应直接执行:

1
2
3
git config user.email
git var GIT_AUTHOR_IDENT
git var GIT_COMMITTER_IDENT

8.3 仓库本地配置覆盖了全局规则

仓库自己的 .git/config 通常可以覆盖全局配置以及条件包含配置。检查仓库是否存在本地账号:

1
2
git config --local --get user.name
git config --local --get user.email

查看全部来源和优先级:

1
2
git config --show-origin --show-scope \
--get-regexp '^user\.(name|email)$'

如果确认本地账号不是有意设置的,可以在该仓库中删除本地覆盖:

1
2
git config --local --unset user.name
git config --local --unset user.email

执行删除前,应先确认该仓库没有故意使用独立账号。

8.4 环境变量覆盖配置文件

下面这些环境变量可能直接影响作者或提交者身份:

1
2
3
4
GIT_AUTHOR_NAME
GIT_AUTHOR_EMAIL
GIT_COMMITTER_NAME
GIT_COMMITTER_EMAIL

检查当前终端是否设置了它们:

1
env | grep -E '^GIT_(AUTHOR|COMMITTER)_(NAME|EMAIL)='

如果有输出,需要继续检查 shell 配置、IDE 启动脚本或自动化任务。最终仍建议执行:

1
2
git var GIT_AUTHOR_IDENT
git var GIT_COMMITTER_IDENT

8.5 .git 可能是目录,也可能是文件

普通仓库中的 .git 通常是目录,但 Git Worktree、部分子模块或特殊工作区中的 .git 可能是一个指向真实 Git 目录的文件。

因此,不要只通过肉眼判断 .git 的位置。使用下面的命令获取 Git 真正使用的目录:

1
git rev-parse --absolute-git-dir

如果这个路径没有落在 gitdir: 条件匹配范围内,目录账号配置就不会生效。

8.6 目录大小写或路径层级不一致

gitdir: 路径匹配依赖实际路径。目录名称、大小写和层级不一致,都可能导致规则无法命中。

默认优先使用普通的 gitdir::

1
2
[includeIf "gitdir:~/company-workspace/"]
path = ~/.gitconfig-company

如果确实需要忽略路径大小写,可以使用:

1
2
[includeIf "gitdir/i:~/company-workspace/"]
path = ~/.gitconfig-company

gitdir/i: 会放宽大小写匹配范围,使用前应确认这不会意外匹配其他目录。

8.7 IDE 或 Git GUI 显示了不同账号

IDE、SourceTree、IDEA、VS Code 等工具可能:

  • 为单个仓库写入本地 user.name 或 user.email;
  • 通过环境变量指定作者信息;
  • 缓存了旧的仓库状态;
  • 显示的是历史提交作者,而不是下一次提交身份。

排查时,优先以仓库目录中的命令行结果为准:

1
2
3
4
5
git config --show-origin --show-scope \
--get-regexp '^user\.(name|email)$'

git var GIT_AUTHOR_IDENT
git var GIT_COMMITTER_IDENT

如果命令行结果正确,但 GUI 提交仍使用错误账号,再检查 GUI 的仓库设置,并尝试重新打开仓库或重启应用。

九、常用排查命令汇总

进入需要检查的具体仓库后,可以依次执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 确认仓库根目录和真实 Git 目录
git rev-parse --show-toplevel
git rev-parse --absolute-git-dir

# 查看最终生效值
git config user.name
git config user.email

# 查看账号配置的全部来源和优先级
git config --show-origin --show-scope \
--get-regexp '^user\.(name|email)$'

# 查看仓库是否存在本地覆盖
git config --local --get user.name
git config --local --get user.email

# 查看 Git 实际准备使用的提交身份
git var GIT_AUTHOR_IDENT
git var GIT_COMMITTER_IDENT

# 检查环境变量覆盖
env | grep -E '^GIT_(AUTHOR|COMMITTER)_(NAME|EMAIL)='

# 查看最近一次已有提交的作者和提交者
git log -1 --format='Author: %an <%ae>%nCommitter: %cn <%ce>'

十、配置后的预期结果

配置完成后,账号选择关系如下:

仓库位置 预期提交账号
~/company-workspace/ 下的 Git 仓库 your-name <company@example.com>
~/personal-workspace/ 下的 Git 仓库 your-name <personal@example.com>
未命中条件目录的 Git 仓库 ~/.gitconfig 中的默认账号

最重要的验证原则是:进入具体 Git 仓库,查看最终生效配置和 git var 输出,不要只看全局配置,也不要只看历史提交。