你可以在git commit期间更改文件内容吗?

时间:2013-05-30 08:39:43

标签: git hook commit

我在open novel in GitHub中保留的一件事是list of words我想自动设置第一行,即字典中的字数。我的第一个选择是编写一个预提交钩子,它读取文件,计算单词,重写第一行并再次写回。这是代码

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

但是,由于该文件已经暂存,我收到此错误

  

错误:您对以下文件的本地更改将被覆盖   结帐时:     文/ words.dic   请提交您的更改或存储它们   在你可以切换分支之前。   中止

可能最好将它作为一个post-commit钩子并将其更改为下一次提交?或者做一些完全不同的事情?一般的问题是:如果你想在提交过程中处理和更改文件的内容,那么这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:21)

git commit中的实际提交是预提交挂钩完成后索引中的任何内容。这意味着只要您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,所以即使我实际上没有在这里进行提交,文件也会继续递增。

答案 1 :(得分:10)

事实证明你可以运行“钩子” - 它们实际上是由另一种机制来处理的 - 当登台文件时(git add时间):

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

(向下滚动到“涂抹/清洁”图表)

以下是我的理解:

  1. 编辑.gitattributes,并为应触发字典更新的文件创建规则:

    novel.txt updateDict

  2. 然后,告诉Git“updateDict”过滤器在涂抹(git checkout)和清理(git add)时做了什么:

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

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