Windows Bash下Git提交钩子重复添加任务代码的问题排查
解决Git钩子中amend操作重复添加任务代码的问题
我明白你遇到的麻烦——用Git钩子自动给提交信息加分支里的任务代码时,执行git commit --amend会重复添加前缀,导致提交消息变得乱糟糟的。咱们一步步来把这个问题搞定。
最初的脚本问题
你一开始的脚本核心逻辑是对的:提取分支里的任务代码,给提交消息加前缀,但它缺少了关键的判断步骤——没有检查提交消息里是否已经存在这个前缀,所以每次amend都会再添一遍。
#!/bin/bash # Include any branches for which you wish to disable this script if [ -z "$BRANCHES_TO_SKIP" ]; then BRANCHES_TO_SKIP=(master develop) fi # Get the current branch name and check if it is excluded BRANCH_NAME=$(git symbolic-ref --short HEAD) BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$") # Trim it down to get the parts we're interested in TRIMMED=$(echo $BRANCH_NAME | sed -e 's:\([a-z]\+\/\)*\([A-Z]\+-[0-9]\+\).\+:\2:') # If it isn't excluded, preprend the trimmed branch identifier to the given message if [ -n "$BRANCH_NAME" ] &&! [[ $BRANCH_EXCLUDED -eq 1 ]]; then sed -i.bak -e "1s,^,$TRIMMED: ," $1 fi
你修改时犯的错误
你参考了Windows CMD的脚本,但忘了当前用的是Bash(Shell脚本),两者语法完全不兼容:
- CMD里的
set 变量|find "字符串"是用来查找变量内容里的字符串,但Bash里的set是用来配置Shell选项的,根本不是输出变量值的命令。 - Bash里的
find命令是用来搜索文件系统中的文件的,不是用来在字符串或文本里查找内容的,所以你写的set BRANCH_NAME|find "$TRIMMED"会被解析成“查找名为LG-132的文件”,自然会报错找不到文件。
正确的修改方案
我们需要用Bash的方式检查提交消息文件(也就是脚本参数$1指向的临时文件)里是否已经有任务代码前缀。这里用grep命令最适合,它可以直接搜索文件内容:
修改后的完整脚本
#!/bin/bash # Include any branches for which you wish to disable this script if [ -z "$BRANCHES_TO_SKIP" ]; then BRANCHES_TO_SKIP=(master develop) fi # Get the current branch name and check if it is excluded BRANCH_NAME=$(git symbolic-ref --short HEAD) BRANCH_EXCLUDED=$(printf "%s\n" "${BRANCHES_TO_SKIP[@]}" | grep -c "^$BRANCH_NAME$") # Trim it down to get the parts we're interested in TRIMMED=$(echo "$BRANCH_NAME" | sed -e 's:\([a-z]\+\/\)*\([A-Z]\+-[0-9]\+\).\+:\2:') # If it isn't excluded, check if message already has the prefix before adding if [ -n "$BRANCH_NAME" ] &&! [[ $BRANCH_EXCLUDED -eq 1 ]]; then # 检查提交消息的第一行是否已以任务代码前缀开头 if! grep -q "^$TRIMMED:" "$1"; then # 如果没有,就给第一行添加前缀 sed -i.bak -e "1s,^,$TRIMMED: ," "$1" fi fi
关键修改点解释
- 用
grep检查文件内容:grep -q "^$TRIMMED:" "$1"里的-q是静默模式,不会输出内容,只返回退出码:- 如果提交消息文件里有以
$TRIMMED:开头的行(比如LG-132:),grep返回0,!取反后条件不成立,跳过添加操作。 - 如果没有找到匹配的行,
grep返回非0,!取反后条件成立,执行sed添加前缀。
- 如果提交消息文件里有以
- 引号包裹变量:把
echo $BRANCH_NAME改成echo "$BRANCH_NAME",避免分支名称里有空格时出现解析错误。 - 精准匹配前缀:用
^$TRIMMED:匹配行开头的前缀,这样可以避免提交消息中间出现相同任务代码时的误判。
这样修改后,不管你执行多少次git commit --amend,都只会在第一次添加前缀,不会重复叠加了。
内容的提问来源于stack exchange,提问作者Alex Ironside
相关产品推荐
相关产品推荐

