Git Hook 是什么?

像许多其他的版本控制系统一样,Git提供了在特定动作发生时执行自定义脚本的功能. 有两种hook, client-side和server-side:

  • client-side: 由commit或者merge之类的操作触发
    • pre-commit
    • prepare-commit-msg
    • commit-msg
    • post-commit
    • pre-rebase
    • post-merge
    • pre-push
    • 等等
  • server-side: 由网络操作触发,例如receiving pushed commits
    • pre-receive
    • update
    • post-receive

详情可参考: Customizing Git - Git Hooks

配置git hook

业务上有个需要: 在markdown格式的文件提交到仓库之后,自动触发任务,生成对应的html格式文件. 非常适合使用post-receive这个git hook来实现, 首先我们了解一下:

post-receive

The post-receive hook runs after the entire process is completed and can be used to
update other services or notify users.
It takes the same stdin data as the pre-receive hook.
Examples include e-mailing a list, notifying a continuous integration server,
or updating a ticket-tracking system –
you can even parse the commit messages to see if any tickets need to be opened, modified, or closed.
This script can’t stop the push process, but the client doesn’t disconnect until it has completed,
so be careful if you try to do anything that may take a long time.

也就是说post-receive这个hook在服务器接收到pushed commits之后触发, 可以用来更新其他服务或者通知用户,非常适合于通知CI, 更新文档之类的任务.

我们的配置过程如下:

  1. 进入服务器的git仓库目录,编写.git/hooks/post-receive文件,如下:
    #!/bin/sh
    echo "---post receive hook started---"
    ssh dev ./gen_doc.sh
    echo "---post receive hook finished---"
    

    注: 以上的ssh命令需要配置相应的.ssh/config文件和authorized_keys公私密钥等,不是本文重点,此处略去.

  2. 设置正确的文件权限:
    sudo chmod a+x .git/hooks/post-receive
    
  3. 任务后台化

此时当用户git push 之后就会自动触发更新文档的任务了,但是还有一个小瑕疵:

This script can’t stop the push process,
but the client doesn’t disconnect until it has completed,
so be careful if you try to do anything that may take a long time.

我们并不想让用户在运行git push时等待生成html文件的整个过程, 所以可以将耗时的生成文件任务后台化, 更改post-receive文件如下:

#!/bin/sh
echo "---post receive hook started---"
ssh dev ./gen_doc.sh > /dev/null 2>&1 &
echo "---post receive hook finished---"

此时,在用户git push时会自动执行任务并后台化,无需等待任务完成git push命令就可以直接结束,完美.