零基础,上周为了一个需求一直在学习git的使用,
没接触git的时候,听到git hook简直一头雾水,只能粗略的知道这是一种类似于触发器的东西。
边实践边接触,这东西也算是懂了,其实使用并不是很复杂,但是要知道互相之间的关系。
钩子分为客户端和服务端。
客户端的动作比较多,服务端的动作只有三个。
钩子解析:
服务端:
正常使用git init --bare出来的仓库都是没有这三个文件夹的,
这是我使用gitea管理之后默认会给服务端的hook文件夹中创建这三个文件夹区分客户端钩子跟服务端钩子。
gitea管理的话,服务端的钩子就放在这三个文件夹中,但是要想触发钩子动作,
需要在这三个文件夹中创建相应的钩子文件,比如在post-receive.d文件夹中创建post-receive文件。
并赋予post-receive权限变成可执行文件,例如:chmod 755 post-receive。
注:如果不是gitea管理(gitlab应该类似),那就直接在git服务端的hook文件夹下创建post-receive文件编写脚本,另外两个一样。
post-receive:在服务端收到文件之后,比如git push XXX 之后,服务端上已经能查到提交信息之后自动触发。
pre-receive:在客户端git push 之后但是服务端还没有收到文件时触发。
update:如果有多个分支推送内容则每一个分支在把内容推送到服务端之前都会触发一次,相比于pre-receive只会触发一次。
这三种钩子,只在服务端运行。
客户端:
顾名思义,只在客户端会触发的钩子,放在客户端clone下的.git/hook文件夹下。
eg:
里面有服务端的钩子注意区分,使用gitea管理的话,只会触发文件夹里的钩子,就算你编辑这个目录下的这三个文件也不会触发钩子动作。
客户端的钩子这个目录下其实并不全,有兴趣的话可以看看官方的文档,
我就捡几个举个例子说一下。(需要编写的话,去掉.sample后缀修改一下文件的执行权限即可)
commit-msg 客户端每执行一次git commit 操作成功之后自动触发。
pre-rebase 你在本地每执行一次git rebase 操作,在变基之前触发(其实并不能感觉到这个过程,除非做一些测试)
post-checkout 比如执行 git checkout -b <branchname> 或者 git checkout <branchname>之后会自动触发。
以上就是钩子的分析,其实找到钩子的存放位置,知道触发的动作,编辑相应的脚本就可以实现类似触发器的东西。
实战场景:
有这么一个需求,就是当客户端向服务端push代码的时候,
服务端触发一个post-receive钩子,把相应的项目再push到远端的一个仓库。
实际场景更复杂一点 {
1、每一个用户在自己的用户下面派生了一个公共组中的一个仓库
2、每一个用户又把派生的仓库克隆到本地
3、客户端push项目的时候先把项目push到服务端的派生仓库里。
4、管理员在在gitea页面进行一次合并请求操作,把派生出来的仓库合并到公共组的那个原仓库
5、合并请求完成之后,公共组的仓库会触发钩子把项目push到2号服务器的git仓库中。
}
这个地方博主也有一个疑惑,按理说只能非裸push到裸,不能裸到裸。
但是服务端的仓库都是裸仓库,触发了钩子却可以裸到裸。
注:标记一下操作,使用gitea的合并请求也是一次push操作,可以触发钩子,并不是只有客户端push到服务端才能触发。
场景如下图:
捋清楚了整个过程其实脚本倒是很简单,
demo:
并不是只可以自行这一种脚本,只要你安装有相应的编译器,理论上可以执行所有脚本,比如python。
注:脚本其实可以很复杂,能满足自己的需求就行。
链接格式不懂的可以看我<apache+git搭建>这篇博文。
-f-------这个地方有个坑,要不是这个坑,这个任务早两天就跑出来了。
假如说,你在本地克隆了2号服务器上的仓库,并且push了一些内容在上面。
然后你换了一个仓库,也没有fetch2号服务器上的git仓库,就想直接push到2号上面。
那就需要加一个-f(表示强制),直接把原先本地提交到这个仓库的信息覆盖掉,就是新的项目了。
裸仓库里只能使用git log查看日志信息,不能使用任何工作命令。
以上就是git hook的全部内容,我觉得大概也就这么多了,希望能帮到看到这篇文章的朋友们。
各位老铁,有什么问题请提出来,大家共同进步。