HarmonyHu 多思不如养志,多言不如守静,多才不如蓄德

Git Hook实践

2017-09-01
Git

钩子脚本路径

钩子存放路径:.git/hooks/
该路径会有如下文件:

post-update.sample
pre-rebase.sample
pre-applypatch.sample
applypatch-msg.sample
pre-commit.sample
prepare-commit-msg.sample
commit-msg.sample
pre-push.sample
pre-receive.sample
update.sample

以上是钩子脚本的样板,可以用作参照,尤其传入参数。
.sample去掉后,便是对应的钩子脚本。

钩子脚本说明

客户端钩子

  • pre-commit: 在键入commit之前执行。可以用于检查提交的快照,比如pclint扫描。
  • prepare-commit-msg: 在启动commit编辑器之前执行。可以用于自动生成提交信息模板等。
  • commit-msg: 在commit编辑完成后执行。可以用于检查提交信息是否遵循模板等。
  • post-commit: 在commit完成后执行。可以用于发出通知等等。
  • pre-rebase: 在rebase之前执行。可以用于禁止对已经推送的提交rebase等等。

服务器端钩子

  • pre-receive: 来自客户端推送操作时执行。
  • update: 来自客户端推送操作时执行,对每个分支推送内容运行一次。
  • post-receive: 整个推送完成后执行。可以用于通知。

钩子脚本范例

update

#!/usr/bin/env ruby
$refname = ARGV[0]
$oldrev = ARGV[1]
$newrev = ARGV[2]
$user = ENV['USER']
puts "Enforcing Policies..."
puts "(#{$refname}) (#{$oldrev[0,6]}) (#{$newrev[0,6]})"
$regex = /\[ref: (\d+)\]/
def check_message_format
  missed_revs = `git rev-list #{$oldrev}..#{$newrev}`.split("\n")
  missed_revs.each do |rev|
    message = `git cat-file commit #{rev} | sed '1,/^$/d'`
    if !$regex.match(message)
      puts "[POLICY] Your message is not formatted correctly"
      exit 1
    end
  end
end
check_message_format

该脚本用于服务器端检查从客户端推送的消息中是否包含类似ref: 1234这样的字符串,不包含则返回错误。
其中几条git命令的含义如下:

  • 获取提交的SHA1值列表
    $ git rev-list 538c33..d14fc7
    d14fc7c847ab946ec39590d87783c69b031bdfb7
    9f585da4401b0a3999e84113824d15245c13f0be
    234071a1be950e2a8d078e6141f5cd20c1e61ad3
    dfa04c9ef3d5197182f13fb5b9b1fb7717d2222a
    17716ec0f1ff5c77eff40b7fe912f9f6cfd0e475
    
  • 获取提交的原始数据
    $ git cat-file commit ca82a6
    tree cfda3bf379e4f8dba8717dee55aab78aef7f4daf
    parent 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
    author Scott Chacon <schacon@gmail.com> 1205815931 -0700
    committer Scott Chacon <schacon@gmail.com> 1240030591 -0700
    (此处空行)
    changed the version number
    

参考书籍:《Pro Git SECOND EDITION》


Content