PowerShell 下 git log 中文乱码的完整排查与解决
场景:PowerShell、WebStorm 内置终端(默认 PowerShell)中执行
git log,中文提交信息显示乱码。
背景
在 PowerShell 中使用 git log、git stash等命令时,中文提交信息显示为乱码。排查后发现,是分页器导致,一个很自然的想法是------禁用分页器:
perl
git --no-pager log
乱码确实没了,但代价是 git log 直接把整段历史刷屏,翻不动、找不着,体验极差。分页要保留,中文也要正常,这才是目标。
这个问题在 WebStorm 内置终端(默认 PowerShell) 里尤其容易遇到,而且比裸 PowerShell 更顽固------后文会解释原因。
问题本质:编码链上有三个环节
git log 的输出要经过一条链路才能显示到屏幕上:
Git 输出 → less 分页器渲染 → PowerShell 控制台显示
三个环节任何一环的字符集不一致,中文就会变成乱码。默认情况下:
| 环节 | 默认编码 | 结果 |
|---|---|---|
| Git 输出 | UTF-8(通常) | ✅ |
less 渲染 |
视 LESSCHARSET 而定,Windows 下常不识别 UTF-8 |
❌ |
| PowerShell 控制台 | 代码页 936(GBK) | ❌ |
所以只改一处往往不够,必须三端对齐到 UTF-8。
排查过程(踩坑记录)
第一步:配置 Git 与 less
按常规思路先配 Git 和分页器:
powershell
csharp
# 让 git log 以 UTF-8 输出
git config --global i18n.logoutputencoding utf-8
# 使用 less,-R 保留颜色渲染
git config --global core.pager "less -R"
再把 LESSCHARSET 设为 utf-8。为了让设置永久生效,把它加进了 Windows 系统环境变量 (变量名 LESSCHARSET,值 utf-8),然后重启终端。
结果:依然乱码。
第二步:定位变量到底有没有生效
在 PowerShell 里检查:
powershell
ruby
$env:LESSCHARSET
没有任何输出------变量没被当前进程读到。
但换一种方式读注册表:
powershell
css
[Environment]::GetEnvironmentVariable('LESSCHARSET','Machine')
能正常输出 utf-8。
这就是关键矛盾:注册表里有,进程里没有。
第三步:找到根因
Windows 的环境变量是在进程启动时一次性继承的快照,之后注册表再怎么改,已经运行的进程(包括新开的终端)都不会自动刷新。
而 WebStorm 的内置终端更特殊 :它继承的是 WebStorm 主进程启动时的环境快照。这意味着:
- 你在 Windows 里新加了系统变量;
- 关掉内置终端再开一个;
- 新终端拿到的仍然是 WebStorm 启动那一刻的旧环境。
必须重启整个 WebStorm,内置终端才可能拿到新变量。很多人卡在这里,以为是配置写错了。
第四步:临时验证
在当前会话里直接设一次:
powershell
ini
$env:LESSCHARSET = 'utf-8'
再跑 git log------中文正常了。
至此结论明确:Git 配置没问题,问题纯粹是 LESSCHARSET 没进入 PowerShell 进程。
最终方案
方案一(推荐):写入 PowerShell Profile
不依赖系统环境变量的传播机制,每次启动终端自动执行,最可控。
打开 Profile 文件:
bash
notepad $PROFILE
如果提示文件不存在,先创建:
bash
New-Item -Path $PROFILE -Type File -Force
notepad $PROFILE
粘贴以下内容并保存:
ini
# ============================================================
# PowerShell 环境编码配置
# 目的:解决 git log 分页显示时中文乱码的问题
# 原理:让 Git 输出、less 渲染、PowerShell 控制台三端统一使用 UTF-8
# ============================================================
# ------------------------------------------------------------
# 1. 告诉 less 分页器使用 UTF-8 字符集来解析和渲染文本
# 这是解决分页乱码最关键的一项。
# 必须显式设置到当前进程------Windows 系统环境变量有时不会被
# 新开的终端(尤其是 WebStorm 内置终端)正确继承。
# ------------------------------------------------------------
$env:LESSCHARSET = 'utf-8'
# ------------------------------------------------------------
# 2. 将控制台代码页切换为 65001(UTF-8)
# 默认可能是 936(GBK),会把 less 输出的 UTF-8 字节流
# 误读成乱码。> $null 用于屏蔽 chcp 自带的提示输出。
# ------------------------------------------------------------
chcp 65001 > $null
# ------------------------------------------------------------
# 3. 设置 .NET 控制台的输出编码为 UTF-8
# 影响 PowerShell 向控制台写字符时的编码方式。
# ------------------------------------------------------------
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# ------------------------------------------------------------
# 4. 设置 PowerShell 管道的默认输出编码为 UTF-8
# 影响命令之间通过管道传递文本时的编码。
# ------------------------------------------------------------
$OutputEncoding = [System.Text.Encoding]::UTF8
第 2~4 项是辅助项。如果只保留
$env:LESSCHARSET = 'utf-8'通常也能解决当前场景,但保留全部能让编码链更完整,避免输出重定向、管道等场景再次踩坑。
方案二:配套的 Git 全局配置
Profile 解决的是"进程内变量",Git 侧的配置需要另外持久化(写入全局 .gitconfig):
csharp
# 让 git log 以 UTF-8 编码输出日志内容
git config --global i18n.logoutputencoding utf-8
# 使用 less 作为分页器,-R 允许正确渲染颜色控制字符
git config --global core.pager "less -R"
# 关闭路径转义,让中文文件名/路径直接显示,
# 而不是 \346\226\207 这样的八进制转义码
git config --global core.quotepath false
这三条是持久化写入配置文件的,只需执行一次。
验证
1. 让 Profile 立即生效(免开新窗口):
bash
. $PROFILE
2. 确认变量已加载:
ruby
$env:LESSCHARSET
# 应输出:utf-8
3. 确认控制台编码:
markdown
[Console]::OutputEncoding
# 应显示 UnicodeEncoding(UTF-8),而不是 gb2312 / 936
4. 实际测试:
bash
git log -5
分页正常工作,中文提交信息显示正常,即大功告成。
避坑提示
- WebStorm 内置终端必须重启 WebStorm 才会加载新的系统环境变量。 只关终端窗口没用,因为它继承的是 IDE 主进程启动时的环境快照。这也是 Profile 方案更可靠的原因------每次终端启动都会执行,绕过了快照问题。
i18n.logoutputencoding并未被废弃。 网上有说法称它在较新 Git 版本中弃用,但在 Windows 环境下它依然有效,是解决乱码的标准配置之一,可以放心保留。- 系统环境变量 vs Profile 的取舍。 系统变量是"全局但传播不可靠",Profile 是"局部但每次都生效"。就个人开发场景而言,Profile 更透明、更可复现,推荐优先。
core.quotepath false容易被忽略。 它不解决"提交信息乱码",但能解决"中文文件名显示成八进制转义"的问题,顺手加上体验会好很多。
小结
| 层次 | 配置项 | 位置 | 作用 |
|---|---|---|---|
| Git 输出 | i18n.logoutputencoding utf-8 |
~/.gitconfig |
日志以 UTF-8 输出 |
| 分页器 | core.pager "less -R" |
~/.gitconfig |
保留分页与颜色 |
| 路径显示 | core.quotepath false |
~/.gitconfig |
中文路径不转义 |
| less 字符集 | $env:LESSCHARSET = 'utf-8' |
$PROFILE |
less 按 UTF-8 渲染 |
| 控制台代码页 | chcp 65001 |
$PROFILE |
控制台切 UTF-8 |
| 控制台/管道编码 | [Console]::OutputEncoding / $OutputEncoding |
$PROFILE |
端到端统一 UTF-8 |
核心思路一句话:让 Git、less、PowerShell 三端都对齐 UTF-8,并把进程级变量写进 Profile,绕开 Windows 环境变量传播不可靠的坑。