别再把 Git 代理设成全局了

别再把 Git 代理设成全局了------一份更干净的 .gitconfig

十年开发踩坑记。这是我见过最频繁、最隐蔽、又最容易一劳永逸解决掉的一类 Git 问题。

一个再熟悉不过的场景

刚入职一家公司,你兴冲冲给自己的 Mac 装好了代理工具(Clash、V2Ray、Surge,随意),然后复制粘贴一套"网上到处都能搜到"的命令:

bash 复制代码
git config --global http.proxy  http://127.0.0.1:7897
git config --global https.proxy http://127.0.0.1:7897

GitHub 秒下、brew install 顺畅、go get 也欢快。

过了两天,你开始拉公司内网的 GitLab:

vbnet 复制代码
fatal: unable to access 'https://git.internal.company.com/...':
Failed to connect to 127.0.0.1 port 7897: Connection refused

或者你在某个没开代理的机器上复用这份配置,再或者代理挂了一次,于是所有 Git 操作------包括拉 Gitee、拉公司内网、拉国内镜像------全数倒下。

这锅 Git 不背。是全局代理这个选择从一开始就错了。

全局代理的原罪

Git 不懂你的网络拓扑。你跟它说 --global http.proxy,它就老老实实把每一个 HTTP/HTTPS 请求都塞进代理。它不会帮你判断:

  • 这是不是公司内网域名?
  • 这是不是 Gitee、Coding、华为 CodeArts 这类国内服务?
  • 代理进程还活着吗?

境外源走代理顺畅,境内源绕一圈境外反而慢、甚至直接走不通。本来只想修一个"拉 GitHub 慢"的问题,结果把十条路都堵上了。

这是典型的"为了解决一个问题,引入了更多问题"

正确姿势:按域名配代理

Git 其实原生支持"只给特定 URL 配代理"。语法长这样:

ini 复制代码
[http "https://github.com"]
    proxy = http://127.0.0.1:7897

匹配规则是 URL 前缀 。只要请求的 URL 以 https://github.com 打头,就走这个代理;其他域名一律直连。精确、可预测、可关闭。

一个常见误会 :网上很多教程会让你同时写 [http "..."][https "..."] 两段,但 Git 的配置里根本没有 https 这个 section ------叫 http 的这一组,同时管 HTTP 和 HTTPS 两种协议的请求。多写的 [https "..."] Git 完全不读,纯属以讹传讹。想验证也简单:GIT_TRACE_CURL=1 git ls-remote https://github.com/xxx/xxx 跑一下,日志里能看到它用的就是 http.proxy

一份我在用的 .gitconfig

把"需要代理的域名"一个个列清楚,比写 --global 省心多了:

ini 复制代码
[user]
    name  = your-name
    email = you@company.com

# ========== 需要走代理的 GitHub 家族 ==========

# 主站:clone / push / fetch
[http "https://github.com"]
    proxy = http://127.0.0.1:7897

# Raw 文件:很多脚本、CI 会直接 curl 这个地址
[http "https://raw.githubusercontent.com"]
    proxy = http://127.0.0.1:7897

# Gist
[http "https://gist.github.com"]
    proxy = http://127.0.0.1:7897

# API:gh CLI、各类机器人、自动化脚本都走它
[http "https://api.github.com"]
    proxy = http://127.0.0.1:7897

# 源码打包下载:git archive、npm install github:user/repo 会用
[http "https://codeload.github.com"]
    proxy = http://127.0.0.1:7897

# Release 资源 CDN:下载二进制、release 附件时的真实宿主
[http "https://objects.githubusercontent.com"]
    proxy = http://127.0.0.1:7897

前四组大家都知道,后两组 codeloadobjects.githubusercontent.com 经常被漏------但它们恰恰是"为什么我 npm install 某个 GitHub 包失败"、"为什么我下 release 二进制卡住"的元凶。把它们也加上,GitHub 相关的操作就真的齐活了。

Gitee、公司内部 GitLab、国内镜像仓库完全不在这份名单里------它们走直连,各得其所。

进阶 1:按目录切换身份(以及任何 Git 配置)

公司项目用公司邮箱,开源项目用个人邮箱,提错邮箱是开源世界的经典社死现场。includeIf 能把两套身份物理隔离------更关键的是,能按目录切换的不只是邮箱:SSH key、GPG 签名、甚至代理配置本身,都可以。

基础:按邮箱分身

ini 复制代码
# ~/.gitconfig
[user]
    name  = your-name
    email = you@company.com

# 注意位置:includeIf 必须写在默认值**之后**,覆盖才会生效
[includeIf "gitdir:~/workspace/github/"]
    path = ~/.gitconfig-github
ini 复制代码
# ~/.gitconfig-github
[user]
    email = you@personal.com

只要仓库落在 ~/workspace/github/ 下,user.email 自动切换。不用再一个个仓库敲 git config user.email ...

顺手把 SSH key 也按目录切了

一台机器同时用公司 GitHub 和个人 GitHub,SSH key 冲突是高频痛点。用 core.sshCommand 一行搞定:

ini 复制代码
# ~/.gitconfig-github
[user]
    email = you@personal.com
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_personal -o IdentitiesOnly=yes

IdentitiesOnly=yes 是关键------它告诉 SSH 用这个 key,不要把 ssh-agent 里所有 key 轮着试。不加这一句,GitHub 会按"第一个能认的 key 属于哪个账号"来认人,经常触发账号错乱或限流。

一份多身份的完整骨架

ini 复制代码
# ~/.gitconfig ------ 默认:公司身份
[user]
    name  = your-name
    email = you@company.com

# (前面的域名代理配置省略)

# ~/workspace/github/ 下:个人 GitHub + 个人 SSH key
[includeIf "gitdir:~/workspace/github/"]
    path = ~/.gitconfig-github

# ~/workspace/oss/ 下:开源贡献,开启 GPG 签名
[includeIf "gitdir:~/workspace/oss/"]
    path = ~/.gitconfig-oss

每一种"身份"都放在独立文件里,主 ~/.gitconfig 只做分派。改动一个身份不会误伤另一个,这是塞一堆 [user] 段到单文件里做不到的。

四个真实踩过的坑

坑 1:路径必须以 / 结尾

ini 复制代码
[includeIf "gitdir:~/workspace/github"]   # ❌ 只匹配字面路径本身
[includeIf "gitdir:~/workspace/github/"]  # ✅ 匹配该目录及其所有子孙仓库

坑 2:includeIf 要写在默认值之后

Git 按从上到下的顺序读配置,后出现的覆盖先出现的。includeIf 放在默认 [user]之前,下面的默认值又会反手把它盖掉------覆盖了个寂寞。

坑 3:默认大小写敏感

gitdir: 区分大小写。如果你的路径有时 Workspace 有时 workspace(macOS 上特别容易),改用 gitdir/i: 切换成大小写无关版。

坑 4:别用相对路径

ini 复制代码
[includeIf "gitdir:./projects/"]  # ❌ 不生效
[includeIf "gitdir:~/workspace/"] # ✅

验证究竟生效了哪份配置

进到一个预期要切换身份的仓库,跑:

bash 复制代码
cd ~/workspace/github/some-repo

git config --get user.email
# 期望:you@personal.com

git config --list --show-origin | grep user.email
# 能看到 .gitconfig-github 被 include 进来,以及最终生效值来自哪里

--show-origin 是多层 include 场景下的调试神器------它告诉你每一条配置分别来自哪个文件,解 include 问题不用再靠猜。

进阶 2:SSH 协议 gitconfig 管不到

很多人卡在这里:.gitconfig 里明明配了代理,为什么 git clone git@github.com:xxx/xxx.git 还是连不上?

答案是:SSH 协议完全绕过 http.proxy 设置 ,它归 SSH 客户端管,要在 ~/.ssh/config 里配:

sshconfig 复制代码
# 方案 A:HTTP 代理(Clash、V2Ray 最常见)
Host github.com
    HostName ssh.github.com
    User git
    Port 443
    ProxyCommand nc -X connect -x 127.0.0.1:7897 %h %p

# 方案 B:SOCKS5 代理
Host github.com
    HostName github.com
    User git
    ProxyCommand nc -X 5 -x 127.0.0.1:7891 %h %p

注意方案 A 里的 HostName ssh.github.com + Port 443------这是 GitHub 官方提供的备用 SSH 入口,走 443 端口。很多公司网络会封掉 22,走这条路能救命。

验证配置真的生效了

方法一:查询某个 URL 实际匹配到的代理配置:

bash 复制代码
git config --get-urlmatch http https://github.com
# 输出:http.proxy http://127.0.0.1:7897

git config --get-urlmatch http https://gitee.com
# 空输出,说明没走代理,符合预期

方法二:让 Git 把所有网络活动打印出来:

bash 复制代码
GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://github.com/torvalds/linux

看日志里有没有 Connected to 127.0.0.1 (127.0.0.1) port 7897,有就说明代理生效。

方法三:看实际发出的请求:

bash 复制代码
curl -v --proxy http://127.0.0.1:7897 https://github.com

应急技巧:一次性开/关代理

一次性给某条命令加代理:

bash 复制代码
git -c http.proxy=http://127.0.0.1:7897 \
    -c https.proxy=http://127.0.0.1:7897 \
    clone https://github.com/xxx/xxx

一次性禁用代理(用来临时绕开老旧的全局代理配置):

bash 复制代码
git -c http.proxy= -c https.proxy= clone https://gitee.com/xxx/xxx

永久取消全局代理(写给曾经踩过坑、现在想搬家的你):

bash 复制代码
git config --global --unset http.proxy
git config --global --unset https.proxy

一张表总结

场景 正确做法
所有 Git 流量都走代理 别用 --global http.proxy
只让 GitHub 走代理 [http "https://github.com"] 精准匹配
SSH 协议(git@github.com:xxx)走代理 ~/.ssh/configProxyCommand
不同目录用不同身份 includeIf "gitdir:..."
临时开代理 git -c http.proxy=http://... clone ...
临时关代理 git -c http.proxy= clone ...
调试代理是否生效 GIT_CURL_VERBOSE=1 git clone ...

写在最后

Git 的配置哲学是一句很朴素的话:能精确就别粗糙

代理这件事尤其如此------把它收束到最小必要范围,你的 git pull 会稳得多,也不用再跟同事解释"为什么我的 Git 时好时坏"。

如果你之前一直在用全局代理,花十分钟把 .gitconfig 翻修一下,这是我能想到的、ROI 最高的本地开发环境优化之一。


配置试了有用、或者遇到了新的坑,欢迎留言告诉我。

相关推荐
BING_Algorithm2 小时前
Java多线程全体系教程 - 第二篇:Java多线程核心原理·线程安全与锁机制篇
后端
徐志斌2 小时前
Linux 内核与 Zero-Copy 零拷贝
后端
Java编程爱好者2 小时前
Spring-Boot-缓存实战-@Cacheable-这10个坑
后端
沛沛rh453 小时前
用 Rust 实现用户态调试器:mini-debugger项目原理剖析与工程复盘
开发语言·c++·后端·架构·rust·系统架构
消失的旧时光-19433 小时前
Spring Boot + MyBatis 从 0 到 1 跑通查询接口(含全部踩坑)
spring boot·后端·spring·mybatis
SamDeepThinking4 小时前
Spring AOP记录日志,生产环境的代码长什么样
java·后端·架构
小江的记录本4 小时前
【网络安全】《网络安全三大加密算法结构化知识体系》
java·前端·后端·python·安全·spring·web安全
GetcharZp4 小时前
「干掉 Gin?」极致性能的 Go Web 框架 Fiber:这才是真正的“快”!
后端