介紹
官方文檔:
- 英文:https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
- 中文:https://git-scm.com/book/zh/v2/自定義-Git-Git-鉤子
下面只復制了pre-commit部分文檔,其他詳見官方文檔。
Git Hooks
Like many other Version Control Systems, Git has a way to fire off custom scripts when certain important actions occur. There are two groups of these hooks: client-side and server-side. Client-side hooks are triggered by operations such as committing and merging, while server-side hooks run on network operations such as receiving pushed commits. You can use these hooks for all sorts of reasons.
Installing a Hook
The hooks are all stored in the hooks
subdirectory of the Git directory. In most projects, that’s .git/hooks
. When you initialize a new repository with git init
, Git populates the hooks directory with a bunch of example scripts, many of which are useful by themselves; but they also document the input values of each script. All the examples are written as shell scripts, with some Perl thrown in, but any properly named executable scripts will work fine – you can write them in Ruby or Python or whatever language you are familiar with. If you want to use the bundled hook scripts, you’ll have to rename them; their file names all end with .sample
.
To enable a hook script, put a file in the hooks
subdirectory of your .git
directory that is named appropriately (without any extension) and is executable. From that point forward, it should be called. We’ll cover most of the major hook filenames here.
Client-Side Hooks
There are a lot of client-side hooks. This section splits them into committing-workflow hooks, email-workflow scripts, and everything else.
Note | It’s important to note that client-side hooks are not copied when you clone a repository. If your intent with these scripts is to enforce a policy, you’ll probably want to do that on the server side; see the example in An Example Git-Enforced Policy. |
---|---|
Committing-Workflow Hooks
The first four hooks have to do with the committing process.
The pre-commit
hook is run first, before you even type in a commit message. It’s used to inspect the snapshot that’s about to be committed, to see if you’ve forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code. Exiting non-zero from this hook aborts the commit, although you can bypass it with git commit --no-verify
. You can do things like check for code style (run lint
or something equivalent), check for trailing whitespace (the default hook does exactly this), or check for appropriate documentation on new methods.
翻譯:
Git 鉤子
和其它版本控制系統一樣,Git 能在特定的重要動作發生時觸發自定義腳本。 有兩組這樣的鉤子:客戶端的和服務器端的。 客戶端鉤子由諸如提交和合并這樣的操作所調用,而服務器端鉤子作用于諸如接收被推送的提交這樣的聯網操作。 你可以隨心所欲地運用這些鉤子。
安裝一個鉤子
鉤子都被存儲在 Git 目錄下的 hooks
子目錄中。 也即絕大部分項目中的 .git/hooks
。 當你用 git init
初始化一個新版本庫時,Git 默認會在這個目錄中放置一些示例腳本。 這些腳本除了本身可以被調用外,它們還透露了被觸發時所傳入的參數。 所有的示例都是 shell 腳本,其中一些還混雜了 Perl 代碼,不過,任何正確命名的可執行腳本都可以正常使用 —— 你可以用 Ruby 或 Python,或任何你熟悉的語言編寫它們。 這些示例的名字都是以 .sample
結尾,如果你想啟用它們,得先移除這個后綴。
把一個正確命名(不帶擴展名)且可執行的文件放入 .git
目錄下的 hooks
子目錄中,即可激活該鉤子腳本。 這樣一來,它就能被 Git 調用。接下來,我們會講解常用的鉤子腳本類型。
客戶端鉤子
客戶端鉤子分為很多種。 下面把它們分為:提交工作流鉤子、電子郵件工作流鉤子和其它鉤子。
Note | 需要注意的是,克隆某個版本庫時,它的客戶端鉤子 并不 隨同復制。 如果需要靠這些腳本來強制維持某種策略,建議你在服務器端實現這一功能。 (請參照 使用強制策略的一個例子 中的例子。) |
---|---|
提交工作流鉤子
前四個鉤子涉及提交的過程。
pre-commit
鉤子在鍵入提交信息前運行。 它用于檢查即將提交的快照,例如,檢查是否有所遺漏,確保測試運行,以及核查代碼。 如果該鉤子以非零值退出,Git 將放棄此次提交,不過你可以用 git commit --no-verify
來繞過這個環節。 你可以利用該鉤子,來檢查代碼風格是否一致(運行類似 lint
的程序)、尾隨空白字符是否存在(自帶的鉤子就是這么做的),或新方法的文檔是否適當。
分析
結合文檔說明,git init之后其實就會生成hooks示例文件,在./.git/hooks/
目錄下,*.sample
就是,使用的時候我們需要把后綴.sample
去掉,它就會生效了。
$ ls -alh ./.git/hooks/
total 53K
drwxr-xr-x 1 Administrator 197121 0 5月 26 23:59 ./
drwxr-xr-x 1 Administrator 197121 0 5月 27 18:52 ../
-rwxr-xr-x 1 Administrator 197121 478 5月 26 23:59 applypatch-msg.sample*
-rwxr-xr-x 1 Administrator 197121 896 5月 26 23:59 commit-msg.sample*
-rwxr-xr-x 1 Administrator 197121 4.6K 5月 26 23:59 fsmonitor-watchman.sample*
-rwxr-xr-x 1 Administrator 197121 189 5月 26 23:59 post-update.sample*
-rwxr-xr-x 1 Administrator 197121 424 5月 26 23:59 pre-applypatch.sample*
-rwxr-xr-x 1 Administrator 197121 1.7K 5月 26 23:59 pre-commit.sample*
-rwxr-xr-x 1 Administrator 197121 416 5月 26 23:59 pre-merge-commit.sample*
-rwxr-xr-x 1 Administrator 197121 1.5K 5月 26 23:59 prepare-commit-msg.sample*
-rwxr-xr-x 1 Administrator 197121 1.4K 5月 26 23:59 pre-push.sample*
-rwxr-xr-x 1 Administrator 197121 4.8K 5月 26 23:59 pre-rebase.sample*
-rwxr-xr-x 1 Administrator 197121 544 5月 26 23:59 pre-receive.sample*
-rwxr-xr-x 1 Administrator 197121 2.8K 5月 26 23:59 push-to-checkout.sample*
-rwxr-xr-x 1 Administrator 197121 3.6K 5月 26 23:59 update.sample*
具體使用
以pre-commit為例,進行測試,文檔介紹了例子是在提交之前進行代碼的操作,這里就簡單點:將當前時間打印到某個文件。
# 新建shell
echo 'date >> now_time.txt' > print_time.sh
chmod +x print_time.sh# 去掉后綴
mv ./.git/hooks/pre-commit.sample ./.git/hooks/pre-commit
vim ./.git/hooks/pre-commit# <<<內容
#!/bin/sh
echo "Running pre-commit hook"
sh ./print_time.sh
git add now_time.txt
# 內容>>>git add print_time.sh
git commit -m "feat: add print_time.sh"# 提交打印的日志
$ git commit -m "feat: update print_time.sh"
Running pre-commit hook
[main c9bf1ef] feat: update test.sh2 files changed, 2 insertions(+)create mode 100644 print_time.shcreate mode 100644 now_time.txt
至此,成功實現在提交之前自動執行腳本的效果。
其他類型的hooks其實就是嵌入的時機不同,當然也有一些各自的屬性,可參照這個pre-commit進行實現。