巧用Git钩子

什么是钩子?

我们知道Git是迭代式开发工具,我们的开发流程都是git add、git commit,git push,钩子呢就是你完成每一步Git给你的“回调”,举个例子假如你想让服务器每次上传完新的代码后更新网站,如果你没有钩子,你只能自己ssh登录上服务器,自己更新软件,一次两次还好,多了的话你会骂娘的,所以钩子是给我偷懒的脚手架,我们可以很轻松的写一些脚步帮我们完成一些重复的步骤

介绍玩钩子的作用,我们来介绍一下钩子的分类

我们知道Git核心是commit和push两个命令,一个对应客户端,一个对应服务端,所以钩子主要分客户端和服务端,由于Git步骤分的很细,所以每个大分类下面还有很多小分类,比如pre-commit,post-commit这些。

钩子的全部放在.git/hooks下面,在新建一个项目仓库的时候,Git已经在这个文件夹下给我们生成了很多个.sample后缀的钩子,这些钩子只要把.sample去掉就可以运行了,我们可以在这些sample上面修改完成我们自己的钩子

客户端钩子

客户端钩子很好理解,你commit之后想做其他事,比如说编译一下程序啥的,这里我就不多讲,主要由下面几个钩子组成

  • pre-commit 提交之前
  • post-commit 提交之后
  • pre-rebase 变基之前
  • post-rewrite 替换提交记录之后
  • pre-push 推之前

详细的可以看官网链接钩子

客户端钩子我觉得一般没有太多作用,因为我在提交之前就会运行脚步进行开发调试什么的,我把介绍重点放在服务端钩子

服务端钩子

服务端钩子就是你push之后的事情服务器要运行的脚步,有用推的步骤只有一个,所以钩子只有四个

  • pre-receive 接受之前
  • update 更新之前
  • post-update 更新之后
  • post-receive 接受之后

服务器接收到客户端请求时,pre-receive先进行调用,如果返回值为非0就会拒绝推送,所以我们写钩子的时候一定要记住最后要返回0才能正常接收更新,update主要处理多分支推送,有的时候你一次更新,推三四个分支到服务器,pre-receive只会调用一次,update会对每个的分支调用一次,后面两个都很容易理解

一般我们就是要在服务端更新代码之后运行脚步,所以我们要修改的就是post-update或者post-receive

bash脚步大家都会写,但是大家可能会很陌生什么是Git服务端,接下来我们就来介绍一下Git服务端是什么

Git 服务端

大家一般使用Git都是使用的客户端,但是Git这个工具的确很强,它不但可以当做客户端,也可以当做服务端,为了让大家更好的理解Git服务端,我们先来拿本地文件做”服务器“

首先我们先新建一个文件夹为server,在新建一个文件夹为local,假设文件夹都在/root文件夹下

我们执行下面的命令生成服务器

cd /root/server
git init --bare

只需要在init后面添加一个--bare选项告诉Git,Git就会帮我们生成一个空的“服务端”,我们可以查看一下文件,我们发现Git 给我们生成下面几个文件夹,其中就有我们的hooks

branches  config  description  HEAD  hooks  info  objects  refs

但是服务端和客户端生成的位置不一样,客户端是给我们生成一个.git文件夹,里面放了这些文件夹,然而服务端直接将这些文件夹放在主目录了

行我们已经生成了服务端的,接下来我们生成客户端的钩子

cd /root/local
git init

很简单,同我们往常操作一样,我们这时候添加一个README.md 然后commit一下准备开始往服务端推代码了

在 linux 下直接执行下面命令就行

echo “local update” >> README.md
git add README.md
git commit -m “Add ReadME”

接下来我们就要向”服务器“提交代码了,我们先添加本地文件作为远程服务器

git remote add origin file:////root/server

然后直接推代码

git push origin master

这样我们就向我们文件提交了代码,这时候我们回到我们”服务器“

cd /root/server
ls
branches  config  description  HEAD  hooks  info  objects  refs

我们惊奇的发现服务器并没有我们新建的README.md文件,原来Git服务端并不像SVN一样只保留一份代码大家共同修改,Git服务端只是记录文件变化和分支变化

这里插一句我为什么会去了解Git钩子,由于一开始实现服务器自动更新我的FastProxyScan项目代码,但是我又不想使用Github钩子(push后发送http请求),太麻烦了,后来我一想干脆直接推到我的服务器上,但是推到服务器上的代码只是记录了分支和提交信息,不包含源文件,所以我只好在在服务器上部署这个项目,并添加一个服务器钩子,当服务器更新完成后,再用钩子把服务器上的项目代码更新

如何写服务器钩子

通过上面对本地文件新建仓库,我们知道Git“服务端”新建很简单,我们一般接触比较多的是Github服务端,但是Git非常强大,他可以支持多种协议来连接“服务端”,比如说我们上面用到的本地文件(file协议),假如你用ssh连接远程服务器,你也可以使用类似git remote add origin ssh://username@ip/file/path添加ssh远程仓库

git 支持的协议有ssh、http、https、file、git等协议,你只要确保你能连接上远程服务器就行,接下来我们谈谈如何写服务器钩子

在使用git init --bare新建了一个Git服务端之后,在服务端文件下面有一个hooks文件夹,我们要做的就是把脚本放到hooks文件夹里面(当然你要确保它有执行权限),如果你更擅长写Python,Ruby那些脚步也可以,不过要确保前缀后后缀正确。

这里要提到很重要的一点,由于在执行钩子的时候,环境变量GIT_DIR被设置为服务端当前目录,如果你像我一样想更新在另外一个文件夹下面的项目代码,你必须使用uset GIT_DIR清除变量名,否则只会更新服务端,而不会更新你的项目代码

这里我提供一个模板

文件名为 post-update或者post-receive

#!/bin/sh
cd /project/path/ || exit
unset GIT_DIR
git pull origin master

exec git-update-server-info

你只需修改项目文件路径和仓库名即可

总结

通过这个Git钩子了解了Git服务端,也让自己更加了解Git这个软件,以前一直懵懵懂懂,只会向Github提交文件,一直以为Git只是一个版本记录工具而且,现在看来神器之名不是浪得虚名,通过一个小小的钩子,摇身一变成部署神器。

转载请注明出处:https://stgod.com/3828/