You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下Git commit-msg钩子非ASCII字符计数异常问题求助(无额外依赖)

解决Windows下TortoiseGit commit-msg钩子统计俄文(UTF-8)字符长度翻倍问题

这个问题我之前也碰到过——在Git for Windows的bash环境里,默认的字符串长度统计是按字节数来的,而俄文的西里尔字母在UTF-8编码中每个占2个字节,所以${#line}会返回实际字符数的两倍。刚好你不想加额外依赖,那咱们用Git环境自带的工具和配置就能搞定。

原因分析

你的.git/COMMIT_EDITMSG是UTF-8编码,钩子能正确显示俄文字符,说明终端已经支持UTF-8,但bash默认的字符串处理(包括${#}长度统计)在未指定UTF-8 locale的情况下,会把多字节字符拆成单个字节计数。

解决方案1:配置UTF-8 Locale(推荐)

Git for Windows自带的bash 4.2+版本已经支持Unicode字符长度统计,只要在钩子开头设置正确的locale即可:

#!/bin/sh

# 强制设置UTF-8 locale,让bash按Unicode字符统计长度
export LC_ALL=en_US.UTF-8

# 读取提交消息文件($1是commit-msg钩子的参数,即COMMIT_EDITMSG路径)
while read -r line; do
    # 去除Windows风格的回车符(避免干扰长度统计)
    cleaned_line=$(echo "$line" | tr -d '\r')
    char_length=${#cleaned_line}
    
    # 这里替换成你的长度检查逻辑,比如限制每行不超过72字符
    if [ "$char_length" -gt 72 ]; then
        echo "错误:提交消息行长度超过限制(当前$char_length字符,最大允许72)" >&2
        exit 1
    fi
done < "$1"

保存钩子脚本后,记得给它加可执行权限(在Git Bash里运行chmod +x .git/hooks/commit-msg)。

解决方案2:用iconv转码计算(兼容旧版本bash)

如果你的bash版本比较旧,不支持Unicode长度统计,可以用Git环境自带的iconv工具,把UTF-8转成UTF-16(每个BMP字符占2字节),再通过字节数换算字符数:

#!/bin/sh

while read -r line; do
    cleaned_line=$(echo "$line" | tr -d '\r')
    # 将UTF-8转成UTF-16LE(无BOM),统计字节数后除以2得到字符数
    byte_count=$(printf "%s" "$cleaned_line" | iconv -f utf-8 -t utf-16le | wc -c)
    char_length=$((byte_count / 2))
    
    if [ "$char_length" -gt 72 ]; then
        echo "错误:提交消息行长度超过限制(当前$char_length字符,最大允许72)" >&2
        exit 1
    fi
done < "$1"

这个方法不需要依赖bash的Unicode支持,完全用Git自带的工具实现。

验证方法

你可以在钩子中加一行调试代码,打印实际字符数和字节数对比:

echo "字符数:$char_length,字节数:${#cleaned_line}"

运行提交测试,俄文行的字符数应该和你实际输入的一致,字节数是它的两倍。

内容的提问来源于stack exchange,提问作者Igor Melnichenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:45:54