Git hook, изменение файлов фиксации

Я пытаюсь написать git pre-commit hook script, он должен записывать дату фиксации в начале измененных файлов. Моя проблема в том, что я не могу добавить измененные файлы в предыдущую фиксацию. Когда я снова пытаюсь вызвать 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

person SerCe    schedule 01.02.2013    source источник


Ответы (3)


Вы не можете изменить фиксацию в хуке pre фиксации.
И то, что вы делаете, похоже на механизм расширения ключевых слов, что не является лучшей практикой для Git (или любого другого DVCS), как объяснялось в "Чтобы поставить префикс ?<revision-number> в коды Git / Svn ".

Другие подходы включают:

person VonC    schedule 01.02.2013

Может быть атрибутом git с smudge / clean - это то, что вы ищете:

введите описание изображения здесь

введите описание изображения здесь

Связано: используйте git smudge / clean для замены содержимого файла

person Kenny Ho    schedule 29.08.2014

Глядя на хук перед фиксацией, у вас почти что-то вроде работает. Вот минимальные изменения, которые я считаю необходимыми:

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

Вышеупомянутая реализация может обрабатывать любое имя файла, которое вы ей задаете.

person src committer    schedule 22.10.2015