1 minute read     Posted on:     Updated on:     Views: Loading...

What Is Git Hook

在開發過程當中,我們常常會遇到需要手動進行測試以及 format 程式碼等等的事情,那就會讓我思考
有沒有一種自動化的工具可以執行這些任務呢?

Git - 一個幾乎可以說每個軟體工程師都會使用的工具,提供了一個解方

git hook 簡單來說就是一個在 commit, push, receive 之前或之後跑的 script,可以讓開發者自定義需要執行的 script
這個 script 不限定使用何種語言撰寫皆可(e.g. python, perl, ruby 或 shell script … etc.)
而 git hook 通常分為兩大類

  • client-side: 透過 commit 或者是 merge 觸發
  • server-side: 多半是透過網路,當接收到 commit 時觸發

How to setup Git Hook

git hook 是內建的功能之一,我們可以在 ./git/hooks 底下找到許多範例檔案

1
2
3
4
5
6
ambersun@station:~/ambersun1234.github.io/.git/hooks$ ls
applypatch-msg.sample      pre-applypatch.sample    pre-rebase.sample
commit-msg.sample          pre-commit.sample        pre-receive.sample
fsmonitor-watchman.sample  pre-merge-commit.sample  prepare-commit-msg.sample
post-update.sample         pre-push.sample          update.sample
ambersun@station:~/ambersun1234.github.io/.git/hooks$

使用 git hook 需要符合以下

  • 將檔案置於 ./git/hooks 資料夾底下
  • 客製化 git hook 不能 有任何副檔名
  • 更改 file mode 成可執行
    1
    
    $ chmod +x my-hook
    
  • 檔案名稱需要完全符合預設 hook 種類的名字(詳細可以參考 Git - githooks documentation) 不然有可能會無法 trigger
  • 如果在 commit 的當下想要 pass 掉 hook 可以使用
    1
    
    $ git commit --no-verify
    

除了放在 ./git/hooks 底下之外,你也可以透過 git config 去設定

1
$ git config core.hooksPath MYPATH

Example

以我自己來說,安裝 git hook 這件事情我會寫成 Makefile 執行,然後呼叫安裝的 script 自動安裝
考慮以下安裝 script

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/sh

if ! test -d .git; then
  echo "Execute scripts/install-git-hooks in the top-level directory"
  exit 1
fi

ln -sf ../../scripts/pre-commit.hook .git/hooks/pre-commit || exit 1
chmod +x ./scripts/pre-commit.hook

echo
echo "Git hooks are installed successfully"

可以看到以上做的事情相對單純,首先先檢查 .git 資料夾是否存在,之後再將 pre-commit.hook 檔案以 symbolic link 的方式安裝進 ./git/hook 中
注意到不可直接將 scripts/pre-commit.hook 安裝進去,會無法正確 trigger
最後在加上 execute 的權限即可

而 pre-commit.hook 的內容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

RED='\033[0;31m'
NC='\033[0m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'

echo -e "${YELLOW}Auto CI for all data structures${NC}"
bash ./ci.sh
if [ "$?" -eq 0 ]; then
  echo -e "${GREEN}CI check done${NC}"
else
  echo -e "${RED}CI check failed${NC}"
fi

這個例子是針對所有子專案進行 compile 看說有沒有 compiler error 而已

在安裝了 pre-commit hook 之後每次執行 git commit 之前就會先跑一遍 local build 了
除此之外你也可以做比如說像是 format code 之類的事情

完整範例可參考: github.com/ambersun1234 - Data-Structures

Reference

Leave a comment