Можете ли вы изменить содержимое файла во время git commit?

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

PRE_COMMIT {
  my ($git) = @_;
  my $branch =  $git->command(qw/rev-parse --abbrev-ref HEAD/);
  say "Pre-commit hook in $branch";
  if ( $branch =~ /master/ ) {
     my $changed = $git->command(qw/show --name-status/);
     my @changed_files = ($changed =~ /\s\w\s+(\S+)/g);
     if ( $words ~~ @changed_files ) {
       my @words_content = read_file( $words );
       say "I have $#words_content words";
       $words_content[0] = "$#words_content\n";
       write_file( $words, @words_content );
     }
   }
};

Тем не менее, так как файл уже был поставлен, я получаю эту ошибку

ошибка: ваши локальные изменения в следующих файлах будут перезаписаны извлечением: text / words.dic Пожалуйста, передайте изменения или сохраните их, прежде чем вы сможете переключать ветки. Aborting

Может быть, лучше сделать это как хук после коммита, и изменился ли он для следующего коммита? Или сделать что-то совершенно другое? Общий вопрос: если вы хотите обрабатывать и изменять содержимое файла во время коммита, каков правильный способ сделать это?

2 ответа

Решение

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

Вот мой пример ловушки pre-commit, модифицированный из.sample:

#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# [snipped much of what used to be in it, added this --
#  make sure you take out the exec of git diff-index!]

num=$(cat zorg)
num=$(expr 0$num + 1)
echo $num > zorg
git add zorg
echo "updated zorg to $num"
exit 0

а потом:

$ git commit -m dink
updated zorg to 3
[master 76eeefc] dink
 1 file changed, 1 insertion(+), 1 deletion(-)

Но обратите внимание на небольшой недостаток (не относится к вашему делу):

$ git commit
git commit
updated zorg to 4
# On branch master
# Untracked files:
[snip]
nothing added to commit but untracked files present (use "git add" to track)
$ git commit
updated zorg to 5
# Please enter the commit message for your changes. Lines starting
[snip - I quit editor without changing anything]
Aborting commit due to empty commit message.
$ git commit
updated zorg to 6
# Please enter the commit message for your changes. Lines starting

В основном, потому что обновления pre-commit hook и git adds, файл продолжает увеличиваться, хотя я на самом деле не делаю коммит здесь.

Оказывается, вы можете запускать "крючки" - они фактически обрабатываются другим механизмом - при размещении файлов (в git add время):

https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes

(прокрутите немного вниз к диаграмме "smudge / clean")

Вот что я понял:

  1. редактировать .gitattributesи создайте правила для файлов, которые должны запускать обновление словаря:

    novel.txt updateDict

  2. Затем скажите Git, что делает фильтр "updateDict" для smudge (git checkout) и clean (git add):

    $ git config --global filter.updateDict.clean countWords.script

    $ git config --global filter.updateDict.smudge cat

Другие вопросы по тегам