Git 挂钩可以自动将文件添加到提交吗?
我想使用 Git 中的提交前或提交后挂钩将自动生成的文件添加到同一提交中,具体取决于该提交中修改的文件。我该怎么办呢?
我已经尝试将此作为预提交挂钩,但没有运气:
#!/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
这成功地将它们添加到存储库,但没有将它们添加到提交。我还尝试在提交后挂钩中使用最后两行执行代码以及提交前检查,但也没有什么好处。
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?
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
可以使用预提交挂钩来做你想做的事情。我们对heroku 部署做了类似的事情(将coffeescript 编译为javascript)。您的脚本无法运行的原因是您不正确地使用了
exec
命令。从 手册页:
仅您的第一个 exec 命令正在运行。之后你的脚本基本上就终止了。
尝试这样的事情(作为预提交挂钩):
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
exec
command improperly.From the man page:
Only your first exec command is running. After that your script is basically terminated.
Give something like this a try (as a pre-commit hook):
这对我来说效果很好。
它将成为当前提交的一部分。
git 版本 1.7.12.4 (Apple Git-37)
This worked just fine for me.
It will be part of the current commit.
git version 1.7.12.4 (Apple Git-37)
您可以结合使用提交前脚本和提交后脚本。
在预提交中:
.commit
或其他内容。 (请务必将其添加到.gitignore
)在提交后:
如果 .commit 存在,您就知道提交刚刚发生,但提交后尚未运行。因此,您可以在这里生成代码。此外,测试
.commit
以及它是否存在:commit --amend -C HEAD --no-verify
(避免循环).commit
文件这大致是我用来将
.metadata
文件存储在从 Metastore 生成的存储库中的过程。如果有人知道更好的方法,我会洗耳恭听,但现在似乎有效。
You could use a combination of a pre and post commit script.
In the pre-commit:
.commit
or something. (be sure to add this to.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 --amend -C HEAD --no-verify
(avoid looping).commit
fileThis is roughly the process I use to store a
.metadata
file in the repository generated from metastore.If anyone knows a better way I'm all ears but it seems to work for now.
您可以使用
update-index
:git update-index --add my_files
You can use
update-index
:git update-index --add my_files
编写一个
post-commit
脚本来生成您的文件,然后让那个做(类似的事情)git add my_files;怎么样? git commit --amend
。How about writing a
post-commit
script instead which generates your files, and then have that do (something along the lines of)git add my_files; git commit --amend
.我有同样的需求,这种方法对我来说效果很好:
其中“create_my_files”应该是可执行的,例如,如果它是一个python文件,你可以将其执行为“python create_my_files && git add my_files”,
这是真的不需要预先提交来再次提交(这会创建一个无限讨厌的循环:p)
I had the same need and this approach worked pretty well for me:
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"
and is true you don't need a pre-commit to commit again (that would create a infinite nasty loop :p)
如果文件是自动生成的,并且它们可以在任何地方生成(隐含在您希望在 Git 预提交挂钩中构建它们的愿望),那么您就不应该首先将它们置于源代码控制之下。您应该只控制源文件——生成的文件应该作为构建脚本的一部分生成。
将生成的文件置于源代码控制之下的唯一原因是当它需要唯一/特权资源来生成(例如许可程序)或需要大量时间来生成时。
添加
来自http://git-scm.com/docs/githooks:
预提交挂钩的目的是在提交之前对工作区的状态和提交的内容进行通过/失败检查。尝试更改提交的内容是行不通的。
我的建议是在构建脚本中添加两个步骤:(1)一个步骤将构建所有需要生成的过时文件(并将它们添加到工作区),以及(2)一个步骤将检查以确保所有生成的文件都是最新的,并返回非零状态代码。您的 Git 预提交挂钩应该运行第二步。您的开发人员应该接受培训以根据需要运行第一步。
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.
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 :
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.
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.
是的,您可以使用 git hooks 在提交上自动添加生成的文件!但这需要一个棘手的脚本。
在这里你可以发现问题已解决。在那里,它会在每次提交时更新文件版本,添加新的修改文件并根据需要修改提交。它正在全面工作:
https://github.com/evandrocoan/.versioning
然后你只需替换 '版本文件替换' ' 文件'updateVersion.sh'上的算法,按照您的算法。也许您需要更改一些内容,例如删除分支限制,因为只有在“开发”分支上时脚本才会运行。
此外,它只会更改指定的文件(如果已暂存)。如果文件没有暂存,那么它除了正常/通常的提交之外什么也不做。更准确地说,它打印出每一步正在做什么。
我要解释一下这个技巧。这是相当棘手的。在prepare-commit-msg-hook上,它检测所需的文件是否正在暂存和提交。之后,它创建一个标志文件,并停止prepare-commit-msg-hook。
稍后在 post-commit-hook 中,它会检查标志文件是否存在。如果是,它会修改提交上的文件。
注意,它会创建一个无限循环,因为它会再次调用prepare-commit-msg-hook(正如我们正在修改的那样)。但由于标志文件的原因,这种情况不会发生。当prepare-commit-msg-hook运行并找到标志文件时,它“知道”发生了什么。然后就是删除标志文件,不再创建它。这样做,它将阻止 post-commit-hook 再次修改提交,从而允许提交永久完成。
Yes, you can add generated files automatically on the commit using git hooks! But it requires a tricky script.
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
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.
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.
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.
想象一下,您有一个预提交钩子可以执行此操作:
当且仅当已经有需要提交的内容时,它才会起作用。它不一定是同一个文件。如果没有需要提交的内容, git add
git add file
将起作用,但不会提交。有效的示例:
gitignore
)pre-commit
挂钩将运行并创建file
。然后它就会提交。file
已提交。git status
现在输出:不起作用的示例
git status
给出:文件
。但提交消息显示他什么也没做。git status
我尝试将其添加为
post-commit
挂钩,但没有成功。如果有人知道解决此问题的方法,我很想知道。Imagine you have a pre-commit hook that does this:
It will work IF AND ONLY IF, there was already something to be commited. It does not have to be the same file tho. If there was nothing to be commited, the git add
git add file
will work, but will not be commited.Example that works:
gitignore
)pre-commit
hook will run and createfile
. Then it will commit.file
was commited. Andgit status
now outputs:Example that DOES NOT work
git add
but it will do nothing.git status
gives:file
. But the commit message says he did nothing.git status
git commit
again for it to work.I tried adding that as a
post-commit
hook but got no luck. If someone knows a fix for this case, I would love to know.我在预提交挂钩中也遇到了同样的问题。我正在修改一个文件并提交,但它使用的是前一个文件而不是更新的文件,因此通过在预提交挂钩中添加 git 命令(如下),它解决了。
注意:
$file
是您要添加的文件。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.
note:
$file
is your file to be added.由于 git add 在预提交中也不适用于我,因此我遵循了 mark 的想法,即使用 .commit 文件并将该过程分为提交前和提交后。
应该很容易理解的代码
下面是一些在预提交中
在提交后:
希望这能让那些 bash 知识很少的人更容易遵循 mark 的想法。
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.
Here is some code that should be easy to understand
In the pre-commit:
In the post-commit:
Hope this makes it easier for people with few bash knowledge to follow mark's idea.