9

我正在尝试编写一个 Git 预提交挂钩脚本。它应该在修改文件的开头写下提交日期。

我的问题是我无法将修改后的文件添加到以前的提交中。当我再次尝试调用 Git 提交时,它会递归运行。如何编写脚本,在修改文件末尾附加修改时间?

我的代码:

#!/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
4

3 回答 3

3

您不能在提交挂钩中修改提交。
而且您所做的类似于关键字扩展机制,这不是 Git(或任何 DVCS)的最佳实践,如“通过 Git/Svn 为代码添加前缀?<revision-number>”中所述。

其他方法包括:

于 2013-02-01T07:33:41.390 回答
2

可能是带有涂抹/清洁操作的git 属性是您正在寻找的:

在此处输入图像描述

在此处输入图像描述

相关: 使用 git smudge/clean 替换文件内容

于 2014-08-29T14:30:02.113 回答
2

看看你的 pre-commit 钩子,你几乎有一些可以工作的东西。这是我认为需要的最小更改:

    #!/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
    

上面的实现可以处理你扔给它的任何文件名。

于 2015-10-22T02:32:41.477 回答