1. 引言
思想,因人而異,難以重複
寫程式碼時,每個人的習慣是不一樣的,所以,引入了程式碼規範,為了省力,引入了自動格式化程式碼工具,前端工程中比較典型的自動格式化程式碼工具如:Prettier · Opinionated Code Formatter
日常多人協作寫程式碼時,需要不斷提交、推送、拉取程式碼,提交程式碼時,需要輸入一段Message來表述這次提交變更,思想因人而異,每個人寫的Message都風格各異,所以,引入了提交規範,以及引入了提交規範輔助工具
可以檢視一些經典開源專案的提交歷史:
這些提交資訊看起來比較易讀且工整,表達資訊較為明確,整體較為規範
Git是常用的版本控制工具,本文描述使用Husky、commitlint等工具實現Git程式碼提交規範
2. Git Hooks
如同其他許多的版本控制系統一樣,Git 也具有在特定事件發生之前或之後執行特定指令碼程式碼功能(從概念上類比,就與監聽事件、觸發器之類的東西類似),Git Hooks 就是那些在Git執行特定事件(如commit、push、receive等)後觸發執行的指令碼,掛鉤是可以放置在掛鉤目錄中的程式,可在git執行的某些點觸發動作
使用Git Hooks可以實現:
- 多人開發程式碼語法、規範強制統一
- commit message 格式化、是否符合某種規範
- 測試用例的檢測
- 程式碼提交後的專案自動打包(git receive之後) 等
更為詳細的Git Hooks介紹與使用可以參考:
3. Husky
使用Git Hooks可以實現程式碼格式化、提交資訊規範化,但是需要手動編寫指令碼,而Husky就是簡化編寫這些指令碼的工具
Husky的官網:Husky - Git hooks (typicode.github.io)
參考官網,可以快速使用Husky:
安裝以及初始化:
npx husky-init && npm install
在專案中使用時,如果沒有package.json
檔案會執行失敗,需先執行npm init
執行完上述命令後,可以發現專案中出現了新的資料夾.husky
,下面有一個pre-commit
:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
其作用主要是在commit之前執行npm test
為什麼會執行這個命令呢?因為在<專案名>/.git/config 中新配置有:
hooksPath = .husky
即,Git Hooks的目錄變更為.husky
,Git處理時會自動應用該目錄中的指定的命令(如,提交前執行npm test
)
接下來,只需要安裝程式碼格式化工具並在pre-commit
中寫入執行命令即可提交前自動格式化
4. ESLint
ESLint時常用的程式碼格式化工具,常用的還有Prettier
官網為:Find and fix problems in your JavaScript code - ESLint - Pluggable JavaScript Linter
參考官網的手冊:Getting Started with ESLint - ESLint - Pluggable JavaScript Linter
可以快速的使用ESLint:
安裝:
npm init @eslint/config
然後根據提示進行操作即可安裝完成
格式化檔案程式碼:
npx eslint yourfile.js
執行npx eslint <yourfile.js>
即可格式化程式碼檔案
此處,當然可以提交前格式化所以程式碼檔案,但是,每次提交的檔案修改只是部分,並不需要把所有的程式碼檔案進行格式化操作
只需把提交修改的檔案,即暫存區的檔案進行格式化操作即可
5. lint-staged
見字識義,lint-staged工具就是對暫存區的程式碼檔案進行格式化
GitHub站點為:okonet/lint-staged: ?? — Run linters on git staged files (github.com)
根據站點的操作指南:okonet/lint-staged: ?? — Run linters on git staged files (github.com)
可以快速的使用lint-staged:
安裝:
npm install --save-dev lint-staged
配置引數:
配置引數可以參考示例:okonet/lint-staged: ?? — Run linters on git staged files (github.com)
即,在 package.json
中新增"lint-staged": {}
,最後 package.json
形如
{
"name": "My project",
"version": "0.1.0",
"scripts": {
"my-custom-script": "linter --arg1 --arg2"
},
"lint-staged": {
"*.{js,jsx}": "eslint"
}
}
然後,在pre-commit
中寫入執行命令即可提交前自動格式化程式碼:
npx lint-staged
接下來提交規範化
6. commitlint
commitlint是一個檢查提交是否符合規範的工具
官網為:commitlint - Lint commit messages
參考官網,可以快速的使用commitlint:
安裝:
npm install @commitlint/cli @commitlint/config-conventional
配置:
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
注意:
- 如果
commitlint.config.js
檔案不是utf8編碼,請儲存為utf8編碼 - 此命令不應使用CMD來執行
執行命令寫入husky:
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"
此時commitlint 具有預設的提交規範,參考:commitlint/@commitlint/config-conventional at master · conventional-changelog/commitlint (github.com)
7. Commitizen & cz-git
commitizen是基於Node.js的 git commit
命令列工具,輔助生成標準化規範化的 commit message,GitHub站點為:commitizen/cz-cli: The commitizen command line utility. #BlackLivesMatter (github.com)
cz-git:是一款工程性更強,輕量級,高度自定義,標準輸出格式的 commitizen 介面卡,官網為:快速開始 | cz-git (qbb.sh)
參考上述兩個官方文件,可以快速的使用這兩個工具:
安裝:
npm install -D commitizen cz-git
配置:
修改 package.json
指定使用的介面卡並新增 commit
指令:
{
"scripts": {
"commit": "git-cz"
},
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
}
此時,由於具有預設配置,在執行git add
的情況下,直接執行npm run commit
,就可以根據提示一步步的完善 commit msg 資訊:
npm run commit
> git-hooks@1.0.0 commit
> git-cz
cz-cli@4.3.0, cz-git@1.6.1
? Select the type of change that you're committing: Use arrow keys or
type to search
> feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing tests
(Move up and down to reveal more choices)
當然,可以根據:配置模板 | cz-git (qbb.sh),進行進一步的配置
筆者從下面文件中複製了一份配置:
commitlint.config.js
檔案:
module.exports = {
extends: ['@commitlint/config-conventional'],
prompt: {
messages: {
type: '選擇你要提交的型別 :',
scope: '選擇一個提交範圍(可選):',
customScope: '請輸入自定義的提交範圍 :',
subject: '填寫簡短精煉的變更描述 :\n',
body: '填寫更加詳細的變更描述(可選)。使用 "|" 換行 :\n',
breaking: '列舉非相容性重大的變更(可選)。使用 "|" 換行 :\n',
footerPrefixesSelect: '選擇關聯issue字首(可選):',
customFooterPrefix: '輸入自定義issue字首 :',
footer: '列舉關聯issue (可選) 例如: #31, #I3244 :\n',
generatingByAI: '正在透過 AI 生成你的提交簡短描述...',
generatedSelectByAI: '選擇一個 AI 生成的簡短描述:',
confirmCommit: '是否提交或修改commit ?'
},
// prettier-ignore
types: [
{ value: 'feat', name: '特性: ✨ 新增功能', emoji: ':sparkles:' },
{ value: 'fix', name: '修復: ? 修復缺陷', emoji: ':bug:' },
{ value: 'docs', name: '文件: ? 文件變更', emoji: ':memo:' },
{ value: 'style', name: '格式: ? 程式碼格式(不影響功能,例如空格、分號等格式修正)', emoji: ':lipstick:' },
{ value: 'refactor', name: '重構: ♻️ 程式碼重構(不包括 bug 修復、功能新增)', emoji: ':recycle:' },
{ value: 'perf', name: '效能: ⚡️ 效能最佳化', emoji: ':zap:' },
{ value: 'test', name: '測試: ✅ 新增疏漏測試或已有測試改動', emoji: ':white_check_mark:' },
{ value: 'build', name: '構建: ?️ 構建流程、外部依賴變更(如升級 npm 包、修改 vite 配置等)', emoji: ':package:' },
{ value: 'ci', name: '整合: ? 修改 CI 配置、指令碼', emoji: ':ferris_wheel:' },
{ value: 'revert', name: '回退: ⏪️ 回滾 commit', emoji: ':rewind:' },
{ value: 'chore', name: '其他: ? 對構建過程或輔助工具和庫的更改(不影響原始檔、測試用例)', emoji: ':hammer:' }
],
useEmoji: true,
emojiAlign: 'center',
useAI: false,
aiNumber: 1,
themeColorCode: '',
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: 'bottom',
customScopesAlias: 'custom',
emptyScopesAlias: 'empty',
upperCaseSubject: false,
markBreakingChangeMode: false,
allowBreakingChanges: ['feat', 'fix'],
breaklineNumber: 100,
breaklineChar: '|',
skipQuestions: [],
issuePrefixes: [{ value: 'closed', name: 'closed: ISSUES has been processed' }],
customIssuePrefixAlign: 'top',
emptyIssuePrefixAlias: 'skip',
customIssuePrefixAlias: 'custom',
allowCustomIssuePrefix: true,
allowEmptyIssuePrefix: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: '',
defaultIssues: '',
defaultScope: '',
defaultSubject: ''
}
}
此時在執行git add
的情況下,執行npm run commit
:
PS E:\Code\test\Git-hooks> npm run commit
> git-hooks@1.0.0 commit
> git-cz
cz-cli@4.3.0, cz-git@1.6.1
? 選擇你要提交的型別 : Use arrow keys or type to search
❯ 特性: ✨ 新增功能
修復: ? 修復缺陷
文件: ? 文件變更
格式: ? 程式碼格式(不影響功能,例如空格、分號等格式修正)
重構: ♻️ 程式碼重構(不包括 bug 修復、功能新增)
效能: ⚡️ 效能最佳化
測試: ✅ 新增疏漏測試或已有測試改動
(Move up and down to reveal more choices)
根據提示執行即可提交commit
8. 參考資料
[1] Git - githooks Documentation (git-scm.com)
[2] GitHook 工具 —— husky介紹及使用 - 較瘦 - 部落格園 (cnblogs.com)
[3] Husky - Git hooks (typicode.github.io)
[4] Find and fix problems in your JavaScript code - ESLint - Pluggable JavaScript Linter
[5] okonet/lint-staged: ?? — Run linters on git staged files (github.com)
[6] conventional-changelog/commitlint: ? Lint commit messages (github.com)
[7] commitlint - Lint commit messages
[8] commitizen/cz-cli: The commitizen command line utility. #BlackLivesMatter (github.com)
[9] cz-git | 一款工程性更強,輕量級,高度自定義,標準輸出格式的 Commitizen 介面卡 (qbb.sh)