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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16831536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 08:34:18  来源:igfitidea点击:

Can you change a file content during git commit?

githookcommit

提问by jjmerelo

One of the things I keep in my open novel in GitHubis a list of wordsI would like to set automatically the first line, which is the number of words in the dictionary. My first option is to write a pre-commit hook that reads the file, counts the words, rewrites the first line and writes it back again. Here's the code

有一个问题我一直在我的东西在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 );
     }
   }
};

However, since the file has already been staged, I get this error

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

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

错误:您对以下文件的本地更改将被检出覆盖: text/words.dic 请提交您的更改或将它们隐藏,然后才能切换分支。中止

Might it be better to do it as a post-commit hook and have it changed for the next commit? Or do something completely different altogether? The general question is: if you want to process and change the contents of a file during commit, what's the proper way of doing it?

将其作为提交后挂钩并在下一次提交时进行更改可能会更好吗?或者做一些完全不同的事情?一般的问题是:如果您想在提交期间处理和更改文件的内容,那么正确的做法是什么?

采纳答案by torek

The actual commit stuck in by git commitis whatever is in the index once the pre-commit hook finishes. This means that you canchange files in the pre-commit hook, as long as you git addthem too.

git commit一旦预提交钩子完成,实际提交的内容就是索引中的任何内容。这意味着您可以更改预提交挂钩中的文件,只要您更改git add它们。

Here's my example pre-commit hook, modified from the .sample:

这是我的示例预提交钩子,从 .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

and then:

进而:

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

But note a minor flaw (won't apply to your case):

但请注意一个小缺陷(不适用于您的情况):

$ 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

Basically, because the pre-commit hook updates and git adds, the file keeps incrementing even though I'm not actually doing the commit, here.

基本上,因为 pre-commit 钩子更新和git adds,即使我实际上并没有在这里进行提交,文件也会不断增加。

回答by LeGEC

It turns out you can run "hooks" - they are actually handled by another mechanism - when stagingfiles (at git addtime) :

事实证明,您可以运行“钩子”——它们实际上是由另一种机制处理的——当暂存文件时(在git add时间):

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

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

(scroll down a bit to the "smudge" and "clean" diagrams)

(向下滚动到“污迹”和“清洁”图表)

Here is what I understood :

这是我的理解:

  1. edit the .gitattributes, and create rules for the files which should trigger a dictionary update:

    novel.txt filter=updateDict

  2. Then, tell Git what the updateDictfilter does on smudge(git checkout) and clean(git add):

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

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

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

    novel.txt filter=updateDict

  2. 然后,告诉 GitupdateDict过滤器对smudge(git checkout) 和clean(git add) 的作用:

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

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