輕鬆上手約定式提交:Commitizen 初體驗

最近參加 DevOps Meetup 的活動,Speaker 提到團隊使用 Commitizen 這套工具來統一提交訊息的風格,當場就有種醍醐灌頂的感覺。我們團隊前陣子才 Suffer 在 Commit Style 分歧,知識管理效率低落,有時只有 commit 本人能看懂,而使用共同模板又太浪費時間,跟 Git 鼓勵 commit 的精神背道而馳。聽完後,真的是相見恨晚,完全命中我的痛點。

Commitizen 是由 AngularJS 的規範衍伸而來,各團隊可以依照需求自行調整,我們 Step by Step 來看看 Commitizen 的效果如何。

Install Node.js

因為 Commitizen 是使用 Node.js 開發,不免俗的,要裝一下 Node.js,Ubuntu 的安裝方式是

sudo apt install nodejs
sudo apt install npm

確認是否有安裝完成

ken@ken-Lenovo-ideapad-330-15ICH:~/git/git$ node -v
v8.10.0
ken@ken-Lenovo-ideapad-330-15ICH:~/git/git$ npm -v
3.5.2

Install Commitizen

接著使用 Node.js 的 Package Management 工具 npm 來安裝 Commitizen

npm install -g commitizen
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

-g 是全域安裝的意思,如果沒有需要針對 Project 制定 Style,用全域安裝即可,.czrc 則是用來設定 template 的路徑。

Git Format

在預設的 format 中,commit comment 由三個部分組成

<head>
<body>
<footer>

讓我們看一個簡單的例子

commit 4030e040b6044de68b2750702a5b6065c887960c
Author: kenwschen <ken*****@[gmail.com](mailto:[email protected])>
Date:   Thu Nov 28 22:51:44 2019 +0800

feat(libhello): add hello file

hello, this is a longer description

fix #100

第一行是 head,也就是 title,通常會由

<type>(<scope>): <subject>

在本例中可以看成這個 commit 為新增功能(feature),更改的 module 是 libhello,簡單描述是 add hello file。

中間行是 body,代表詳細的描述,通常會說明要解決的問題是什麼,具體做法是什麼等等。

最後一行是 footer,通常會標明相關的 issue,如果沒有將 issue 跟 git 結合在一起的話,footer 可以不標。

Git cz

實際執行 Commitizen,使用 git cz 來取代 git commit

可以看到,Commitizen 會很貼心顯示選單讓 user 選擇,只要照著問題跟選單將答案填入就好,就是這麼簡單。

來看一下提交的結果

ken@ken-Lenovo-ideapad-330-15ICH:~/git$ echo hello > hello     
ken@ken-Lenovo-ideapad-330-15ICH:~/git$ git add .              
ken@ken-Lenovo-ideapad-330-15ICH:~/git$ git cz                 
[email protected], [email protected]                  
                                                                
? Select the type of change that you're committing: feat:        A new feature                                                     
? What is the scope of this change (e.g. component or file name): (press enter to skip) libhello                                   
? Write a short, imperative tense description of the change (max 84 chars):                                                        
    (14) add hello file                                               
? Provide a longer description of the change: (press enter to skip)
    hello, this is a longer description
? Are there any breaking changes? No
? Does this change affect any open issues? No
[master 2e1ea38] feat(libhello): add hello file
    1 file changed, 1 insertion(+)
    create mode 100644 hello

ken@ken-Lenovo-ideapad-330-15ICH:~/git$ git log
commit 2e1ea3868dcf972c2499378ee9d5b3ac7ab654b6 (HEAD -> master)
Author: kenwschen <[ken*****@gmail.com](mailto:[email protected])>
Date:   Fri Nov 29 00:40:31 2019 +0800

feat(libhello): add hello file

hello, this is a longer description

是不是太美了!

Customize Format

如果專案有自訂格式,例如需要標註修改方式、修改目的等等,可以怎麼做?Commitizen 支援許多模板,其中 cz-customizable 有讓 user 自訂選項的彈性,先安裝起來

sudo npm install -g cz-customizable
echo '{ "path": "cz-customizable" }' > ~/.czrc

將配置項的範例複製到家目錄

cp /usr/local/lib/node_modules/cz-customizable/cz-config-EXAMPLE.js ~/.cz-config.js

打開配置文件,可以看到其中有許多配置設定,假設現在需要新增一個互動問答,讓 user 輸入 commit 的 purpose,可以在其中加入

    messages: {
        type: "Select the type of change that you're committing:",
        scope: '\nDenote the SCOPE of this change (optional):',
        customScope: 'Denote the SCOPE of this change:',
        subject: 'Write a SHORT, IMPERATIVE tense description of the change:\n',
        body: 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n',
        **bodyPurpose: 'The purpose of the change:\n',**
        breaking: 'List any BREAKING CHANGES (optional):\n',
        footer: 'List any ISSUES CLOSED by this change (optional). E.g.: #31, #34:\n',
        confirmCommit: 'Are you sure you want to proceed with the commit above?',
      },

其中 bodyPurpose 這行是新加入的選項。

接著修改問句文件

sudo vi /usr/local/lib/node_modules/cz-customizable/questions.js

在其中加入 bodyPurpose

    ...
    messages.body =
          messages.body || 'Provide a LONGER description of the change (optional). Use "|" to break new line:\n';
        **messages.bodyPurpose = messages.bodyPurpose || 'The purpose of the change:\n';**
        messages.breaking = messages.breaking || 'List any BREAKING CHANGES (optional):\n';
    ...

    ...
          {
            type: 'input',
            name: 'body',
            message: messages.body,
          },
          **{
            type: 'input',
            name: 'bodyPurpose',
            message: messages.bodyPurpose,
          },**
    ...

然後修改 commit 生成文件,將 bodyPurpose 加入

    let body = wrap(answers.body, wrapOptions) || '';
    **body = body + (wrap(answers.bodyPurpose, wrapOptions) || '');**
    body = addBreaklinesIfNeeded(body, config.breaklineChar);

現在來看一下修改的成果

而實際的 log 是

commit 3cc8c9aa4a9084fb4b8faa651d98b5376f24e4d6 (HEAD -> master)
Author: kenwschen <[[email protected]](mailto:[email protected])>
Date:   Fri Nov 29 19:56:58 2019 +0800

feat(libhello): add hello file

add a new file to test commitizen tool. hello is a lib that can say "hello"

小結

有時候程式寫一寫,會忘記升級自己的工具,很多時候團隊遇到的問題不是人的問題,而是工具的問題,我們應該要盡量 align 目標,用工具時時提醒出發點在哪。commit comment 原本是為了溝通而存在,而 Commitizen 可以幫我們更好地去做這件事。

Reference

Read more

Weekly Issue 第 27 期:Nvidia 收購 Groq

從 Windsurf 的案件後,我一直在想,新創成立時,支持創辦人的早期員工與投資人,是不是能得到合理的報酬?Groq 收購案給出很多細節,告訴我們即使是 Acquhire,也還是能盡可能公平。 改變世界很重要,但使用的方式也很重要。 🗞️ 熱門新聞 Nvidia deal a big win for Groq employees and investors Groq 收購案的消息出來後,我關心的事情是:這跟 Windsurf 的案子有什麼不同?早期投資人跟團隊有得到回報嗎? 先講結論:如果消息正確,該得到的報酬都有得到,皆大歡喜。但我覺得 Acquhire 存在太多灰色地帶,應該要納入監管,不是每家收購發起者跟創辦人都有同樣的素質。 按照 Axios 的說法,輝達付出的 200 億將被視為估值分配給股票持有人,90% 員工會加入輝達,到期股票會變現,

By Ken Chen

Weekly Issue 第 26 期:AI 批評指南

最近在讀《高效槓桿力》,書中提出一套變革管理框架:「尋找關鍵支點,重新配置資源。」當然,書裡給出很多案例,說明如何找到支點,只是我同時在想,如何將他們帶到我面對的情境呢? ✨ 科技觀點 Pluralistic: The Reverse-Centaur’s Guide to Criticizing AI 看到有人非常認真討論事情,即使是批評 AI,都會讓我有興趣。 附上一些我的觀點: 1) 成長型公司聽起來很美好,每個人都會想待在那,但當它變成前提時就是另一回事了。很多決策都會以成長為基礎,最後就是投資人跟企業都沒辦法接受不成長的代價。 2) 常常在爭論 AI 是否會取代工作,看的是 AI 的兩個面向,賦能與自動化,哪個會更符合當前情境。贊同賦能的人會認為 AI 帶來生產力的解放,並創造價值,可是實際上呢? 3) 很多人提過 AI 的解壓縮 / 壓縮特性,特別是在履歷或信件應用。

By Ken Chen

Weekly Issue 第 25 期:Slack 基礎設施爭議

因為地緣政治議題,我們會關心資料存放的地點是否足夠安全,即使當使用者被盯上,他仍然可以放心資料足夠隱密。這也是為什麼當網路上傳出 Slack 台灣的資料轉移到阿里雲時,會引起爭議的原因。 Slack 已經出面澄清並無此事,這也讓我們反思,當軟體業面臨這類公關危機時,應該要揭露到什麼程度。 🗞️ 熱門新聞 Slack 在臺服務將移轉至中國? Salesforce:臺灣用戶使用全球基礎設施,與阿里巴巴無關 前幾天 Salesforce 傳出要將 Slack 台灣資料轉移到阿里雲,立刻引起一陣討論,有 Salesforce 的人出來澄清,說沒有這回事。 「台灣市場一直以來都是採用 Global Infrastructure 全球基礎設施。簡單說,台灣用戶的資料是儲存在美洲或亞太區(如日本),跟中國的阿里雲在物理和邏輯上都是完全切開的。 」 讓我有興趣的是,Salesforce 沒有說他們是用哪個雲平台。我們以前有次遇到類似情況,也討論到是否揭露使用平台。當時我持反對意見,認為只需要揭露「使用全球基礎設施」已經夠了,頂多說非中國廠商的服務就好,不需要也不應該說明具體是哪個。

By Ken Chen

Weekly Issue 第 24 期:網路的精神高地

前陣子去了雪梨一趟,跟布里斯本或台北都形成有趣的對比,旅行中也不斷在想,一座城市如何發展出自己的文化?這有點像是網路平台如何形成聚落,而又如何消亡。 很喜歡本期談知乎的一篇文章,理想主義的光輝是最吸引人的,我常在想,有沒有辦法將那座「看不見的城市」帶到真實世界中。 🗞️ 熱門新聞 A ChatGPT prompt equals about 5.1 seconds of Netflix 看到 Simon Willison 提到,如果 Sam Altman 的資訊是對的,每個 LLM 提問相當於 5.1s 的 Netflix 影片耗能。 計算的需求讓輝達跟台積電挖到金礦,那電力需求又會讓誰挖到金礦呢? ✨ 科技觀點 我们失去的不只是知乎,而是中文互联网的精神高地 「那时的知乎,更像“思想沙龙”,而非“内容平台”。」 昨天跟朋友聊天,

By Ken Chen