强制 git 运行 post-receive hook,即使一切都是“最新的”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13677125/
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
Force git to run post-receive hook, even if everything is "up-to-date"
提问by AndyL
How do I force git
to run a post-receive
hook on a server even if I don't have a new commit to push?
即使我没有要推送的新提交,如何强制在服务器上git
运行post-receive
挂钩?
Background
背景
I use git to automatically deploy a website to a server. I have a bare repo in a protected area of the server and a post-receive
hook that checks out the contents and systematically copies over certain files into a public_html
folder. (Inspired by this tutorial)
我使用 git 自动将网站部署到服务器。我在服务器的受保护区域有一个裸仓库和一个post-receive
钩子,用于检查内容并系统地将某些文件复制到public_html
文件夹中。(受本教程启发)
I got tired of modifying the post-receive
hook manually on the server, so my post-receive
hook now actually copies over a new version of itself from the repo:
我厌倦了post-receive
在服务器上手动修改钩子,所以我的post-receive
钩子现在实际上从 repo 复制了一个新版本:
#!/bin/sh
rm -rf ~/../protected/*
GIT_WORK_TREE=~/../protected git checkout -f
# Rewrite over this file with any updates from the post-receive file
cp ~/../protected/post-receive hooks/post-receive
# Delete public_html
# Copy stuff public_html
The problem, of course, is that the new post-receive
hook never gets run. A seemingly simple solution would be merely to push again, but now everything is already up to date. This is annoying, because it requires me to fake a new commit every time I update the post-receive
hook. Is there a way to invoke the post-receive
hook without faking a commit or ssh
ing in?
当然,问题是新post-receive
钩子永远不会运行。一个看似简单的解决方案只是再次推送,但现在一切都已经是最新的。这很烦人,因为每次更新post-receive
钩子时都需要我伪造一个新的提交。有没有办法在post-receive
不伪造提交或ssh
输入的情况下调用钩子?
What I tried
我试过的
git push
git push -f
回答by AndrewD
Use '--allow-empty'
使用'--allow-empty'
After the initial push replacing the script, you can do this :
在初始推送替换脚本后,您可以执行以下操作:
git commit --allow-empty -m 'push to execute post-receive'
The --allow-empty
flag overrides git's default behavior of preventing you from making a commit when there are no changes.
该--allow-empty
标志会覆盖 git 的默认行为,即在没有更改时阻止您进行提交。
Use an alias and make your life even easier
使用别名让您的生活更轻松
Add the following to ~/.gitconfig
将以下内容添加到 ~/.gitconfig
[alias]
pushpr = "!f() { git push origin master;git commit --allow-empty -m 'push to execute post-receive';git push origin master; }; f"
Now Just do git pushpr
现在就做 git pushpr
git pushpr
This will push any changes to master, which in your case will trigger your post receive replacement script, then it will push again (using the --allow-empty
flag) which will then execute your updated post-receive
script.
这会将任何更改推送到 master,在您的情况下,这将触发您的 post 接收替换脚本,然后它会再次推送(使用--allow-empty
标志),然后执行您更新的post-receive
脚本。
回答by Jamie Carl
I know this probably going to be considered "dangerous" but I like to live on the edge.
我知道这可能会被认为是“危险的”,但我喜欢生活在边缘。
I just delete the remote branch and then push it again. Make sure your local branch is up-to-date first to limit the chance of losing stuff.
我只是删除远程分支,然后再次推送它。首先确保您当地的分支机构是最新的,以减少丢失东西的机会。
So if I want to trigger post-receive, in my case to get the testing branch to provision, all I do is:
因此,如果我想触发 post-receive,就我而言,要让测试分支进行配置,我所做的就是:
$ git push origin :testing
$ git push origin testing
Don't accept this as the answer though. It's more of a just FYI thing.
不要接受这个作为答案。这更像是一个仅供参考的事情。
回答by pts
I'm afraid you have to ssh to the server and run the hook script manually. git push
doesn't make the server run the pre-push, pre-receiveand post-receivehooks if there was nothing added (i.e. when git prints Everything up-to-date).
恐怕您必须通过 ssh 连接到服务器并手动运行挂钩脚本。如果没有添加任何内容(即当 git 打印Everything up-to-date 时)git push
,不会让服务器运行pre-push、pre-receive和post-receive钩子。
The rest of the answer is about version-tracking the post-receivehook, so you can modify it without sshing to the server.
答案的其余部分是关于对post-receive挂钩进行版本跟踪,因此您可以在不通过 SSH 连接到服务器的情况下对其进行修改。
Add a shell script named do-post-receive
to the local repository:
添加一个命名do-post-receive
到本地存储库的 shell 脚本:
$ ls -ld .git
$ echo 'echo "Hello, World!"' >do-post-receive
$ git add do-post-receive
$ git commit do-post-receive -m 'added do-post-receive'
Replace your hooks/post-receive
hook on the server with:
将hooks/post-receive
服务器上的钩子替换为:
#! /bin/sh
while read OLDID NEWID BRANCH; do
test "$BRANCH" = refs/heads/master && eval "$(git show master:do-post-receive)"
done
(Make sure to chmod 755 hooks/post-receive
on the server.)
(确保chmod 755 hooks/post-receive
在服务器上。)
Push your changes from the local repository to the server, and watch your do-post-receive
code run:
将您的更改从本地存储库推送到服务器,并观察您的do-post-receive
代码运行:
$ git push origin master
...
remote: Hello, World!
...
回答by laughedelic
If you want to avoid making a fake newcommit, you can simply use
如果你想避免进行虚假的新提交,你可以简单地使用
git commit --amend --no-edit
This will modify the last commit record and you will be able to use git push -f
(assuming from your answer that you're fine with the overwrite).
这将修改最后一个提交记录,您将能够使用git push -f
(假设从您的回答中您可以接受覆盖)。
- convenient:it doesn't create an extra commit
- good:it doesn't use explicit path for the hook in the remote repo
- bad:you overwrite history, which is fine in your use case, but shouldn't be used in a shared repository
- 方便:它不会创建额外的提交
- 好:它没有为远程仓库中的钩子使用显式路径
- 不好:您覆盖历史记录,这在您的用例中很好,但不应在共享存储库中使用
I use this command relatively often to fix something in the last commit before pushing, so I made an alias for it:
我相对经常使用这个命令来在推送之前修复最后一次提交中的某些内容,所以我为它创建了一个别名:
git config --global alias.amend 'commit --amend --no-edit'
Now I can use it directly for the use case as yours (git amend
), or
现在我可以像你一样直接将它用于用例(git amend
),或者
- to add (all) modified files to the last commit:
git amend -a
- to modify the message:
git amend -m 'better message'
- 将(所有)修改过的文件添加到最后一次提交:
git amend -a
- 修改消息:
git amend -m 'better message'
回答by sites
I tried empty commitsand delete upload branch.
But what about a direct ssh command:
但是直接 ssh 命令呢:
ssh your_host /path/to/your_repo/hooks/post-receive
回答by jthill
Post-receive is the wrong place for artificial command responses.
接收后是人工命令响应的错误位置。
You want your server-side goodies in the pre-receive exit, dependent on the updated ref -- do e.g. git update-ref refs/commands/update-hooks @
on the server, then you can e.g. git push server +@:commands/update-hooks
, and in the server's pre-receive you can
你希望你的服务器端好东西在 pre-receive 出口中,取决于更新的 ref——git update-ref refs/commands/update-hooks @
在服务器上做,然后你可以 eg git push server +@:commands/update-hooks
,在服务器的 pre-receive 中你可以
while read old new ref; do case $ref in
commands/update-hooks)
maybe check the incoming commit for authorization
update hooks here
echo the results from the update
denypush=1
;;
refs/heads/master)
extreme vetting on master-branch updates here
;;
esac; done
((denypush)) && exit $denypush
回答by Bryce Guinta
I made a bash function to do this. It assumes that you have ssh access can ~/.ssh/config
set accordingly. The default remote is origin
我做了一个 bash 函数来做到这一点。它假定您具有 ssh 访问权限,可以~/.ssh/config
相应地进行设置。默认遥控器是 origin
kick-git() {
remote="${1:-origin}"
ssh $(echo $(git remote get-url "$remote")/hooks/post-receive | tr ':' ' ')
}
Source and run kick-git [remote]
来源和运行 kick-git [remote]
回答by Clay
I like Jamie Carl's suggestion but it doesn't work, and I got the error:
我喜欢杰米卡尔的建议,但它不起作用,我得到了错误:
remote: error: By default, deleting the current branch is denied, because the next error: 'git clone' won't result in any file checked out, causing confusion.
remote: error: 默认情况下,删除当前分支是被拒绝的,因为下一个错误: 'git clone' 不会导致任何文件被检出,造成混乱。
In my case I'm testing post-receive hooks on my localhost against a bare repository. Warning/super important, run this command onlyon the remote
server location!
就我而言,我正在本地主机上针对裸存储库测试接收后挂钩。警告/超级重要,仅在remote
服务器位置运行此命令!
git update-ref -d refs/heads/develop
It'll delete the reference for the develop branch (you may also need to delete any of the files you deployed for that branch too), then you can go ahead and do the git push deploy_localtest develop
or whatever push command you want for that branch.
它将删除开发分支的引用(您可能还需要删除为该分支部署的任何文件),然后您可以继续为该分支执行git push deploy_localtest develop
或执行您想要的任何推送命令。
回答by Cosme Marins
In my case i login into remote and run:
就我而言,我登录远程并运行:
$ sh project.git/hooks/post-receive
$ sh project.git/hooks/post-receive
works fine!
工作正常!