網頁

2021/8/16

使用pre-commit做commit前檢查

利用pre-commit做Git commit提交前的檢查。




Git的Git Hooks可以在git操作時觸發git專案中的hooks來執行某些動作,例如程式碼格式化、語法檢查、執行測試等,然而hooks script通常會搭配一些檔案、工具及特定的執行環境來達成目的,也就是説需要一大包東西跟著hook script跑。當hook script要用在多個專案時就得把這一大包複製到另個專案非常麻煩,而pre-commit這個套件即是用來解決上述問題。


下面示範如何在本機使用pre-commit做commit前的檢查。


安裝pre-commit

範例環境:

  • macOS Big Sur
  • Python 3.9.0

pre-commit是Python的一個套件,所以本機要先裝好Python 3及pip套件管理程式

在終端機輸入pip3 install pre-commit安裝。

$ pip3 install pre-commit
Collecting pre-commit
  Downloading pre_commit-2.14.0-py2.py3-none-any.whl (191 kB)
     |████████████████████████████████| 191 kB 915 kB/s
...
Installing collected packages: cfgv, toml, nodeenv, pyyaml, identify, platformdirs, backports.entry-points-selectable, filelock, six, distlib, virtualenv, pre-commit
Successfully installed backports.entry-points-selectable-1.1.0 cfgv-3.3.0 distlib-0.3.2 filelock-3.0.12 identify-2.2.13 nodeenv-1.6.0 platformdirs-2.2.0 pre-commit-2.14.0 pyyaml-5.4.1 six-1.16.0 toml-0.10.2 virtualenv-20.7.2

在Mac或可以用Homebrew安裝,在終端機輸入brew install pre-commit

$ brew install pre-commit
...
==> Installing pre-commit
==> Pouring pre-commit--2.14.0.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/pre-commit/2.14.0: 925 files, 15.2MB

安裝好後輸入pre-commit --version檢視版本資訊確認安裝成功。

$ pre-commit --version
pre-commit 2.14.0


使用pre-commit

pre-commit透過讀取.pre-commit-config.yaml配置檔來執行repo的hooks動作,所以在專案根目錄新增一個.pre-commit-config.yaml內容如下。yaml中的元素如reporevhooksid等為pre-commit的配置元素

.pre-commit-config.yaml

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.3.0
    hooks:
    -   id: check-yaml
    -   id: end-of-file-fixer
    -   id: trailing-whitespace

接著在專案根目錄以命令列執行pre-commit install下載pre-commit的hooks至專案的./git/hooks目錄。

~/../go-demo$ pre-commit install
pre-commit installed at .git/hooks/pre-commit

設定好以上之後git commit提交時就會執行.pre-commit-config.yaml中設定的hooks。例如這邊執行的pre-commit-hooks有檢查yaml格式(check-yaml)、修正檔案結尾(end-of-file-fixer)、移除行尾空白(trailing-whitespace)

pre-commit在執行時會先初始化environment,會將repo路徑的pre-commit repository下載回來,預設存放在~/.cache/pre-commit cache起來,之後再執行同樣的pre-commit hooks就不用再下載了。

~/../go-demo$ git commit -m "add pre-commit config"
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
Check Yaml...............................................................Passed
Fix End of Files.........................................................Failed
- hook id: end-of-file-fixer
- exit code: 1
- files were modified by this hook

Fixing .pre-commit-config.yaml

Trim Trailing Whitespace.................................................Passed

上面在commit時先執行了pre-commit並在end-of-file-fixer檢查時修正了檔案結尾因此commit失敗。

將檔案修正重新commit成功顯示如下。

$~/../go-demo$ git commit -m "add pre-commit config"
Check Yaml...............................................................Passed
Fix End of Files.........................................................Passed
Trim Trailing Whitespace.................................................Passed
[hello-world 7d233ac] add pre-commit config
 1 file changed, 7 insertions(+)
 create mode 100644 .pre-commit-config.yaml


如果想在commit前先手動執行指定的hooks,輸入pre-commit run <hook_id> -a-a代表檢查全部檔案,同--all-files。例如執行Trim Trailing Whitespace的hook則輸入pre-commit run trailing-whitespace -a

~/../go-demo$ pre-commit run trailing-whitespace -a
Trim Trailing Whitespace.................................................Passed

如果想在commit前先手動對特定檔案做pre-commit檢查,
輸入pre-commit run --files <file_1> <file_2>
例如只對main.go執行輸入pre-commit run --files main.go

(實際測試此參數似乎沒效果,一樣跑git專案下的全部檔案。)

~/../go-demo$ pre-commit run --files main.go
Check Yaml...........................................(no files to check)Skipped
Fix End of Files.........................................................Passed
Trim Trailing Whitespace.................................................Passed

下面對main.go執行Fix End of Files。

~/../go-demo$ pre-commit run end-of-file-fixer --files main.go
Fix End of Files.........................................................Passed

如果這次的提交想要跳過pre-commit檢查,提交時加上--no-verify參數。

~/../go-demo$ git commit --no-verify -m "skip pre-commit check"
[pre-commit 53be699] skip pre-commit check
 1 file changed, 2 insertions(+)

如果提交時只想省略某個hook檢查,可在環境變數SKIP設定要省略的hook id後再執行git commit。例如下面pre-commit省略了trailing-whitespace

~/../go-demo$ SKIP=trailing-whitespace git commit -m "skip trim trailing space"
Check Yaml...........................................(no files to check)Skipped
Fix End of Files.........................................................Passed
Trim Trailing Whitespace................................................Skipped
[pre-commit 735ba50] skip trim trailing space
 1 file changed, 2 insertions(+)

若要停用pre-commit則輸入pre-commit uninstall

~/../go-demo$ pre-commit uninstall
pre-commit uninstalled
Restored previous hooks to .git/hooks/pre-commit


參考github(Go專案)。


沒有留言:

張貼留言