Git:自动从代码仓库拉取代码的方法?

118

有没有办法设置Git监听远程仓库的更新,并在有变更时拉取更新?我的需求是使用Git部署Web应用(这样我就可以对已部署应用进行版本控制),但我希望将“中央”Git仓库放在GitHub上,而不是Web服务器上(因为GitHub的界面真心好看)。

有人做过类似的事情吗?Heroku是如何实现的?我的谷歌搜索失败了,没有给我任何相关的结果。

6个回答

64

Git有“钩子”功能,可以在其他操作后执行。你似乎正在寻找的是“post-receive hook”。在github管理界面中,您可以设置一个post-receive url,每当有人向您的存储库推送内容时,它将被访问(携带有关刚刚推送内容的数据负载)。

就我个人而言,我认为自动拉取不是一个好主意——如果错误的内容被推送到您的分支,会发生什么情况?我建议使用像capistrano(或类似工具)这样的工具来处理这些事情。


19
我计划的用法是在开发的“测试和玩弄”阶段有一个单独的代码库/分支,并且有一个特殊的“推送到生产”代码库,只有当我确定一切都正常工作时才进行推送。我基本上使用Git来完成rsync可以做的事情,只是它会记录部署的所有版本,我很容易就能恢复到之前的版本。与像capistrano这样更高级的工具相比的优势在于(目前)这是一个非常小的项目,我不必学习一个全新的工具。 - Li Haoyi
Webhook(网络钩子)身份验证增加了额外的安全问题和复杂性,因此拉(pull)式解决方案仍然具有其优势。发布版本控制可以使用标签来避免意外部署。 - lz96
我认为这对于团队开发很有好处。 - DoctorHe

28

在类Unix系统上,您可以创建一个cron工作,以调用您的机器上的 "git pull"(每天或每周或任何其他时间)。在Windows上,您可以使用任务计划程序或“AT”命令执行相同的操作。


5
不是使用Git的正确方式。 - deepdive
37
为什么不呢?想象一下,如果你在家里有一台树莓派 (Raspberry Pi),但没有静态 IP 地址可用,除了运行 cron 或 runwhen 作业之外,你还有哪些选择? - kaiser
5
不是个好主意。他希望在推送后立即应用更改。 - Alex Coroza
17
OP特别要求一种方法,可以监听来自远程仓库的更新,并在每次有更改时拉取。这种解决方案只会定期从仓库拉取,因此为了使其有效,间隔时间必须非常短,导致大量冗余的拉取请求。 - Boaz
6
一种不用更改cron tab的快速方法是:while true; do git pull; sleep 10; done。这将每隔10秒执行一次git pull操作。 - JakeD
显示剩余4条评论

3

有一些持续集成程序,如Jenkins或Bamboo,它们可以检测提交并触发构建、测试、打包和部署等操作。它们可以满足你的需求,但是它们依赖重,配置难度大,最终可能会对git仓库进行周期性检查,这与通过cron每分钟调用git pull具有相同的效果。


1

正如一些人在尝试后注意到的那样,如果您使用php exec(),解决权限问题并不简单。

执行命令的用户可能不是您自己,而是www-dataapache

如果您拥有root/sudo访问权限,我建议您阅读这篇Jonathan的博客文章

当您没有被允许/无法解决权限问题时

我的解决方案有点创意。我注意到我可以使用循环在我的用户名下创建一个脚本,然后git pull就可以正常工作。但是,正如其他人指出的那样,这带来了运行大量无用git pull的问题,比如每60秒运行一次。

因此,以下是使用webhooks更为精细的解决方案步骤:

  • 部署密钥:前往您的服务器并键入:ssh-keygen -t rsa -b 4096 -C“deploy”以生成新的部署密钥,不需要写入权限(只读更安全)。将公钥复制到您的 GitHub 存储库设置中,在“部署密钥”下方。
  • Webhook:前往您的存储库设置并创建 Webhook。假设有效载荷地址为:http://example.com/gitpull.php
  • 有效载荷:创建一个包含以下代码示例的 PHP 文件。有效载荷的目的不是进行git pull,而是提醒以下脚本需要进行pull。这里是简单代码:

gitpull.php:

<?php

/* Deploy (C) by DrBeco 2021-06-08 */

echo("<br />\n");
chdir('/home/user/www/example.com/repository'); 
touch(GITPULLMASTER);
?>
  • 脚本:在您喜欢的文件夹中创建一个脚本,比如说/home/user/gitpull.sh,并使用以下代码:

gitpull.sh

#!/bin/bash

cd /home/user/www/example.com/repository
while true ; do
      if [[ -f GITPULLMASTER ]] ; then
            git pull > gitpull.log 2>&1
            mv GITPULLMASTER GITPULLMASTER.`date +"%Y%m%d%H%M%S"`
      fi
      sleep 10
done
  • 分离:最后一步是以分离模式运行脚本,这样您可以注销并在后台继续运行脚本。

有两种方法可以实现这个目的,第一种比较简单,不需要安装 screen 软件:

  • disown:

    • 运行./gitpull.sh &将其放入后台
    • 然后键入disown -h %1进行分离,然后您可以注销
  • screen:

    • 运行screen
    • 运行./gitpull.sh
    • 键入control+a d进行分离,然后您可以注销

结论

这个解决方案很简单,您可以避免处理密钥、密码、权限、sudo、root 等问题,还可以防止脚本向服务器发送无用的 git pull 命令。

它的工作方式是检查文件GITPULLMASTER是否存在;如果不存在,则继续睡觉。只有当它存在时,才执行git pull

您可以更改以下行:

mv GITPULLMASTER GITPULLMASTER.date +"%Y%m%d%H%M%S"`

rm GITPULLMASTER

如果您喜欢一个更清洁的目录结构。但是我发现让拉取日期注册(且未跟踪)对调试很有用。


0
对于我们的本地 Windows 测试服务器,我们使用 Windows 任务计划程序任务,设置为每 3 分钟运行一次,从 Bitbucket Cloud 拉取到那些服务器上的存储库。虽然不是即时的,但它满足我们的需求,并被证明是可靠的。

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接