初探Git Hooks,優化Git工作流
git 是現在主流的版控控制,寫軟體的人基本上都知道,但關於如何優化工作流以及什麼是 git hooks 知道的人可能就不多,因為這個部分是一種「優化」,使用了會更好,但是不用也沒關係,那我研究後覺得 git hooks 學會之後好處很多,那下面會儘量用好懂的方式來記錄跟介紹。
不講腳本寫法,不講複雜應用,只講整體的概念以及簡單的小應用來幫助理解概念。
但還是要有對於 git 的簡單知識,不然可能看不懂這篇。
這篇文章主要會有以下這三個大重點:
- 什麼是 git hooks
- 為什麼要使用 git hooks
- git hook 基本的應用有哪些
什麼是 git hooks
用一句話來講解這個概念,就是「每次使用了 git 的資料庫中發生特別事件時(像生命週期)自動運行的腳本」。
生命週期就是像人的一生中,有嬰兒、壯年,生、老、病、死,那 git 的特別事件我覺得也像是生命週期一樣,就是 git 的一些重要環節上代表各個 git 的生命週期,這個稍微就會解釋。
腳本就是一種程式的文件,我會把它想像是可以做某一種事情的程式,像是玩遊戲的時候,假如覺得一直在做一些重複性的事情很煩,那就可以寫一個滑鼠自動一直點的腳本。
而使用了 git 的資料庫的話,就是一個乾淨的專案裡面,只要下一個指令git init,那這個專案就會被加入到 git 的版控中,然後專案目錄下也會多出一個.git 的隱藏檔。
好,然後下一個問題我想就是那該如何去之後這個腳本會怎麼運行? 我得去哪裡控制它?
首先,會在它 git 專屬的隱藏檔裡面,在.git/hooks的位置,可以在裡面去放入腳本來去進行控制的動作,但要注意,一般來說是觀測不到的,因為 git 的.git 隱藏檔是預設看不到,所以要使用 git hooks 的技術,第一步得先找到 git hooks 檔案所需要放置的位置。
以下是打開 git 隱藏檔,找出 git hooks 的方式,我是用 vscode,所以只講它的情境:

一開始打開 vscode,
=> 設定 (右下角齒輪裡面,蠻明顯的,按下去再使用者那邊找)
=> 找 Files: Exclude
=> 如上圖,刪除裡面.git 選項
這樣一來,你就會發現隱藏檔露出了它的廬山真面目,但注意的是,因為這種改動從設定(使用者)的話是影響整個專案,而之所以 git 隱藏檔要隱藏起來,是因為不小心亂改到是很危險的,所以如果用這種方式改的話,那之後所有的專案都可以看到的。
這邊也提供另外一個技巧,如果你今天只想 for 自己的這個專案可以看到的 git 隱藏檔,可以這樣做。
一樣進到設定,但不是使用者,而是它右邊的工作區,點擊進去工作區之中的settings.json,加上這一段程式碼就 ok 了。
1 | { |
當成功的把 git 的隱藏檔顯露出來後,就可以觀測到 git hooks 的所在。

一個名字叫做 hooks 的資料夾,裡面擺了很多的 git 生命週期事件的檔案,等等會把這個檔案跟 git 的真正對應指令做個比較圖,先講這邊要如何去修改跟撰寫。
其實很簡單,就是把這個檔案的sample給刪除,直接去更改裡面就會生效了,我的理解是sample是要讓它預設為沒作用,那拿掉就變成有作用。

另外裡面打開會長這個,除了最上面的#!/bin/sh之外其他都刪除也沒關係,我都會先把預設的都刪掉然後再自己寫新的,還有就是裡面寫的腳本可以用任何的程式語言去寫,像是 node.js 也是完全沒問題。
接下來這邊最後就來講裡面的各種檔案對應的 git 指令吧:
有很多,但我只列舉 git 的最常用的那幾個,像是耳熟能詳的git add、git commit這種,而我們想要利用 git hooks 做的事情,其實就是當我們在使用這些 git 指令的時候,可以在那個時期做事情而已,也就是執行腳本。
會發現 hit hooks 裡面的特定檔案事件會把 git 指令分成執行前以及執行後,初看會覺得似乎沒有必要,但這卻是必須的。
我來舉例一個情境,假如你使用腳本,是為了在git commit之前去做檢查,要是 commit 訊息中,沒有某些字,你要用 git hooks 腳本的方式,阻止 coomit 訊息的發送,那麼同樣的腳本,執行前跟執行後就分成兩種不同的情境。
git commit執行之前的話,那代表還沒有成功 commit,所以腳本檢查完去阻止,是可以成功擋下的,
但是在git commit執行之後的話,它 git 生命週期的點已經是 commit 結束之後了,就算可以檢查得出錯誤,但也沒辦法阻止發生,這是它一個很大的差別。
所以說,執行前有它的情境,執行後也有它的用處,這是兩種不同的卻又都有需求,兩個都要有很合理。
為什麼要使用 git hooks
關於這個部分,我有整理出了幾點:
- 自動化流程
- 強制規範
- 安全性
第一,自動化流程的意思是使用 Git hooks 可以自動化許多重複性、瑣碎的工作。
沒有也可以,但你就是要手動一直做很多重複事情,軟體開發時總是會遇到這種事情,像是運行單元測試、檢查代碼風格、自動化部署等等,會發現這些事情可能超級耗時間,而且因為是手動去執行的,所以會發生一些像是忘記執行,或是少執行了一些步驟,然後導致整個在使用版控的流程發生錯誤。
git hooks 只要把這個自動化的流程流程寫成腳本,放進去 git 的生命週期,像是每次 push 之後都要做一個自動化部署,直接幫你省一大堆時間,開發效率直線上升。
接著是強制規範的部分,Git hooks 可以強制做一些規範,像是說查程式碼風格、檢查文件格式、防止不必要的合併等等,甚至連 git commit 訊息都可以去規定它要怎麼寫,用了就回不去了,實在是太方便。
這樣做可以確保假如有在協作的話,大家全部人的風格都符合同一個標準,有一致性的同時也拉高了可讀性,讓寫 code 變成更愉快的同時,程式碼也是變的用容易維護以及修改。
最後是安全性,Git hooks 可以幫助保持資料庫的安全性,例如說防止提交敏感資訊、防止執行有害的程式碼等等。
像是如果有不能被傳上去的禁止字樣,或是可怕的程式碼寫法,直接上傳上去是會造成困擾的,這個部分跟強制規範規範其實有點類似,主要就是在提交程式碼之前,再次做個檢查,看看這些程式中有沒有包含危險不安全的東西存在,有的話就馬上警告,確保整個專案都是安全的狀態。
總之,做個小結論,使用 Git hook 可以幫助自動化流程、強制規範和提高安全性,從而提高開發效率、確保品質和減少風險,不用可以,用了會更好,這是我覺得它的優點。
git hook 基本的應用有哪些

這邊最基礎的話,從pre-commit開始寫起 git hooks,也就是所謂的git commit執行之前的腳本,跟前面說的一樣,除了最上面那行之外,其他全部刪掉,自己寫。
我這邊寫的意思是,當 coomit 的指令下出去,指令之後,執行之前會去跑這個腳本觸發,功能是會呼叫一次我的名字,”hello vic”這樣。
有用到了兩個我覺得要知道的語法,介紹一下什麼是Echo及exit。
Echo命令用來將後方參數輸出到 console,就是把寫的東西印出來。exit命令如果是 0 的話會讓 commit 繼續,若 exit 後為非 0,例如 exit 1 則會終止 commit。

然後是稍微讓大家了解概念的應用,也就是執行腳本這件事情,專案當中,可能就已經使用了很多lint系列的套件,這些套件就是專門用來負責處理程式的格式、風格,所以其實可以把它們直接加上 git hooks 就好了。
舉例來說,假如專案中有在使用eslint,通常 Node.js 專案會在 package.json 的 scripts 欄位下設定 lint 腳本,來呼叫 lint 工具去檢查 JavaScript 等程式碼的語法。
那我可以把它搭配做使用,在 git hooks 當中的 pre-commit 腳本中去執行 npm run lint。
這樣就會達成效果是 commit 指令下去之後,會在 commit 執行之前,幫我得程式碼做一個檢查的動作,這也是我目前比較常用的做法,然後 commit 的話也有專門的 commitlint 可以做使用,所以其實不用真的會寫 git hooks 的腳本也沒關係。
小結
以上大致就是我在研究 git hooks 之後,想分享及做的筆記心得,下次可能會想研究 git hooks 的工具搭配,因為其實要打開隱藏檔這件事情真的是比較麻煩的,而且由於.git 隱藏檔不吃版控的關係,我找了一些奇怪的方式才能追蹤到推遠端,覺得應該可以用更好的方式。
有一個叫做Husky的工具,據說使用它可以讓 git hooks 這件事情變得更加簡單,下一個研究的目標就會是它,研究完我會再把我的心得研究丟 blog。
參考資料
影片類
(2) [Git#8] 用 pre-commit 檢查提交時的分支是否正確 - YouTube
透過工具建立有規範的 git commit message 吧 - YouTube
文章類
Git - Git 鉤子
菜鳥工程師 肉豬: Git 什麼是 Git Hooks?
aitemr/awesome-git-hooks: 😎 A collection of awesome Git Hooks
手写 git hooks 脚本(pre-commit、commit-msg)
探索藏在 Git 當中的 Git Hook - HackMD
如何在執行 git commit 前自動進行檢查?Git Hooks 的基本用法 | MagicLen
