Git钩子,修改提交文件

时间:2013-02-01 05:27:00

标签: git bash hook commit pre-commit-hook

我正在尝试编写git pre-commit钩子脚本,它应该在修改文件的开头写入提交日期。我的问题是我无法将修改过的文件添加到以前的提交中。当我再次尝试调用git commit时,它会运行递归。如何编写脚本,在修改后的文件末尾添加修改时间?

我的代码:

#!/bin/bash

files_modified=`git diff-index --name-only HEAD`

for f in $files_modified; do
    if [[ $f == *.groovy ]]; then
        $line = $(head -1 f)
        if [[ $line == "/%%*" ]];
        then
            sed -i 1d
        fi
        echo "/%% " + $(date +"%m_%d_%Y") + " %%\\" >> f
        git add f
    fi
done 
git commit --amend #recursive
exit

3 个答案:

答案 0 :(得分:2)

您无法修改 pre 提交挂钩中的提交 而你所做的与关键字扩展机制类似,这不是Git(或任何DVCS)的最佳实践,如“To put the prefix ?<revision-number> to codes by Git/Svn”中所述。

其他方法包括:

答案 1 :(得分:2)

答案 2 :(得分:2)

看着你的预提交钩子,你几乎有一些有点工作的东西。这是我认为需要的最小变化:

    #!/bin/bash
    files_modified=`git diff --cache --name-only --diff-filter=ACM`
            ### fix: use current branch; cached; and only files
    for f in $files_modified; do ### broken: if space in filename(s)
        if [[ $f == *.groovy ]]; then
            line=$(head -1 $f) ### fix: forgot a $ before f
            if [[ $line == "/%%*" ]];
            then
                sed -i 1d "$f" ### fix: forgot file argument
            fi
            echo "/%% " + $(date +"%m_%d_%Y") + " %%\\" >> $f
                    ### fix: forgot a $ before f
            git add -u $f ### fix: forgot a $ before f
        fi
    done
    ### undesired ### git commit --amend #recursive
    ### unneeded ### exit

但是,我注意到您的实施存在一些问题。您将从文件顶部删除与“/ %% *”匹配的行,并在底部添加一个新行。每次运行此操作时,您将永远在文件末尾添加新的/%% mm_dd_YYYY %%\行。这可能不是你想要的(1000个提交以后,以前空的文件将有1000行)。我认为你打算做的是更换现有的生产线。在这种情况下,替换匹配行的sed转换将起作用。

这是一个我认为更接近你想要的食谱:

    #!/bin/sh
    TMPFILE="/tmp/${0##*/}.$$"
    for f in $( git diff --cached --name-only --diff-filter=ACM ); do
            # XXX broken: if space in filename(s)
            case "$f" in
            *.groovy) : fall through ;;
            *) continue
            esac
            cp "$f" "$TMPFILE" || continue
            awk -v new="/%% $(date +%m_%d_%Y) %%\\" \
                    'NR==1{sub("^/%% .* %%\\\\$",new)}1' \
                    < "$TMPFILE" > "$f"
            git add -u -- "$f"
    done

如果文件的第一行与/%% ... %%\匹配,则使用当前日期/时间(在预提交挂钩时)更新。

然而,这只是为了说明如何简单地完成它。这实际上不是一个完整的解决方案。上述脚本不适用于名称中包含空格的文件,双引号,反斜杠,制表符等。

要获得完整的解决方案:

  1. 使用以下预提交挂钩:

    #!/bin/sh
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 .filters/myfilter
    
  2. 使用以下内容创建“.filters / myfilter”:

    #!/bin/sh
    TMPFILE="/tmp/${0##*/}.$$"
    for f in "$@"; do ### the only difference from above recipe
            case "$f" in
            *.groovy) : fall through ;;
            *) continue
            esac
            cp "$f" "$TMPFILE" || continue
            awk -v new="/%% $(date +%m_%d_%Y) %%\\" \
                    'NR==1{sub("^/%% .* %%\\\\$",new)}1' \
                    < "$TMPFILE" > "$f"
            git add -u -- "$f"
    done
    
  3. 上面的实现可以处理你抛出的任何文件名。