Что делать после запуска хомута перед фиксацией? - PullRequest
7 голосов
/ 14 декабря 2011

Для перехвата перед фиксацией, который изменяет промежуточные файлы, мне нужно выяснить, что нужно ставить после запуска перехвата.

Хук перед фиксацией применяет красивую печать файловэто должно быть совершено.Хук выполняет следующие задачи:

  • заменяет табуляцию пробелами
  • удаляет завершающие пробелы в конце строк
  • убирает двойные пустые строки *)
  • , если отсутствует, добавить пустую строку в конец файла *)

Действия, отмеченные *) - это те, которые вызывают проблему, описанную ниже.

После того, как это будет сделано, хук добавляет измененные файлы в индекс с помощью git add $filename.Таким образом, весь файл становится подготовленным, и я больше не могу фиксировать только небольшие части (то есть фрагменты) измененного файла.

Конечно, я мог бы git add --no-verify и обойти ловушку, но этоопция недоступна при использовании git gui.Кроме того, я хочу , чтобы применить симпатичную печать на поэтапных строках файла, поэтому обход крючка не является моей целью.

Есть ли способ выяснить, что должнобыть добавленным в индекс после применения симпатичной печати, чтобы я мог ставить содержимое right после запуска хука вместо того, чтобы ставить весь файл?


Edit 1:
Хотя ответ , предоставленный David Brigada выглядит многообещающе, он не работает: git stash --keep-index оставляет инсценированные изменения без изменений (это хорошочасть), но (по крайней мере, в msysgit) он помещает все изменений в тайник (не только неустановленные).Это приводит к конфликтам слияния при возврате тайника обратно в WC, потому что поэтапные строки могут быть изменены.


Edit 2:
Также обновленный ответ David не приводит к успеху, поскольку git отказывается сливать тайник в грязный туалет.


Редактировать 3:
Ответ от larsks указывает мне на использование .gitattributes.На первый взгляд, это кажется правильным, но я нахожу довольно запутанным, что проверенная версия была пропущена через фильтр и WC отличается от зарегистрированной версии.По крайней мере, это был мой опыт, и это подтверждается следующим замечанием в Git Book :

Если вы фиксируете эти изменения и извлекаете файл снова, вы видитеправильно подставлено ключевое слово

Мне нужно удалить файл и затем проверить его еще раз , чтобы увидеть изменения, которые были применены фильтром?Ни за что!Есть еще подсказки?

Ответы [ 5 ]

2 голосов
/ 15 декабря 2011

Я не уверен, что ловушка перед фиксацией - подходящее место для выполнения такого рода работы.Git имеет механизм фильтрации, который позволяет применять фильтры подтверждения / извлечения к документам через .gitattributes; Pro Git Book содержит примеры, в которых этот механизм фильтрации применяется для автоматического применения программы indent к исходным файлам C.

2 голосов
/ 15 декабря 2011

Вы можете поместить изменения, которые вы не подготовили для фиксации, в свой тайник в сценарии предварительной фиксации, а затем вытолкнуть их, когда вы закончите. Параметр --keep-index сохраняет только те изменения, которые вы не добавили в индекс (не запускали git add), а параметры --quiet подавляют уведомления, которые вы создаете и уничтожаете в хранилище.

То, как вы описали, не совсем канонический "мерзкий способ сделать это", большинство скриптов перед фиксацией, которые я видел, проверяют только неправильный стиль и затем выдают ошибку при фиксации, если они что-то находят. Таким образом, у вас не будет сценария предварительной фиксации непреднамеренно перезаписать какой-либо файл, в котором по какой-то причине должны быть вкладки (например, данные тестирования) - вы можете просто перезапустить коммит с помощью --no-verify, как только вы уверен, что ошибки должны были быть там.

У меня здесь есть простой сценарий предварительной фиксации. Он в основном просто запускает базовый тест git diff-index --check, но использует git stash только для тех изменений, которые он должен выполнить.

#!/bin/sh
if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

git stash save --keep-index --quiet
git diff-index --check --cached $against --
RETVAL=$?
git stash pop --quiet
exit $RETVAL

Обновление:

Вы получите конфликты слияния, если попытаетесь использовать эту стратегию со сценарием, который изменяет содержимое, которое вы хотите зафиксировать. Мы должны извлечь всплывающее окно из сценария до фиксации и выполнить явное слияние в сценарии после фиксации.

#!/bin/sh

git stash save --keep-index --quiet
# Add your script to prettify the code here ...
git add .

Теперь скрипт пост-фиксации выглядит следующим образом

#!/bin/sh

git merge stash@{0} -s recursive -Xtheirs
git stash drop --quiet stash@{0}

Слияние recursive с параметром theirs должно сохранить изменения, сделанные скриптом, когда это возможно.

0 голосов
/ 22 октября 2015

То, что вы хотите - это иметь ловушку перед фиксацией, которая выполняет описанные вами действия, но затем также ловушку commit-msg.

Вот как бы я решил проблему:

  1. Добавьте следующий хук предварительной фиксации:

    #!/bin/sh
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 YOUR_SMUDGE_SCRIPT
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 git add -u -v --
    
  2. Добавьте следующий хук commit-msg:

    #!/bin/sh
    awk '!/^[[:space:]]*(#|$)/{exit f++}END{exit !f}' "$1" && exit
    # NOTREACHED unless commit was aborted
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 YOUR_CLEAN_SCRIPT
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 git add -u -v --
    

Позаботьтесь о том, чтобы заменить YOUR_CLEAN_SCRIPT и YOUR_SMUDGE_SCRIPT на имя команды, которую вы хотите запустить, которая будет выполнять фактические процедуры очистки / удаления пятен. Подпрограмма smudge должна расширять ключевые слова (происходящие перед фиксацией), а процедура clean должна отменять изменения (происходящие, когда фиксация прерывается). Этим сценариям будут переданы файлы, которые необходимо изменить (предварительно подготовленные для другого редактирования).

0 голосов
/ 06 июля 2012

Поскольку моя цель не представляется достижимой, я помог мне с другим решением:

Я ставлю только части файлов, когда нахожусь в git gui. К счастью, git gui позволяет добавлять пользовательские команды в меню Tools. Я установил скрипт с именем hooks.sh, который получает один параметр: enable или disable. Этот скрипт добавляется в меню Tools, один раз с enable, один раз с disable в качестве параметра.

Таким образом, я мог бы спокойно отключить перехват, когда ставил только часть файла, затем зафиксировать и снова включить перехват.

Вот, пожалуйста:

#!/bin/sh

################################################################################
# hooks.sh                                                                     #
# enable or disable git hooks.                                                 #
################################################################################

THEHOOK=pre-commit                  # which hook to work with
ENABLEDFILE=./.git/hooks/$THEHOOK   # original name of the file
DISABLEDFILE=$ENABLEDFILE.disabled  # disabled name of the file
OLDFILE=''                          # for mv command: old name
NEWFILE=''                          # for mv command: new name

# parse parameters
case $1 in
  disable)
    OLDFILE=$ENABLEDFILE
    NEWFILE=$DISABLEDFILE
    ;;
  enable)
    OLDFILE=$DISABLEDFILE
    NEWFILE=$ENABLEDFILE
    ;;
  *)
    echo -e "operation:\n    $0 enable  to enable the hook\n    $0 disable to disable the hook"
    exit 1
    ;;
esac

if [ -e $OLDFILE ]
then
  mv $OLDFILE $NEWFILE
else
  echo "nothing to do"
fi
0 голосов
/ 24 декабря 2011

Я не уверен на 100%, что понимаю цель, но, возможно, вы могли бы попробовать следующий подход. Пусть ваш хук сгенерирует патч вместо записи изменений на диск. (Вы можете сделать это, например, в Python, используя модуль difflib, или записать временный файл и создать оболочку для diff.) Затем используйте git apply--cached и другими флагами в зависимости от ситуации) для патч для индекса, а также для рабочего дерева (вручную или автоматически с помощью хука).

...