用 Git 钩子进行自动部署

Git 钩子

Git 钩子(hooks)是在 Git 仓库中特定事件(certain points)触发后被调用的脚本。通过钩子可以自定义 Git 内部的相关(如 git push)行为,在开发周期中的关键点触发自定义的行为。Git 含有两种类型的钩子:客户端的和服务器端的。客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。

Webhook1

Git 钩子最常见的使用场景包括根据仓库状态改变项目环境、接入持续集成工作流等。由于脚本是可以完全定制,所以你可以用 Git 钩子来自动化或者优化你开发工作流中任意部分。

在这篇文章中,我们会先简要介绍 Git 钩子相关要素,然后实例使用 Git 钩子进行博客自动部署。

Git 钩子安装

Git 钩子存在于每个 Git 仓库的 .git/hooks 目录中。 当你用 git init 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,不过,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python,或其它语言编写它们。

1
2
3
4
➜  hooks git:(master) ls
applypatch-msg.sample pre-applypatch.sample pre-rebase.sample
commit-msg.sample pre-commit.sample prepare-commit-msg.sample
post-update.sample pre-push.sample update.sample

.sample拓展名是为了防止它们默认被执行,安装一个钩子只需要去掉.sample拓展名即可。

Git 钩子的作用域

Git 钩子是对本地仓库相关操作影响,对于任何 Git 仓库来说钩子都是本地的,初始的钩子都是从 Git 默认模板目录中自动安装。

在开发团队中为了保持团队所使用钩子一致,维护起来算是比较复杂的,因为 .git/hooks 目录不随你的项目一起拷贝,也不受版本控制影响。

Webhook1

简单的解决办法是把钩子文件存放在项目的实际目录中(在.git 外),这样就可以像其他文件一样进行版本控制,然后在.git/hooks中创建一个链接,或者简单地在更新后把它们复制到.git/hooks目录下。

当我们了解了以上 Git 钩子基础知识后,下面我们来实例操作 Git 钩子进行博客自动部署。

Git 钩子进行自动部署

如何实现 Git 钩子进行自动部署,其实原理很简单,我们只需要监听每次本地 git push到远程服务器,然后远程服务器同步拉取最新文件,重启服务器即可(pm2 reload xx)。

Webhook1

1.在服务器初始化一个远程 Git 裸仓库 (git init –bare)

裸仓库与 git init 初使化的仓库不太一样,裸仓库其实相当于通过克隆来的仓库里的.git文件夹,整个裸仓库中只有git索引(index),不包含工作目录。要实现Push to Deploy,首先我们需要一个裸仓库。

1
2
3
4
5
6
7
git init --bare xxx-bare.git



mkdir xxx-bare.git
cd xxx-bare.git
git init --bare

post-update.sample去掉sample, 在里面增加执行脚本:

1
2
3
4
5
6
7
8
#!/bin/sh
#
DIR_ONE=/home/user/deploy-directory
#
cd $DIR_ONE
git clean -fd
#
git checkout --force

2.在服务器初始化一个本地 Git 仓库

deploy-directory目录 git init 初始化本地仓库,它的作用是拉去远程仓库最新的源码,然后在这个仓库里进行编译,把代码编译到 www 目录(网站的根目录)。

post-update.sample去掉sample, 在里面增加执行脚本

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
unset GIT_DIR
DeployPath=/home/user/Deploy
WwwPath=/home/wwwroot/Deploy
cd $DeployPath
git clean -f
git pull origin master

ath build WwwPath
#exec git-update-server-info

注意: 一定要unset GIT_DIR清除变量, 不然会引起remote: fatal: Not a git repository: '.'错误。

post-update添加执行权限:

1
chmod +x post-receive

3.本地仓库添加 remote 源

1
2
3
4
git init
git remote add origin user@1.2.3.4:/home/git/xxx-bare.git
//例如git remote add origin ssh://root@41.72.11.11:26244/home/www/BRIDGE_REPO.git
git push origin master

参考资料:

自定义 Git - Git 钩子
Git钩子:自定义你的工作流
github-webhook-handler
如何通过Git钩子自动部署(Push to Deploy)
用 Git Hooks 进行自动部署
“fatal: not a git repository: ‘.’”