Git Hook实现轻量级自动化部署
前言
最近在整理项目,发现以前的一个项目中,发现使用git hook和pm2实现了一个简单的自动化部署,也没有写什么记录,故复记录之。
正文
原理与流程
- git用户执行git push操作;
- 远程仓库发现有用户执行了push操作,就会执行一个脚本post-update(钩子);
- 在post-update脚本中,将git仓库的代码拷贝到web站点目录下。
Git 钩子
Git 钩子(hooks)是在 Git 仓库中特定事件(certain points)触发后被调用的脚本。通过钩子可以自定义 Git 内部的相关(如 git push)行为,在开发周期中的关键点触发自定义的行为。Git 含有两种类型的钩子:客户端的和服务器端的。客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。
每个使用git进行版本版本管理的项目都存在hooks,这些hooks存在于项目目录下的.git/hooks/
:
以上这些就是git hook脚本。简单地说,hook是一种特殊的脚本(代码),仅在满足特定条件时执行。git hooks分别有对应各种操作的hook。每个hook都对应在不同的情况下触发,比如接下来要用到的post-update脚本,则是在检测到push的操作时触发。
实现流程
- 在服务端创建一个裸仓库;
- 编辑裸仓库中的post-update hook脚本;
- 本地仓库添加远程裸仓库作为remote。
1. 在服务端创建一个裸仓库
什么是裸仓库?
裸仓库与 git init 初使化的仓库不太一样,裸仓库其实相当于通过克隆来的仓库里的.git文件夹,整个裸仓库中只有git索引(index),不包含工作目录。裸仓库只保存了一些配置信息等,肉眼找不到上传的代码。简单说就是一个简单版的git仓库,不能使用常见的git命令,比如git status
等等。
创建裸仓库很简单:
1 | bare.git名字可以任意 |
为什么要创建裸仓库?
裸仓库存在于服务端,是我们要提交代码的目标。我们在本地仓库push代码,就是要push到这个裸仓库。当我们push到这个裸仓库时,就会触发裸仓库响应的git hook——post-update。
2. 编辑裸仓库中的post-update hook脚本
在脚本中,你可以写Bash、Python、JavaScript等代码,Git通过Shebang来选择执行代码的解释器。如果要写Bash,Shebang可以是这样:
1 | !/usr/bin/bash |
使用Windows的读者请注意,如果脚本文件含有BOM(字节序标识符),可能会导致一些问题。
1 | 去掉sample后缀才会触发 |
下面是一个比较简单的hook脚本:
1 | !/bin/sh |
注意: 一定要unset GIT_DIR清除变量, 不然会引起remote: fatal: Not a git repository: ‘.’错误。
上面脚本做的事情很简单:
- 切换到部署目录;
- 初始化git,在部署目录中添加裸仓库作为remote;
- 拉取裸仓库中的代码;
- 执行打包脚本。
接着还需要给 post-update 添加执行权限:
1 | chmod +x将所有用户的执行权限添加到现有权限 |
3. 本地仓库添加远程裸仓库作为remote
1 | // 如果测试,并且裸仓库建在本地 |
总结
- 利用每次push到目标仓库都会触发对应git hook的机制,在git hook中进行需要部署的代码从目标仓库中克隆到实际的代码部署目录;
- 实现流程分为三步:
- 在服务端创建一个裸仓库;
- 编辑裸仓库中的post-update hook脚本;
- 本地仓库添加远程裸仓库作为remote。