一台电脑,两个 Git 身份:公司 GitLab + 个人 GitHub 共存

概述

用公司电脑写个人项目,git log 里却全是公司邮箱?推送到 GitHub 却提示权限拒绝?这是每个同时使用公司 GitLab 和个人 GitHub 的开发者都会遇到的问题。

本文基于一次真实的配置过程,采用 SSH 多密钥 + Git 条件包含 方案,实现不同目录自动切换 Git 身份。从密钥生成到推送成功,包含完整步骤、原理图解,以及公司网络下端口被封、Host Key 验证失败等实际踩坑的解决方案。

你也可以将当前网页保存,然后用Claudecode参考这个网页内容直接完成。

适用场景:公司 GitLab + 个人 GitHub 并存(也适用于任意两个 Git 平台的多账号管理)

阅读时间 :约 10 分钟 | 配置时间:约 15 分钟

需求场景

graph LR A["你的电脑"] --> B["公司项目
(任意目录)"] A --> C["个人项目
(指定目录)"] B -->|公司密钥 + 公司邮箱| D["公司 GitLab"] C -->|个人密钥 + 个人邮箱| E["个人 GitHub"] style B fill:#4A90D9,color:#fff style C fill:#7B68EE,color:#fff style D fill:#FC6D26,color:#fff style E fill:#238636,color:#fff

配置前的准备

在开始之前,请先确认你有以下信息:

信息 示例 你的值
公司 GitLab 地址 git.company.com ______
公司邮箱 zhangsan@company.com ______
公司 Git 用户名 zhangsan ______
个人 GitHub 邮箱 zhangsan@qq.com ______
个人 GitHub 用户名 zhangsan ______
个人项目目录 D:/obsidian/ ______

下面的步骤以 Windows 为例。macOS/Linux 路径稍有不同,会在对应步骤标注。


Step 1: 生成个人 SSH 密钥

打开 Git Bash,执行:

bash 复制代码
ssh-keygen -t ed25519 -C "你的个人邮箱" -f ~/.ssh/id_ed25519_personal

会提示输入密码(passphrase),直接按两次回车跳过即可。

执行成功后会在 ~/.ssh/ 目录下生成两个文件:

  • id_ed25519_personal --- 私钥(不要给任何人)
  • id_ed25519_personal.pub --- 公钥(后面要添加到 GitHub)

注意:如果你还没有公司的 SSH 密钥,也用类似命令生成一份:

bash 复制代码
ssh-keygen -t ed25519 -C "你的公司邮箱" -f ~/.ssh/id_ed25519

Step 2: 配置 SSH config

创建或编辑 SSH 配置文件:

  • WindowsC:\Users\你的用户名\.ssh\config
  • macOS/Linux~/.ssh/config

写入以下内容(根据你的实际信息修改):

bash 复制代码
# ====================================
# 公司 GitLab(使用公司密钥)
# ====================================
Host git.company.com
    HostName git.company.com
    User git
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

# ====================================
# 个人 GitHub(使用个人密钥)
# ====================================
Host github-personal
    HostName ssh.github.com
    Port 443
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
    IdentitiesOnly yes

逐行解释:

配置项 含义
Host 给这个连接起个别名,后面 git 操作会用到
HostName 实际连接的服务器地址
Port 443 使用 443 端口(很多公司网络封了默认的 22 端口,443 端口更通用)
User git SSH 用户名,Git 服务固定为 git
IdentityFile 指定使用哪个私钥文件
IdentitiesOnly yes 只使用指定的密钥,不尝试其他密钥

为什么 GitHub 用 ssh.github.com 和 443 端口? 很多公司防火墙会封锁 22 端口,导致 ssh -T git@github.com 超时。 GitHub 官方提供了 443 端口的替代方案,用 ssh.github.com 即可绕过限制。 如果你不在公司网络环境下,也可以用标准配置:

bash 复制代码
Host github-personal
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
    IdentitiesOnly yes

Step 3: 把个人公钥添加到 GitHub

3.1 复制公钥内容

bash 复制代码
cat ~/.ssh/id_ed25519_personal.pub

会输出类似这样的一行内容(选中并复制):

css 复制代码
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...... your@email.com

3.2 添加到 GitHub

  1. 打开浏览器,登录 GitHub
  2. 点击右上角头像 → Settings
  3. 左侧菜单找到 SSH and GPG keys
  4. 点击 New SSH key
  5. Title :随便填个名字,比如 work-laptop
  6. Key:粘贴刚才复制的公钥内容
  7. 点击 Add SSH key

公司 GitLab 同理:如果还没添加过公司密钥,把 ~/.ssh/id_ed25519.pub 的内容添加到 GitLab 的 SSH Keys 设置中。


Step 4: 添加 GitHub 的 Host Key

首次连接 GitHub 时,SSH 需要确认服务器身份。提前添加可以避免后续报错:

bash 复制代码
ssh-keyscan -p 443 ssh.github.com >> ~/.ssh/known_hosts 2>/dev/null

如果你在 Step 2 中用的是标准 22 端口配置,则执行:

bash 复制代码
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null

Step 5: 测试 SSH 连接

bash 复制代码
# 测试个人 GitHub
ssh -T git@github-personal

# 测试公司 GitLab
ssh -T git@git.company.com

期望结果:

vbnet 复制代码
# GitHub 成功输出(退出码 1 是正常的):
Hi 你的用户名! You've successfully authenticated, but GitHub does not provide shell access.

# GitLab 成功输出:
Welcome to GitLab, 你的名字!

如果失败了怎么办? 见文末 常见问题


Step 6: 配置 Git 用户身份(条件包含)

目标:不同目录自动使用不同的用户名和邮箱,无需手动切换。

6.1 编辑全局 Git 配置

打开全局配置文件:

  • WindowsC:\Users\你的用户名\.gitconfig
  • macOS/Linux~/.gitconfig

确保文件中有以下内容(在文件末尾添加 includeIf 部分):

gitconfig 复制代码
[user]
    name = 公司用户名
    email = 公司邮箱@company.com

# 当在个人项目目录下操作时,自动加载个人配置
[includeIf "gitdir:D:/obsidian/"]
    path = ~/.gitconfig-personal

macOS/Linux 路径写法不同:

gitconfig 复制代码
[includeIf "gitdir:~/obsidian/"]
    path = ~/.gitconfig-personal

注意gitdir: 后面的路径末尾必须带 /,否则不会生效。

6.2 创建个人配置文件

新建文件 ~/.gitconfig-personal(跟 .gitconfig 同目录),写入:

gitconfig 复制代码
[user]
    name = 你的GitHub用户名
    email = 你的个人邮箱

6.3 验证配置是否生效

bash 复制代码
# 在个人项目目录下
cd D:/obsidian
git init    # 如果还不是 git 仓库的话
git config user.name
git config user.email
# 应该输出你的个人用户名和个人邮箱

# 在公司项目目录下
cd /path/to/company/project
git config user.email
# 应该输出你的公司邮箱

Step 7: 初始化个人仓库并推送

7.1 在 GitHub 上创建仓库

  1. 打开 GitHub → 点击右上角 +New repository
  2. 填写仓库名(如 obsidian
  3. 不要勾选任何初始化选项(不要添加 README、.gitignore 等)
  4. 点击 Create repository

为什么不要勾选初始化选项? 如果 GitHub 自动创建了一个 master 分支(带 README),而你本地也创建了提交, 两边的 Git 历史是独立的,推送时会遇到 refusing to merge unrelated histories 错误,需要额外处理。 空仓库则不会有这个问题。

7.2 本地初始化并推送

bash 复制代码
cd D:/obsidian

# 初始化 Git 仓库
git init

# 添加远程仓库(注意用 github-personal,不是 github.com)
git remote add origin git@github-personal:你的用户名/仓库名.git

# 添加所有文件并提交
git add .
git commit -m "chore: 初始化仓库"

# 推送到远程(首次推送需要 -u 设置上游分支)
git push -u origin master

关键点 :远程地址中用 github-personal 而不是 github.com。 这样 SSH 才会匹配到 Step 2 中配置的个人密钥。

7.3 后续日常推送

首次推送设置了 -u 之后,以后只需:

bash 复制代码
cd D:/obsidian
git add .
git commit -m "你的提交信息"
git push

完整配置文件参考

~/.ssh/config

bash 复制代码
# 公司 GitLab
Host git.company.com
    HostName git.company.com
    User git
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

# 个人 GitHub(443 端口,适配公司网络)
Host github-personal
    HostName ssh.github.com
    Port 443
    User git
    IdentityFile ~/.ssh/id_ed25519_personal
    IdentitiesOnly yes

~/.gitconfig

gitconfig 复制代码
[user]
    name = 公司用户名
    email = 公司邮箱@company.com

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

~/.gitconfig-personal

gitconfig 复制代码
[user]
    name = GitHub用户名
    email = 个人邮箱

常见问题

Q1: ssh -T 超时(Connection timed out)

原因:公司网络封了 22 端口。

解决 :在 ~/.ssh/config 中将 GitHub 配置改为 443 端口:

markdown 复制代码
Host github-personal
    HostName ssh.github.com
    Port 443
    ...

Q2: Host key verification failed

原因:首次连接服务器,SSH 不认识对方身份。

解决:手动添加服务器的 host key:

bash 复制代码
# GitHub(443 端口)
ssh-keyscan -p 443 ssh.github.com >> ~/.ssh/known_hosts 2>/dev/null

# GitHub(22 端口)
ssh-keyscan github.com >> ~/.ssh/known_hosts 2>/dev/null

# 公司 GitLab
ssh-keyscan git.company.com >> ~/.ssh/known_hosts 2>/dev/null

Q3: Permission denied (publickey)

排查步骤

bash 复制代码
# 1. 查看详细连接日志
ssh -vT git@github-personal

# 2. 确认密钥文件存在
ls -la ~/.ssh/id_ed25519_personal*

# 3. 确认公钥已添加到 GitHub(对比本地公钥和 GitHub 设置页面的内容)
cat ~/.ssh/id_ed25519_personal.pub

Q4: refusing to merge unrelated histories

原因:GitHub 上创建仓库时勾选了初始化选项(生成了 README),导致远程和本地是两个独立的 Git 历史。

解决

bash 复制代码
# 先拉取远程分支
git fetch origin

# 合并时允许不相关历史
git merge origin/master --allow-unrelated-histories -m "merge: 合并远程分支"

# 推送
git push

建议:创建 GitHub 仓库时不要勾选任何初始化选项,可以避免这个问题。

Q5: git config user.email 显示的还是公司邮箱

排查步骤

bash 复制代码
# 1. 确认当前目录
pwd

# 2. 确认目录是个 git 仓库(必须有 .git 目录,条件包含才会生效)
git status

# 3. 检查 .gitconfig 中 includeIf 的路径是否正确(末尾要有 /)
cat ~/.gitconfig

# 4. 手动设置(仅当前仓库,作为兜底方案)
git config user.name "你的GitHub用户名"
git config user.email "你的个人邮箱"

原理小结

整体架构

graph TB subgraph 你的电脑 subgraph SSH 层 ["SSH 层(~/.ssh/config)"] KEY1["id_ed25519
公司密钥"] KEY2["id_ed25519_personal
个人密钥"] end subgraph Git 身份层 ["Git 身份层(条件包含)"] GC[".gitconfig
公司身份(默认)"] GP[".gitconfig-personal
个人身份"] end subgraph 项目目录 P1["公司项目
C:/work/project/"] P2["个人项目
D:/obsidian/"] end end subgraph 远程服务器 GITLAB["公司 GitLab
git.company.com"] GITHUB["个人 GitHub
github.com:443"] end P1 --> GC P2 -->|"includeIf gitdir:D:/obsidian/"| GP GC --> KEY1 GP --> KEY2 KEY1 -->|"Host: git.company.com"| GITLAB KEY2 -->|"Host: github-personal"| GITHUB style KEY1 fill:#4A90D9,color:#fff style KEY2 fill:#7B68EE,color:#fff style GC fill:#4A90D9,color:#fff style GP fill:#7B68EE,color:#fff style P1 fill:#4A90D9,color:#fff style P2 fill:#7B68EE,color:#fff style GITLAB fill:#FC6D26,color:#fff style GITHUB fill:#238636,color:#fff

git push 执行流程

以在 D:/obsidian/ 目录下执行 git push 为例:

sequenceDiagram participant U as 你 participant Git as Git participant Config as .gitconfig participant SSH as SSH participant GH as GitHub U->>Git: git push Git->>Config: 读取全局配置(公司身份) Config->>Config: 检查 includeIf 条件 Note over Config: 当前目录 D:/obsidian/
匹配 gitdir:D:/obsidian/ Config->>Git: 加载 .gitconfig-personal
覆盖为个人身份 Git->>SSH: 连接 github-personal SSH->>SSH: 匹配 ~/.ssh/config 中的
Host github-personal SSH->>SSH: 使用 id_ed25519_personal 密钥 SSH->>GH: SSH 连接 ssh.github.com:443 GH->>GH: 验证公钥 GH-->>SSH: 认证成功 SSH-->>Git: 连接建立 Git->>GH: 推送代码(身份: 个人邮箱) GH-->>U: 推送完成

概述

用公司电脑写个人项目,git log 里却全是公司邮箱?推送到 GitHub 却提示权限拒绝?这是每个同时使用公司 GitLab 和个人 GitHub 的开发者都会遇到的问题。

本文基于一次真实的配置过程,采用 SSH 多密钥 + Git 条件包含 方案,实现不同目录自动切换 Git 身份。从密钥生成到推送成功,包含完整步骤、原理图解,以及公司网络下端口被封、Host Key 验证失败等实际踩坑的解决方案。

适用场景:公司 GitLab + 个人 GitHub 并存(也适用于任意两个 Git 平台的多账号管理)

阅读时间 :约 10 分钟 | 配置时间:约 15 分钟

graph LR subgraph SSH配置 SC["~/.ssh/config"] K1["~/.ssh/id_ed25519"] K2["~/.ssh/id_ed25519_personal"] SC -->|"公司 Host"| K1 SC -->|"个人 Host"| K2 end subgraph Git配置 GC["~/.gitconfig"] GP["~/.gitconfig-personal"] GC -->|"includeIf
目录匹配时加载"| GP end subgraph 远程平台 GL["GitLab
添加 id_ed25519.pub"] GH["GitHub
添加 id_ed25519_personal.pub"] end K1 -.->|公钥认证| GL K2 -.->|公钥认证| GH style SC fill:#f5f5f5,stroke:#333 style GC fill:#f5f5f5,stroke:#333 style GP fill:#f5f5f5,stroke:#333 style GL fill:#FC6D26,color:#fff style GH fill:#238636,color:#fff

配置步骤总览

flowchart TB S1["Step 1
生成个人 SSH 密钥"] S2["Step 2
编写 SSH config"] S3["Step 3
公钥添加到 GitHub"] S4["Step 4
添加 Host Key"] S5["Step 5
测试 SSH 连接"] S6["Step 6
配置 Git 条件包含"] S7["Step 7
初始化仓库并推送"] S1 --> S2 --> S3 --> S4 --> S5 S5 -->|成功| S6 --> S7 S5 -->|失败| FAQ["查看常见问题排查"] FAQ -.-> S5 style S1 fill:#4A90D9,color:#fff style S2 fill:#4A90D9,color:#fff style S3 fill:#4A90D9,color:#fff style S4 fill:#4A90D9,color:#fff style S5 fill:#7B68EE,color:#fff style S6 fill:#238636,color:#fff style S7 fill:#238636,color:#fff style FAQ fill:#D9534F,color:#fff
相关推荐
全栈王校长2 小时前
Nest 中间件 Middleware - 就像 Vue 的路由守卫
后端·nestjs
全栈王校长2 小时前
Nest ValidationPipe 参数验证 - 就像前端的表单校验
后端·nestjs
猫咪老师2 小时前
Day11 Python 关于线程和进程的最详细介绍!
后端·python
林木882 小时前
Druid 实时数据摄入与持久化全链路深度分析
后端
李日灐2 小时前
【优选算法3】二分查找经典算法面试题
开发语言·c++·后端·算法·面试·二分查找·双指针
Miss 古月先生2 小时前
thinkphp6.0 html生成pdf
后端·pdf·php
浮尘笔记2 小时前
Docker中安装Kafka以及基本配置和用法、踩坑记录
后端·docker·容器·kafka·php
IT_陈寒2 小时前
Python的异步陷阱:我竟然被await坑了一整天
前端·人工智能·后端