即使我没有新的提交提示,如何强制git
在服务器上运行post-receive
挂钩?
我使用git自动将网站部署到服务器。我在服务器的受保护区域中有一个简单的repo和一个post-receive
挂钩,它检查内容并系统地将某些文件复制到public_html
文件夹中。 (灵感来自this tutorial)
我厌倦了在服务器上手动修改post-receive
挂钩,所以我的post-receive
挂钩现在实际上从回购中复制了自己的新版本:
#!/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
问题当然是新的post-receive
挂钩永远不会运行。一个看似简单的解决方案只是再次推动,但现在一切都已经是最新的。这很烦人,因为每次我更新post-receive
挂钩时都要求我伪造一个新的提交。有没有办法在不伪造提交或post-receive
的情况下调用ssh
挂钩?
git push
git push -f
答案 0 :(得分:53)
在初始推送替换脚本后,您可以执行以下操作:
git commit --allow-empty -m 'push to execute post-receive'
--allow-empty
标志会覆盖git的默认行为,即在没有更改时阻止您进行提交。
使用别名让您的生活更轻松
将以下内容添加到~/.gitconfig
[alias]
pushpr = "!f() { git push origin master;git commit --allow-empty -m 'push to execute post-receive';git push origin master; }; f"
现在就做git pushpr
git pushpr
这会将任何更改推送到master,在您的情况下将触发您的post post replacement脚本,然后它将再次推送(使用--allow-empty
标志),然后执行更新的post-receive
脚本
答案 1 :(得分:22)
我知道这可能会被认为是"危险"但我喜欢生活在边缘。
我只是删除了远程分支,然后再次推送它。确保您的本地分支机构是最新的,以限制丢失东西的可能性。
因此,如果我想触发post-receive,在我的情况下要让测试分支进行配置,我所做的就是:
$ git push origin :testing
$ git push origin testing
但是,不要接受这个作为答案。它更像是一个公平的事情。
答案 2 :(得分:13)
我担心你必须ssh到服务器并手动运行钩子脚本。如果没有任何内容,git push
不会使服务器运行预推送,预接收和收件后挂钩添加(即当git打印一切都是最新的)。
答案的其余部分是关于跟踪 post-receive 挂钩的版本,因此您可以修改它而无需sshing到服务器。
将名为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'
将服务器上的hooks/post-receive
挂钩替换为:
#! /bin/sh
while read OLDID NEWID BRANCH; do
test "$BRANCH" = refs/heads/master && eval "$(git show master:do-post-receive)"
done
(确保服务器上有chmod 755 hooks/post-receive
。)
将更改从本地存储库推送到服务器,并观察do-post-receive
代码运行:
$ git push origin master
...
remote: Hello, World!
...
答案 3 :(得分:10)
如果您想避免伪造新提交,只需使用
即可git commit --amend --no-edit
这将修改最后一次提交记录,您将能够使用git push -f
(假设您的回答是“你对覆盖很好”。)
我在推送之前相对经常使用此命令来修复上次提交中的内容,因此我为它创建了一个别名:
git config --global alias.amend 'commit --amend --no-edit'
现在我可以直接将它用作您的用例(git amend
)或
git amend -a
git amend -m 'better message'
答案 4 :(得分:3)
我尝试了empty commits和delete upload branch。
但是直接的ssh命令怎么样:
ssh your_host /path/to/your_repo/hooks/post-receive
答案 5 :(得分:2)
接收后是人工命令响应的错误位置。
你希望你的服务器端好东西在预接收出口,取决于更新的参考 - 例如, git update-ref refs/commands/update-hooks @
在服务器上,然后您可以例如git push server +@:commands/update-hooks
,并且在服务器的预收款中,您可以
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
答案 6 :(得分:1)
我喜欢Jamie Carl的建议,但它不起作用,我收到了错误:
remote:错误:默认情况下,拒绝删除当前分支,因为下一个错误:'git clone'不会导致任何文件签出,导致混淆。
在我的情况下,我正在测试我的localhost上的post-receive钩子对着裸存储库。警告/非常重要,请在 remote
服务器位置上运行此命令 !
git update-ref -d refs/heads/develop
它将删除开发分支的引用(您可能还需要删除为该分支部署的任何文件),然后您可以继续执行git push deploy_localtest develop
或任何推送命令想要那个分支。
答案 7 :(得分:0)
在我的情况下,我登录到远程并运行:
$ sh project.git/hooks/post-receive
工作正常!
答案 8 :(得分:0)
我做了一个bash函数来做到这一点。它假设您有ssh访问权限,~/.ssh/config
可以相应地设置。默认遥控器是原点
kick-git() {
remote="${1:-origin}"
ssh $(echo $(git remote get-url "$remote")/hooks/post-receive | tr ':' ' ')
}
来源并运行kick-git [remote]