Git 钩子可以自动将文件添加到提交中吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3284292/
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-10 08:46:09  来源:igfitidea点击:

Can a Git hook automatically add files to the commit?

gitpre-commit-hookgithookspre-commit

提问by Ian Terrell

I'd like to add an automatically generated file to the same commit using a pre- or post-commit hook in Git, dependent on the files that were modified in that commit. How would I go about this?

我想使用 Git 中的提交前或提交后挂钩将自动生成的文件添加到同一提交中,具体取决于在该提交中修改的文件。我该怎么办?

I've tried this as a pre-commit hook, but no luck:

我试过这个作为预提交钩子,但没有运气:

#!/bin/sh
files=`git diff --cached --name-status`
re="<files of importance>"
if [[ $files =~ $re ]]
then
  echo "Creating files"
  exec bundle exec create_my_files
  exec git add my_files
  exec git commit --amend -C HEAD
fi

This successfully adds them to the repository, but does not add them to the commit. I've also tried using the last two exec lines in a post-commit hook along with the pre-commit inspection, but no good either.

这成功地将它们添加到存储库,但不会将它们添加到提交中。我还尝试在提交后挂钩中使用最后两个 exec 行以及提交前检查,但也没有好处。

回答by bitluck

Since git add was also not working for me in a pre commit, I followed mark's idea of using a .commit file and splitting the process into pre- and post-commit.

由于 git add 在预提交中也不适用于我,我遵循了 mark 的想法,即使用 .commit 文件并将过程分为提交前和提交后。

Here is some code that should be easy to understand

下面是一些应该很容易理解的代码

In the pre-commit:

在预提交中:

  • Touch a file .commit or something. (be sure to add this to .gitignore)
  • 触摸一个文件 .commit 什么的。(一定要将此添加到 .gitignore)
#!/bin/sh 
echo 
touch .commit 
exit

In the post-commit:

在提交后:

if .commit exists you know a commit has just taken place but a post-commit hasn't run yet. So, you can do your code generation here. Additionally, test for .commit and if it exists:

  • add the files
  • commit --amend -C HEAD --no-verify (avoid looping)
  • delete .commit file

如果 .commit 存在,你就知道一个提交刚刚发生,但是一个 post-commit 还没有运行。因此,您可以在此处生成代码。此外,测试 .commit 以及它是否存在:

  • 添加文件
  • commit --amend -C HEAD --no-verify(避免循环)
  • 删除 .commit 文件
#!/bin/sh
echo
if [ -e .commit ]
    then
    rm .commit
    git add yourfile
    git commit --amend -C HEAD --no-verify
fi
exit

Hope this makes it easier for people with few bash knowledge to follow mark's idea.

希望这能让几乎没有 bash 知识的人更容易遵循马克的想法。

回答by Jim Garvin

It's possible to do what you want using pre-commit hooks. We do something similar for a heroku deployment (compiling coffeescript to javascript). The reason your script isn't working is because you used the execcommand improperly.

使用预提交钩子可以做你想做的事。我们为 heroku 部署做了类似的事情(将 coffeescript 编译为 javascript)。您的脚本无法正常工作的原因是您未exec正确使用该命令。

From the man page:

手册页

The exec builtin is used to replace the currently running shells process image with a new command. On successful completion, exec never returns. exec can not be used inside a pipeline.

exec 内置命令用于用新命令替换当前运行的 shell 进程映像。成功完成后, exec 永远不会返回。exec 不能在管道内使用。

Only your first exec command is running. After that your script is basically terminated.

只有您的第一个 exec 命令正在运行。之后,您的脚本基本上终止了。

Give something like this a try (as a pre-commit hook):

尝试这样的事情(作为预提交钩子):

#!/bin/sh
files=`git diff --cached --name-status`
re="<files of importance>"
if [[ $files =~ $re ]]
then
  echo "Creating files"
  bundle exec create_my_files
  git add my_files
fi

回答by Mark

You could use a combination of a pre and post commit script.

您可以结合使用提交前和提交后脚本。

In the pre-commit:

在预提交中:

  • Touch a file .commit or something. (be sure to add this to .gitignore)
  • 触摸一个文件 .commit 什么的。(一定要将此添加到 .gitignore)

In the post-commit:

在提交后:

if .commit exists you know a commit has just taken place but a post-commit hasn't run yet. So, you can do your code generation here. Additionally, test for .commit and if it exists:

如果 .commit 存在,你就知道一个提交刚刚发生,但是一个 post-commit 还没有运行。因此,您可以在此处生成代码。此外,测试 .commit 以及它是否存在:

  • add the files
  • commit --ammend -C HEAD --no-verify (avoid looping)
  • delete .commit file
  • 添加文件
  • commit --ammend -C HEAD --no-verify(避免循环)
  • 删除 .commit 文件

This is roughly the process I use to store a .metadata file in the repository generated from metastore.

这大致是我用来在从 Metastore 生成的存储库中存储 .metadata 文件的过程。

If anyone knows a better way I'm all ears but it seems to work for now.

如果有人知道更好的方法,我会全力以赴,但现在似乎可行。

回答by rfunduk

You can use update-index:

您可以使用update-index

git update-index --add my_files

git update-index --add my_files

回答by calimarkus

#!/bin/sh
#
#  .git/hooks/pre-commit
#

git add file.xyz

This worked just fine for me. It will be part of the current commit.

这对我来说很好。它将成为当前提交的一部分。

git version 1.7.12.4 (Apple Git-37)

git version 1.7.12.4 (Apple Git-37)

回答by Craig Trader

If the files are automatically generated, and they can be generated anywhere (implicit in your desire to build them in the Git pre-commit hook) then you shouldn't be putting them under source control in the first place. You should only control source files -- generated files should be generated as part of the build scripts.

如果文件是自动生成的,并且可以在任何地方生成(暗示您希望在 Git 预提交挂钩中构建它们),那么您首先不应该将它们置于源代码控制之下。您应该只控制源文件——生成的文件应该作为构建脚本的一部分生成。

The only reason to put a generated file under source control is when it requires unique/privileged resources to generate (such as a licensed program) or it requires a significant amount of time to generate.

将生成的文件置于源代码控制之下的唯一原因是它需要独特/特权资源来生成(例如许可程序),或者需要大量时间来生成。

Added

添加

From http://git-scm.com/docs/githooks:

http://git-scm.com/docs/githooks

pre-commitThis hook is invoked by git commit, and can be bypassed with --no-verify option. It takes no parameter, and is invoked before obtaining the proposed commit log message and making a commit. Exiting with non-zero status from this script causes the git commit to abort.

The default pre-commit hook, when enabled, catches introduction of lines with trailing whitespaces and aborts the commit when such a line is found.

All the git commit hooks are invoked with the environment variable GIT_EDITOR=: if the command will not bring up an editor to modify the commit message.

pre-commit这个钩子由 git commit 调用,可以通过 --no-verify 选项绕过。它不接受任何参数,并且在获取建议的提交日志消息并进行提交之前被调用。从此脚本以非零状态退出会导致 git commit 中止。

默认的 pre-commit 钩子在启用时,会捕获带有尾随空格的行的引入,并在找到这样的行时中止提交。

所有 git commit 挂钩都使用环境变量 GIT_EDITOR= 调用:如果该命令不会打开编辑器来修改提交消息。

The intent of the pre-commit hook is to be a pass-fail check on the state of the workspace and the contents of the commit, prior to making the commit. Attempting to change the contents of the commit won't work.

pre-commit 钩子的目的是在提交之前对工作区的状态和提交的内容进行通过-失败检查。尝试更改提交的内容是行不通的。

My recommendation would be add two steps to your build scripts: (1) a step that will build all of the out-of-date files that needs to be generated (and adds them to the workspace), and (2) a step that will check to ensure that all of the generated files are up-to-date, and return a non-zero status code. Your Git pre-commit hook should run the second step. Your developers should be trained to run the first step as necessary.

我的建议是在您的构建脚本中添加两个步骤:(1) 构建所有需要生成的过时文件的步骤(并将它们添加到工作区),以及 (2) 一个步骤将检查以确保所有生成的文件都是最新的,并返回非零状态代码。你的 Git 预提交钩子应该运行第二步。您的开发人员应该接受必要的培训以运行第一步。

回答by rfunduk

How about writing a post-commitscript instead which generates your files, and then have thatdo (something along the lines of) git add my_files; git commit --amend.

如何写一个post-commit脚本,而不是生成的文件,然后让做的(沿东西线)git add my_files; git commit --amend

回答by user

Yes, you can add generated files automatically on the commit using git hooks! But it requires a tricky script.

是的,您可以使用 git hooks 在提交时自动添加生成的文件!但它需要一个棘手的脚本。

Here you can find the problem solved. There, it is updating the file version on every commit, adding a new modified file and amending the commit as you need it to. It is fully working: https://github.com/evandrocoan/.versioning

在这里你可以找到解决的问题。在那里,它会在每次提交时更新文件版本,添加一个新的修改文件并根据需要修改提交。它完全正常工作:https: //github.com/evandrocoan/.versioning

Then you just replace the 'Version File Replacement' algorithm on the file 'updateVersion.sh', by your algorithm. Maybe you need to change a few things like, remove the branch limitation, because there, the script only runs if you are on the 'develop' branch.

然后你只需用你的算法替换文件“updateVersion.sh”上的“版本文件替换”算法。也许您需要更改一些内容,例如删除分支限制,因为在那里,脚本仅在您位于“开发”分支时运行。

Also, it will only change the specified file, if is staged. If the file is not staged, then it will do nothing than the normal/usual commit. More precisely, it print out what it is doing on every step.

此外,如果已暂存,它只会更改指定的文件。如果文件没有暂存,那么它除了正常/通常的提交之外什么都不做。更准确地说,它打印出每一步都在做什么。

I am going to explain, that trick. It is quite tricky. On the prepare-commit-msg-hook, it detects whether the desired file is being staged and committed. After that, it creates a flag file, and stops the prepare-commit-msg-hook. Later on the post-commit-hook, it checks whether the flag file exists. If yes, it amends the files on the commit.

我要解释一下,那个把戏。这很棘手。在 prepare-commit-msg-hook 上,它检测是否正在暂存和提交所需的文件。之后,它会创建一个标志文件,并停止 prepare-commit-msg-hook。稍后在 post-commit-hook 上,它会检查标志文件是否存在。如果是,它会修改提交中的文件。

Attention, it would create a infinity loop because it would call again the prepare-commit-msg-hook (as we are amending). But it does not happen because of the flag file. When the prepare-commit-msg-hook runs and find the flag file, it "knows" what is happening. Then is just deletes the flag file and do not create it again. Doing it, it will block the post-commit-hook from amending again the commits, allowing the commit to finish for good.

注意,它会创建一个无限循环,因为它会再次调用 prepare-commit-msg-hook(我们正在修改)。但由于标志文件,它不会发生。当 prepare-commit-msg-hook 运行并找到标志文件时,它“知道”发生了什么。然后只是删除标志文件,不要再次创建它。这样做,它将阻止 post-commit-hook 再次修改提交,从而使提交永远完成。

回答by Hassek

I had the same need and this approach worked pretty well for me:

我有同样的需求,这种方法对我来说效果很好:

#!/bin/sh
files='git diff --cached --name-only'
re="<files of importance>"
if [[ $files =~ $re ]]
then
   echo "Creating files"
   create_my_files && git add my_files
fi

where "create_my_files" should be executable, for example if it is a python file you could execute it as "python create_my_files && git add my_files"

其中“create_my_files”应该是可执行的,例如,如果它是一个python文件,你可以将它作为“python create_my_files && git add my_files”来执行

and is true you don't need a pre-commit to commit again (that would create a infinite nasty loop :p)

确实,您不需要预先提交即可再次提交(这会造成无限讨厌的循环:p)

回答by Saroj Kumar Moharana

I was facing same problem in pre-commit hook also. I was modifying one file and committing but it was taking previous file not updated file so by adding git command(as below) in pre-commit hook, it solved.

我在预提交钩子中也面临同样的问题。我正在修改一个文件并提交,但它采用了以前的文件而不是更新的文件,因此通过在预提交挂钩中添加 git 命令(如下所示),它解决了。

git add $file

note: $fileis your file to be added.

注意:$file是您要添加的文件。

Thanks,

谢谢,