巧用 gitHooks 提交前校驗代碼

2021-12-24 前端宇宙

感謝bigAken投稿

在每一個使用 git 進行版本管理的倉庫,都有一個目錄 .git/hooks,包含 commit 各個階段 Hooks 的腳本。這些 Hooks 在 git 操作 commit、push、merge 等得時候,可以做前置或者後置的操作,例如 pre-commit 在 git commit 前可以做代碼校驗,校驗代碼的時候使用的ESLint,格式化使用的是 prettier。Git 支持的常用鉤子見下表,更多請查看官網Hooks:

Git Hook調用時機調用時機pre-commitgit commit 執行前可以用 git commit --no-verify 繞過commit-msggit commit 執行前可以用 git commit --no-verify 繞過pre-merge-commitgit merge 執行前可以用 git merge --no-verify 繞過pre-pushgit push 執行前

本文先實踐,怎麼去寫 pre-commit 這個 git hooks,然後介紹 husky,lint-staged,commitlint 的使用

在 git 項目中,.git/hooks下面有很多 hooks 示例如下

這些 git hooks 都是.sample結尾的,如果要啟用某個 hooks 用可以去掉.sample結尾

實踐

npm init -y初始化一個項目,然後git init,然後npm install eslint --save-dev

新建.gitignore文件

node_modules

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

*-lock.json
*.lock

新建.eslintrc,配置 eslint

{
 "rules": {
  // 要求使用分號
  "semi": ["error", "always"],
  // 強制使用一致的反勾號、雙引號或單引號
  "quotes": ["error", "double"]
 }
}

新建src目錄,然后里面新建index.js,禁止使用快捷鍵格式化

console.log('object')

根目錄新建文件夾.customGitHooks然後 git config 'core.hooksPath' .customGitHooks,主要是設置 gitHooks 的存放目錄,因為 gitHooks 默認存放目錄是.git/hooks,新建pre-commit,寫入如下

#!/bin/sh

echo 'start check your code,please wait...'
# git diff 獲取更改的內容 可以通過參數--diff-filter 配置條件
npx eslint $(git diff --cached --name-only --diff-filter=ACM -- '*.js')
# 變量$?--->上一個命令的執行狀態結果
if [ $? != '0' ];then
  echo "ending and failed,please check your code;"
 exit 1
else
  echo "check pass"
fi

這時候,執行git add .,git commit -m 'test'就會發現沒有 commit 成功,報錯了,如下圖

如果把 index.js 的代碼修改如下:

console.log('object')

執行git add . ,git commit -m 'test'就會發現 eslint 代碼檢查通過了,能正常提交了,以上實踐能很好解釋 commit 前怎麼檢驗代碼,但是有個缺點就是別人 pull 你的代碼要執行git config 'core.hooksPath' .customGitHooks能起作用;下面就介紹 husky,lint-staged,commitlint 的使用

.git 文件夾不會被跟蹤並且上傳至遠程倉庫的

Husky

github為了解決.git配置不能提交遠程倉庫的問題,husky 出來了,husky 在你npm i安裝完依賴只有自動執行husky install

安裝 npm install husky -D
npm install husky -D

使用

編輯package.json在script裡添加prepare的值為husky install

  "scripts": {
    "prepare":"husky install"
  },

然後執行npm run prepare,做了什麼事呢

源碼index.ts中,我們看到執行 husky install 實際上就是創建 .husky 目錄,複製../husky.sh文件到該目錄下,配置了一個.gitignore,設置了core.hooksPath(設置 .husky 目錄為 git hooks 目錄)

添加一個 hook

在.husky目錄下創建pre-commit

#!/bin/sh

echo 'start check your code,please wait...'
# git diff 獲取更改的內容 可以通過參數--diff-filter 配置條件
npx eslint $(git diff --cached --name-only --diff-filter=ACM -- '*.js')
# 變量$?--->上一個命令的執行狀態結果
if [ $? != '0' ];then
  echo "ending and failed,please check your code;"
 exit 1
else
  echo "check pass"
fi

index.js文件內容如下

console.log('object')

然後執行git add .,git commit -m 'test'發現代碼已經被攔截,沒有提交,因為index.js代碼不符合規範

遺留問題就是 git hooks 不會編寫怎麼辦,下面 lint-staged 出來了

lint-staged

配置例子作用:對 Git 暫存區代碼文件進行 bash 命令操作等等

npm i lint-staged -D

根目錄下新建.lintstagedrc文件

{
  "*.js": "eslint"
}

把husky目錄下的pre-commit修改如下

. "$(dirname "$0")/_/husky.sh"
npm run lint

package.json添加script

"scripts": {
  "lint": "lint-staged"
}

index.js如下

console.log('object')
console.log('object')

執行git add .,git commit -m 'test',可以發現調用了 eslint 去檢查代碼,檢查不通過就退出commit

綜上,代碼檢測規範有了,現在也需要規範一下提交規範;

commitlint

github

校驗 commit 提交的信息

npm install --save-dev @commitlint/config-conventional @commitlint/cli

使用新建commitlint.config.js

module.exports = {
 extends: ['@commitlint/config-conventional'],
 rules: {
  'type-enum': [2, 'always', ['build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'style', 'test', 'revert', 'chore']],
  'type-case': [0],
  'type-empty': [0],
  'scope-empty': [0],
  'scope-case': [0],
  'subject-full-stop': [0, 'never'],
  'subject-case': [0, 'never'],
  'header-max-length': [0, 'always', 72]
 }
}

配置git hooks,執行下面命令

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'

commit message 一般分為三個部分 Header,Body 和 Footer

header
<type>(<scope>): <subject>
// 空一行
<body>
// 空一行
<footer>
其中,Header 是必需的,Body 和 Footer 可以省略

接下來提交的 commit 必須符合下面的格式

注意冒號後面有空格

git commit -m <type>[optional scope]: <description>

常用的 type 類別

build:主要目的是修改項目構建系統(例如 glup,webpack,rollup 的配置等)的提交ci:主要目的是修改項目繼續集成流程(例如 Travis,Jenkins,GitLab CI,Circle 等)的提交refactor:重構代碼(既沒有新增功能,也沒有修復 bug)style:不影響程序邏輯的代碼修改(修改空白字符,補全缺失的分號等)

optional scope:一個可選的修改範圍。用於標識此次提交主要涉及到代碼中哪個模塊。

description:一句話描述此次提交的主要內容,做到言簡意賅。

這時候,執行一次測試一下

git add .
git commit -m 'test'

因為該提交的 commit 是不規範的所以提交時失敗的 如下圖

如果把 commit 修改,就會提交成功,因為符合 commit 規範

git add .
git commit -m 'feat: test'

但是問題又來了,每次 commit 都要輸入,有點不方便;而且有可能輸錯下面就介紹到 commitizen

commitizen

cz-commitlint

生成符合規範的 commit message

本地安裝並沒有全局安裝,當然可以全局安裝具體查看官方文檔,全局安裝可以使用git cz,cz-commitlint打通 commitizen 和commitlint配置

npm install --save-dev @commitlint/cz-commitlint commitizen

然後

npx commitizen init cz-conventional-changelog --save-dev --save-exact

package.json添加script

{
 "scripts": {
  "commit": "git-cz"
 },
 "config": {
  "commitizen": {
   "path": "@commitlint/cz-commitlint"
  }
 }
}

新建commitlint.config.js

module.exports = {
 extends: ['@commitlint/config-conventional']
}

然後執行

git add .

npm run commit

發現為中文提示如下圖

再次修改commitlint.config.js

module.exports = {
 extends: ['@commitlint/config-conventional'],
 prompt: {
  questions: {
   type: {
    description: '選擇你要提交的類型:',
    enum: {
     feat: {
      description: '新功能',
      title: 'Features',
      emoji: '✨'
     },
     fix: {
      description: '修復相關bug',
      title: 'Bug Fixes',
      emoji: '🐛'
     },
     docs: {
      description: '文檔更改',
      title: 'Documentation',
      emoji: '📚'
     }
    }
   }
  }
 }
}

然後執行

git add .

npm run commit

可以看到變成中文了,具體參考官網

接下來提交信息 執行npm run commit,就可以按照規範提交了;如果沒有使用commitlint,在 commitizen中使用 cz-customizable也可以自定義很多配置的

相關焦點

  • 你提交代碼前沒有校驗?巧用gitHooks解決
    這些 Hooks 在 git 操作 commit、push、merge 等得時候,可以做前置或者後置的操作,例如 pre-commit 在 git commit 前可以做代碼校驗,校驗代碼的時候使用的ESLint,格式化使用的是 prettier。
  • 前端代碼庫裡的 git hooks
    上述對話反應幾個問題:git hooks 作用在代碼commit前做些 eslint 校驗,代碼格式化,在推代碼前做分支名檢查、文件目錄規範、yarn.lock文件強制提交等package.json文件
  • 手寫 git hooks 腳本(pre-commit、commit-msg)
    正文用於編寫 git hooks 的腳本語言是沒有限制的,你可以用 nodejs、shell、python、ruby等腳本語言,非常的靈活方便。下面我將用 shell 語言來演示一下如何編寫 pre-commit 和 commit-msg 腳本。另外要注意的是,在執行這些腳本時,如果以非零的值退出程序,將會中斷 git 的提交/推送流程。
  • 通過 husky + lint-staged 實現在 Git 提交前進行文件美化和代碼校驗
    許多人非常傾向於在 Git 提交之前進行 prettier 和 eslint, 這樣能夠保證提交後的文件經過美化和校驗的。
  • 關於 git hooks 的庫 husky 源碼竟如此簡單,你也可以寫一個!
    代碼在提交之前 (pre-commit hook),可做以下諸多校驗,如未通過檢驗,則無法成功提交。Git Hooks在每一個使用 git 進行版本管理的倉庫,都有一個目錄 .git/hooks,包含 commit 各個階段 hook 的腳本。
  • 別亂提交代碼了,看下大廠 Git 提交規範是怎麼做的!
    項目內安裝commitlint & huskyCommit message規範在rrd-fe落地使用情況擴展閱讀git是現在市面上最流行的版本控制工具,書寫良好的commit message能大大提高代碼維護的效率。但是在日常開發中由於缺少對於commit message的約束,導致填寫內容隨意、質量參差不齊,可讀性低亦難以維護。
  • Hook Git實現代碼與需求的一致性
    客戶端鉤子由諸如提交和合併這樣的操作所調用,而伺服器端鉤子作用於諸如接收被推送的提交這樣的聯網操作。 你可以隨心所欲地運用這些鉤子。鉤子都被存儲在 Git 目錄下的 hooks 子目錄中。 也即絕大部分項目中的 .git/hooks 。 當你用 git init 初始化一個新版本庫時,Git 默認會在這個目錄中放置一些示例腳本。
  • 三分鐘了解 git hooks 的原理
    $ ls -lah .git/hooksapplypatch-msg.sample pre-merge-commit.samplecommit-msg.sample pre-push.samplefsmonitor-watchman.sample pre-rebase.samplepost-update.sample
  • 優雅的提交你的 Git Commit Message
    很有意思, 能看到各種提交風格: 有用 emoji 的, 有用唐詩的, 有用隨機生成的. 風格沒有對錯, 只要能夠體現出 commit 所做的修改即可.但是最讓我印象深刻的是 @李華橋 的答案:這種東西,當然要藉助工具了,才能夠寫得即規範,又格式化,還能夠支持後續分析。
  • 編碼規範,代碼提交規範全家桶之husky+lint-staged+commitlint
    lint-staged,一個僅僅過濾出 Git 代碼暫存區文件(被 git add 的文件)的工具;這個很實用,因為我們如果對整個項目的代碼做一個檢查,可能耗時很長,如果是老項目,要對之前的代碼做一個代碼規範檢查並修改的話,這可能就麻煩了,可能導致項目改動很大。所以這個 lint-staged,對團隊項目和開源項目來說,是一個很好的工具,它是對個人要提交的代碼的一個規範和約束。
  • 【第1213期】優雅的提交你的 Git Commit Message
    很有意思, 能看到各種提交風格: 有用 emoji 的, 有用唐詩的, 有用隨機生成的. 風格沒有對錯, 只要能夠體現出 commit 所做的修改即可.但是最讓我印象深刻的是 @李華橋 的答案:這種東西,當然要藉助工具了,才能夠寫得即規範,又格式化,還能夠支持後續分析。
  • 前端必須知道的 Git 和 SVN 的區別
    pullsvn updatepushgit push-查看工作狀態git statussvn status創建分支git branch <分支名>svn cp <分支名>刪除分支git branch -d <分支名>svn rm <分支名>分支合併git merge <分支名>svn merge <分支名>工作區差異git differ
  • 如何規範你的Git commit?
    團隊開發中有沒有遇到過讓人頭疼的git commit?本文分享在git commit規範建設上的實踐,規定了commit message的格式,並通過webhook在提交時進行監控,避免不規範的代碼提交。文末福利:在線IT技能測試。Git每次提交代碼都需要寫commit message,否則就不允許提交。
  • Git如何提交代碼
    git學習篇(2)這是學習Git的第二篇筆記,今天來講講Git提交代碼的使用命令。
  • Git科普文,Git基本原理&各種騷操作
    git log --graph --pretty=oneline --abbrev-commit# 統計倉庫提交排名前5git log --pretty='%aN' | sort | uniq -c | sort -k1 -n -r | head -n 5# 查看指定用戶添加代碼行數,和刪除代碼行數git log --author="iisheng
  • Git-提交更新
    在此之前,請一定要確認還有什麼修改過的或新建的文件還沒有 git add 過,否則提交的時候不會記錄這些還沒暫存起來的變化。所以,每次準備提交前,先用 git status 看下,是不是都已暫存起來了,然後再運行提交命令 git commit:$ git commit這種方式會啟動文本編輯器以便輸入本次提交的說明。
  • 在Gitlab中規範提交的commit message的格式
    我們有時候會遇到開發提交的千奇百怪的commit信息,這樣給代碼更新追蹤溯源增加了麻煩,並且我們使用的gitlab ci 會使用commit信息判斷構建步驟,所以有必要為GitLab 增加自定義 Commit 提交格式檢測介紹Git 支持在不同操作上執行的鉤子。
  • Git commit message 規範
    git是現在市面上最流行的版本控制工具,書寫良好的commit message能大大提高代碼維護的效率。但是在日常開發中由於缺少對於commit message的約束,導致填寫內容隨意、質量參差不齊,可讀性低亦難以維護。在項目中引入commit message規範已是迫在眉睫。# 用什麼規範?
  • 【Git】675- 讓你的 commit 更有價值
    git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset'用工具實現規範提交上面介紹了規範提交的格式,如果讓各位同學在 git commit 的時候嚴格按照上面的規範來寫,首先心智是有負擔的,得記住不同的類型到底是用來定義什麼的,subject
  • Git 基本原理介紹
    請注意接下來的內容非常重要,若你理解了 Git 的思想和基本工作原理,用起來就會知其所以然,遊刃有餘。在學習 Git 時,請儘量理清你對其它版本管理系統已有的認識,如 CVS、Subversion 或 Perforce, 這樣能幫助你使用工具時避免發生混淆。儘管 Git 用起來與其它的版本控制系統非常相似, 但它在對信息的存儲和認知方式上卻有很大差異,理解這些差異將有助於避免使用中的困惑。