zoukankan      html  css  js  c++  java
  • 利用Git钩子实现代码发布


    利用Git钩子实现代码发布

    1、什么是git钩子

    和其它版本控制系统一样,Git能在特定的重要动作发生时触发自定义脚本。 有两组这样的钩子:客户端的和服务器端的。客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。

    2、安装一个钩子

    钩子都被存储在Git目录下的hooks子目录中。 也即绝大部分项目中的.git/hooks。 当你用git init初始化一个新版本库时,Git默认会在这个目录中放置一些示例脚本。这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 所有的示例都是shell脚本,其中一些还混杂了Perl代码,不过,任何正确命名的可执行脚本都可以正常使用——你可以用 RubyPython,或其它语言编写它们。 这些示例的名字都是以.sample结尾,如果想启用它们,得先移除这个后缀。把一个正确命名且可执行的文件放入Git目录下的 hooks子目录中,即可激活该钩子脚本。 这样一来,它就能被Git调用。

    3、常用的钩子脚本类型

    3.1 客户端钩子

    客户端钩子分为很多种。 下面把它们分为:提交工作流钩子、电子邮件工作流钩子和其它钩子。

    3.1.1 pre-commit

    在键入提交信息前运行。它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 如果该钩子以非零值退出,Git将放弃此次提交,不过你可以用git commit --no-verify来绕过这个环节。你可以利用该钩子,来检查代码风格是否一致(运行类似lint的程序)、尾随空白字符是否存在(自带的钩子就是这么做的),或新方法的文档是否适当。

    3.1.2 prepare-commit-msg

    在启动提交信息编辑器之前,默认信息被创建之后运行。它允许你编辑提交者所看到的默认信息。该钩子接收一些选项:存有当前提交信息的文件的路径、提交类型和修补提交的提交的SHA-1校验。它对一般的提交来说并没有什么用;然而对那些会自动产生默认信息的提交,如提交信息模板、合并提交、压缩提交和修订提交等非常实用。你可以结合提交模板来使用它,动态地插入信息。

    3.1.3 commit-msg

    接收一个参数,此参数即上文提到的,存有当前提交信息的临时文件的路径。如果该钩子脚本以非零值退出,Git将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。

    3.1.4 post-commit

    在整个提交过程完成后运行。 它不接收任何参数,但你可以很容易地通过运行git log -1 HEAD来获得最后一次的提交信息。该钩子一般用于通知之类的事情。

    3.1.5 电子邮件工作流钩子

    你可以给电子邮件工作流设置三个客户端钩子。 它们都是由git am命令调用的,因此如果你没有在你的工作流中用到这个命令,可以跳到下一节。如果你需要通过电子邮件接收由git format-patch产生的补丁,这些钩子也许用得上。
    第一个运行的钩子是applypatch-msg。它接收单个参数:包含请求合并信息的临时文件的名字。如果脚本返回非零值,Git将放弃该补丁。你可以用该脚本来确保提交信息符合格式,或直接用脚本修正格式错误。
    下一个在git am运行期间被调用的是pre-applypatch。有些难以理解的是,它正好运行于应用补丁之后,产生提交之前,所以你可以用它在提交前检查快照。 你可以用这个脚本运行测试或检查工作区。 如果有什么遗漏,或测试未能通过,脚本会以非零值退出,中断git am的运行,这样补丁就不会被提交。
    post-applypatch运行于提交产生之后,是在git am运行期间最后被调用的钩子。你可以用它把结果通知给一个小组或所拉取的补丁的作者。但你没办法用它停止打补丁的过程。

    3.1.6 其它客户端钩子

    • pre-rebase钩子运行于变基之前,以非零值退出可以中止变基的过程。你可以使用这个钩子来禁止对已经推送的提交变基。Git自带的pre-rebase钩子示例就是这么做的,不过它所做的一些假设可能与你的工作流程不匹配。

    • post-rewrite钩子被那些会替换提交记录的命令调用,比如git commit --amendgit rebase(不过不包括 git filter-branch)。它唯一的参数是触发重写的命令名,同时从标准输入中接受一系列重写的提交记录。 这个钩子的用途很大程度上跟post-checkoutpost-merge差不多。

    • git checkout成功运行后,post-checkout钩子会被调用。你可以根据你的项目环境用它调整你的工作目录。 其中包括放入大的二进制文件、自动生成文档或进行其他类似这样的操作。

    • git merge成功运行后,post-merge钩子会被调用。 你可以用它恢复Git无法跟踪的工作区数据,比如权限数据。 这个钩子也可以用来验证某些在Git控制之外的文件是否存在,这样你就能在工作区改变时,把这些文件复制进来。

    • pre-push钩子会在git push运行期间,更新了远程引用但尚未传送对象时被调用。它接受远程分支的名字和位置作为参数,同时从标准输入中读取一系列待更新的引用。你可以在推送开始之前,用它验证对引用的更新操作(一个非零的退出码将终止推送过程)。

    • Git的一些日常操作在运行时,偶尔会调用git gc --auto进行垃圾回收。pre-auto-gc钩子会在垃圾回收开始之前被调用,可以用它来提醒你现在要回收垃圾了,或者依情形判断是否要中断回收。

    3.2 服务器端钩子

    除了客户端钩子,作为系统管理员,你还可以使用若干服务器端的钩子对项目强制执行各种类型的策略。 这些钩子脚本在推送到服务器之前和之后运行。 推送到服务器前运行的钩子可以在任何时候以非零值退出,拒绝推送并给客户端返回错误消息,还可以依你所想设置足够复杂的推送策略。

    3.2.1 pre-receive

    处理来自客户端的推送操作时,最先被调用的脚本是pre-receive。它从标准输入获取一系列被推送的引用。如果它以非零值退出,所有的推送内容都不会被接受。 你可以用这个钩子阻止对引用进行非快进(non-fast-forward)的更新,或者对该推送所修改的所有引用和文件进行访问控制。

    3.2.2 update

    update脚本和pre-receive脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。 假如推送者同时向多个分支推送内容,pre-receive只运行一次,相比之下update则会为每一个被推送的分支各运行一次。 它不会从标准输入读取内容,而是接受三个参数:引用的名字(分支),推送前的引用指向的内容的SHA-1值,以及用户准备推送的内容的SHA-1 值。 如果update脚本以非零值退出,只有相应的那一个引用会被拒绝;其余的依然会被更新。

    3.2.3 post-receive

    post-receive挂钩在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。它接受与pre-receive相同的标准输入数据。它的用途包括给某个邮件列表发信,通知持续集成(continous integration)的服务器,或者更新问题追踪系统(ticket-tracking system) —— 甚至可以通过分析提交信息来决定某个问题(ticket)是否应该被开启,修改或者关闭。 该脚本无法终止推送进程,不过客户端在它结束运行之前将保持连接状态,所以如果你想做其他操作需谨慎使用它,因为它将耗费你很长的一段时间。

    4、利用钩子实现代码发布

    根据上述钩子的种类描述,可利用服务器端post-receive钩子来实现代码发布,主要包含步骤如下:

    4.1 在服务器上创建版本库

    [root@server ~]# mkdir /usr/local/git-workspace
    [root@server local]# cd /usr/local/git-workspace
    [root@server local]# git init -bare wwwroot.git
    [root@server local]# ls wwwroot.git/
    branches  config  description  HEAD  hooks  index  info  objects  refs
    

    此处需要注意:
    初始化版本库使用了git init -bare而不仅仅是git initbare汉语意思是:裸,裸的。之所以叫裸仓库是因为这个仓库只保存git历史提交的版本信息,而不允许用户在上面进行各种git操作。意味着初始化的版本库(暂且称为bare repository)只会生成一类文件:用于记录版本库历史记录的.git目录下面的文件;而不会包含实际项目源文件的拷贝;所以该版本库不能称为工作目录working tree;如果你进入版本目录,就会发现只有.git目录下的文件,而没有其它文件;就是说,这个版本库里面的文件都是.git目录下面的文件,把原本在.git目录里面的文件放在版本库的根目录下面;换句话说,不使用--bare选项时,就会生成.git目录以及其下的版本历史记录文件,这些版本历史记录文件就存放在.git目录下;而使用--bare选项时,不再生成.git目录,而是只生成.git目录下面的版本历史记录文件,这些版本历史记录文件也不再存放在.git目录下面,而是直接存放在版本库的根目录下面。用git init初始化的版本库用户也可以在该目录下执行所有git方面的操作。但别的用户在将更新push上来的时候容易出现冲突。

    4.2 创建web目录

    站点使用nginx和php提供服务,web目录如下

    [root@server]$ mkdir -p /home/website/webroot
    

    4.3 本地初始化和克隆版本库

    [root@localhost ~]$ cd /dev-workspace
    [root@localhost dev-workspace]$ git init local.git
    [root@localhost dev-workspace]$ cd local.git
    [root@localhost local.git]$ git clone ssh://root@xxx.xxx/usr/local/git-workspace/wwwroot.git
    

    拉取代码通过ssh协议,如果没有做密钥就直接输入服务器密码即可,若不是使用的默认22端口,命令类似:

    git clone ssh://root@xxx.xxx:端口号/usr/local/git-workspace/wwwroot.git
    

    4.4 设置钩子

    [root@server ~]# cd /usr/local/git-workspace/wwwroot/hooks/
    [root@server hooks]# vim post-receive
    #!/bin/bash
    git --work-tree=/home/website/webroot checkout -f
    

    --work-tree对应站点文件目录

    4.5 代码推送,版本库接收到推送后自动检出到web目录

    在本地版本库工作区里开发,然后使用git push指令推送到远程裸版本库,钩子会post-receive自动生效,将文件检出到--work-tree目录里,即代码一经提交就会自动同步到web目录下。
    至此,利用git钩子实现代码发布完成。

  • 相关阅读:
    HDU 1058 Humble Numbers
    HDU 1160 FatMouse's Speed
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1003 Max Sum
    HDU 1297 Children’s Queue
    UVA1584环状序列 Circular Sequence
    UVA442 矩阵链乘 Matrix Chain Multiplication
    DjangoModels修改后出现You are trying to add a non-nullable field 'download' to book without a default; we can't do that (the database needs something to populate existing rows). Please select a fix:
    opencv做的简单播放器
    c++文件流输入输出
  • 原文地址:https://www.cnblogs.com/ssgeek/p/11487713.html
Copyright © 2011-2022 走看看