2013-05-30 3 views
16

Одна из вещей, которые я держу в своем open novel in GitHub, - это list of words. Я бы хотел установить автоматически первую строку, которая представляет собой количество слов в словаре. Мой первый вариант - написать крюк предварительной фиксации, который читает файл, подсчитывает слова, переписывает первую строку и записывает ее снова. Вот кодМожете ли вы изменить содержимое файла во время git commit?

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); 
    } 
    } 
}; 

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

error: Your local changes to the following files would be overwritten by checkout: text/words.dic Please, commit your changes or stash them before you can switch branches. Aborting

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

ответ

15

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

Вот мой пример зафиксироваться крюк, модифицированный из .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 

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

+0

Так в основном это другой ребенок взлома, не так ли? Выполняя это мой путь, файл изменяется, но не фиксируется до следующего – jjmerelo

+1

Да.Я не уверен, что я был бы очень доволен любым подходом; Я бы предпочел что-то вроде Makefile, чтобы обновлять вещи по мере необходимости, и что-то более ручное. Но это должно сработать. – torek

+0

Может быть, сделать это после коммита будет более правильным? – jjmerelo

9

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

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

(прокручивают немного вниз к " размазать/чистая»схема)

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

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

    novel.txt updateDict

  2. Тогда, скажите Git, что фильтр «updateDict» делает на размазать (мерзавец кассе) и чистые (мерзавец добавить):

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

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

Смежные вопросы