Windows下使用Git Clean Filter,脚本未执行替换操作
Git Clean Filter 版本号递增失效问题排查与修复
问题场景
我试图通过Git Clean Filter实现文件暂存时自动递增版本号,已完成以下配置:
- 在
.gitattributes中添加规则:*.txt filter=increv - 在
.git/config中配置过滤器:[filter "increv"] clean = bash inc_rev
使用的inc_rev脚本如下:
#!/bin/sh STDIN=$(cat) [[ $STDIN =~ (MyRev_)([0-9]{12}) ]] i=${BASH_REMATCH[1]} #需保留并放回的分组 j=${BASH_REMATCH[2]} #需要递增的部分 [[ $j =~ ^0*([^0]+.*$) ]] k=${BASH_REMATCH[1]} #去除前导0 m=$((k+1)) #执行递增 printf -v n "%012d" $m #重新补全前导0为12位 echo STDIN | sed 's|MyRev_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]|$i$n|g'
目标文件test.txt中需要递增的行是:
TEXT "MyRev_000000000019"
当前问题:暂存时版本号替换操作未执行,已通过git status确认脚本被调用(脚本报错会在该命令输出中显示)。
- UPDATE1:使用的Shell为bash
- UPDATE2:执行
git config filter.increv.clean返回bash inc_rev;执行git check-attr -a *.txt返回test.txt: filter: increv
问题原因与修复
脚本存在多个导致替换失效的问题,逐一修复如下:
1. 变量引用错误
echo STDIN会直接输出字符串"STDIN",而非读取到的文件内容,需改为echo "$STDIN"。
2. Sed变量解析失效
Sed命令中使用单引号包裹替换字符串时,shell不会解析其中的$i和$n变量,需改用双引号包裹替换规则。
3. 前导零导致的数值解析错误
带前导零的数字在bash中会被默认当作八进制处理,000000000019属于无效八进制数,直接递增会报错。无需手动去除前导零,改用10#前缀强制按十进制解析即可。
4. 脚本兼容性问题
脚本使用了bash专属特性(BASH_REMATCH、printf -v),但开头指定#!/bin/sh(部分系统中sh不是bash),需改为#!/bin/bash。
修复后的完整脚本
#!/bin/bash STDIN=$(cat) # 匹配MyRev_后跟12位数字的模式 if [[ $STDIN =~ (MyRev_)([0-9]{12}) ]]; then prefix=${BASH_REMATCH[1]} rev_str=${BASH_REMATCH[2]} # 强制按十进制解析版本号,避免前导零引发的八进制错误 rev_num=$((10#$rev_str)) new_rev_num=$((rev_num + 1)) # 格式化为12位带前导零的字符串 printf -v new_rev_str "%012d" "$new_rev_num" # 替换版本号,双引号确保变量被正确解析 echo "$STDIN" | sed "s|MyRev_[0-9]\{12\}|${prefix}${new_rev_str}|g" else # 未匹配到目标模式时,直接输出原内容 echo "$STDIN" fi
调试方法
- 直接测试脚本逻辑:在终端中输入以下命令,模拟Git调用脚本的场景,查看输出是否符合预期:
echo 'TEXT "MyRev_000000000019"' | ./inc_rev
- 添加调试日志:在脚本中插入变量打印语句,追踪每一步的变量值,例如:
echo "原始输入: $STDIN" >> /tmp/git_filter_debug.log echo "匹配到的前缀: $prefix" >> /tmp/git_filter_debug.log echo "原始版本号: $rev_str" >> /tmp/git_filter_debug.log
- 检查脚本权限:确保
inc_rev脚本拥有可执行权限:
chmod +x inc_rev
内容的提问来源于stack exchange,提问作者jayveesea
相关产品推荐
相关产品推荐

