使用 Git Hooks 实现项目自动部署
自动化部署解放双手,发展生产力,更重要的是可以减少部署过程中的错误操作。
之前使用git做为我博客的版本控制,使用Github Pages托管我的博客,所以部署方面都交给了github, 但是当我要部署另一个web应用时,显然要部署在自己的VPS上,把VPS做为git服务器的同时,每次push 代码到服务器上都要手动运行一次脚本更新服务,这样做简直劳神伤力。
幸运的是Git提供了Hook机制用来帮助我们实现自动部署。Hooks分为客户端和服务端,可以用来处理不同
的工作,这些hooks都被存储在 Git 目录下的hooks子目录中,
即大部分项目中的.git/hooks
。 Git 默认会放置一些脚本样本在这个目录中,除了可以作为hooks使用,
这些样本本身是可以独立使用的,这些样本名都是以.sample结尾,必须重新命名。
这次主要用到服务端的hooks: post-receive
。当用户在本地仓库执行git push
命令时,服务器上运端
仓库就会对应执行git receive pack
命令;在所有远程仓库的引用(ref)都更新后,这个钩子就会被调用。
与之对应的是pre-receive
,这个会在更新之前被调用。
环境要求:
- 要求客户端和服务端都有git环境,而且服务端最好已经部署好了;
- 能连上服务器
0x01 实践
我们的实践过程会按照下边的过程实施:
|
在server上初始化一个远程裸仓库:
$ cd ~ |
在server上初始化一个本地仓库,做为web app的代码:
$ cd ~ |
为远程仓库添加hook:
$ cd ~/remoteRepo/webapp.git/hooks |
post-receive
中的命令:
#!/bin/sh |
为post-receive
添加可执行权限
chmod +x post-receive |
为local machined的本地仓库添加远程仓库源:
cd <your-local-repository-folder> |
或者从头开始创建一个项目:
git init |
这样,当我们在本地完成更新并push到server上时,这些代码就会被自动更新。
0x02 后来
改进1
可以在最初在server上创建裸仓库时使用local machine上的现有项目,即将local machine上 的项目仓库导出为裸仓库 — 即一个不包含当前工作目录的仓库:
$ git clone --bare my_project my_project.git |
或者
$ cp -Rf my_project/.git my_project.git |
然后将这个裸仓库移到server上
$ scp -r my_project.git git@<server.ip>:/home/git/remoteRepo |
之后,其他人要进行更新时就可以clone这个项目了:
$ git clone git@<server.ip>:/home/git/remoteRepo/my_project.git |
改进2
有一种情况是当本地更新了webapp,结果push到远程仓库后这个更新被reset了(虽然我觉得这个问题应该避免,
但是还是有可能发生),这是,简单地在hook中使用git push deploy master
是无法完成这个过程的,因为
远端的代码版本低于deploy端的代码版本,再使用pull的时候就不能实现同步,这时就应该使用另一种方式
更新代码:
git fetch --all |
即git reset
把HEAD 指向了新下载的未合并的节点,也就是在local machine上reset之后的。