Skip to content

Latest commit

 

History

History
104 lines (74 loc) · 7.53 KB

commit.md

File metadata and controls

104 lines (74 loc) · 7.53 KB

Git commit 的藝術

git commit 給誰看?

這邊講的不是 commit message,而是 commit changes,就是實際被更動的內容到底是什麼。
我個人認為 commit 就是給人看的,不管是 reviewer 或是 debug 的人或是未來的自己。
所以當一個 PR 送出來給人 review 時,最重要的就是要讓人家看懂你到底做了什麼。
就好像我們程式要寫得易讀的道理是一樣的,我不希望看到一大篇紅紅綠綠不知道到底改了什麼,必須把整份程式再人工解讀一遍才能決定這個 PR 能不能接受。
所以拆 commit 我認為是必要的。

一個好閱讀的 PR 可以:

  • 加快 review 的速度。
  • 避免不易解讀的 commit 而造成對實際改動的認知上的錯誤。
  • 就像抽象過後的 function,如果某一部分不需要是可以被抽離的。
  • 很多,請參閱以下範例自行感受。

依照可被抽離的方式分開 commit

當你一堆更動之中,有部分更動是可以被獨立出來的,那就可以獨立出來 commit。
比如大一點的就是這次要改兩個 component ,且是兩種不一樣的功能,就可以依 component 更動為單位去 commit。
這樣如果發現某個功能其實是多餘的,那不用加一個 commit 去針對多出來的地方再逆回去,只要把該 commit 移除就好了。
如果不能修改歷史,那也可以針對該 commit 做 revert 的動作即可。
如果這兩個 component 的改動被混在一起,那處理這件事情的方法就只能把做過的事情人工再逆回去,這行為差不多是做了 3 個功能了。

同理,如果是改兩個功能,每個功能牽涉多個 component,則應該以功能為單位去 commit。
因為當功能撤銷時是一次要把這些 component 的更動都逆回去,所以以功能為單位去 commit 就可以透過操作 commit 來達到效果,不用人工再逆回去。

以此類推,主要就是以到時候發生了什麼事的話,我們不要以人工的方式去把當初做過的事情再逆向做一次,而是透過 git 處理 commit 的各式各樣的方法來處理。
這樣不僅效率高,還可以避免人工逆向工程中的人為錯誤。

修 bug 與 refactor 要分開

常常修 bug 的時候會發現該區塊的程式設計的不好,想要重構一下讓它變好。
但是如果修復跟重構混在一起的話,那麼這個 commit 會失焦,因為做太多事情了。

一種是先 commit 一個修復的樣子,再 commit 重構的樣子,或是兩者反過來也可以。
目的是當我們看修復的 commit 時可以清楚明瞭的知道該問題點是怎麼被修復的。
同理當我們看重構時只要專注在改動前跟改動後的行為應該要一致就好了。
所以每個 commit 都有明確要 review 的重點,進而讓 review 可以更快更準確。

當然建議先修復再重構,畢竟如果重構後的設計不被接受,只要拿走就可以了。
如果反過來的話,那麼這時候又要再修一次。
只有 bug 的原因是程式設計層面的問題,所以需要先重構才會比較好修的情況才會先重構再修復。

不是你自己做的更動要分開

啥!?還有 commit 不是自己做的?
這邊指的是像 npm install,或是 formatter,或是各種工具可以幫你做出改動的東西。
通常這類改動都是透過 CLI 來完成,且可大可小。
如果混了人為的更動會很難辨別哪些是可信哪些是不可信。
所以基本上只要是 CLI 所產生的更動我就會單獨 commit,包含 cp 或是 sed 之類的都算,且會用該指令作為 commit message。

這樣的好處是基本上我們可以忽略裡面的更動,因為那是 CLI 做的,不是人為的,所以基本上是可以完全相信。
真正要 review 的是 CLI 指令有沒有打錯就好了。
而且這樣做還有個好處就是非當事人可以按照指令重現出一模一樣的更動,這在 PR 有異議的時候非常實用。

複製過來改要分開

這是上一例的衍伸,因為太常見了所以要特別聲明。
很常看到這新的 component 跟之前做過的很像,拿來改就好了,然後 commit 上來是一個全綠色的更動。
這時候要我怎麼相信是拿之前的 component 來改的?我只看到一大片綠色,我得人工去讀完整個 component 運作正常才有信心接受這個 PR。
聰明一點的就是透過一些 diff 的工具把兩個 component 來比較,但你也得先知道做的人是拿什麼東西來改的。
與其這樣不如先 commit 一個 cp a.vue b.vue,那麼這一堆綠綠的就可以完全不用看了,因為很明確就是複製來的。
接著才把不要的東西拿掉,改成新的東西,這樣 review 的人就可以針對實際的更動去做審查,不用重審整個 component。

如果拿掉的東西跟新增的東西是完全兩種程式碼,那建議拿掉跟新增也可以拆開 commit,這可以清楚看見不需要以及新增的部分。
不然紅紅綠綠的修改其實是沒有邏輯的,除非是類似的程式碼那合在一起才有意義。

但這件事情根除的方式應該是抽象 component ,而不是複製過來改。

改名字要分開

有時候有人看不慣變數命名,在做實際更動時還會順便改名,這會造成失焦。
因為一旦一個變數改名了,所有用到這個變數的地方都要改名,但實際的更動可能會只有一點點。
所以改名也要單獨抽出來,一方面這個 commit 算是可信的,可以省略 review 的工。
若是擔心改錯名還是要 review 的話,檢查也很方便,只要專注於改前改後的字就可以了。

換順序要分開

有人喜歡讓程式按照某種順序排列,通常做這種事情也會有一堆紅紅綠綠,尤其是在搬 function 的時候更是可怕。

要特別提醒的是,這邊指的順序要抽出來是限於改順序前跟改順序後都是同樣的運作,就是單純改順序的狀況。
如果你的狀況是必須得改順序才能讓程式運作,那就另當別論。

縮排要分開

這也是容易產生大量更動的情況。
雖然現在很多 review 用的工具已經可以聰明到把實際更動的部分高亮出來,但據我經驗僅限於簡單的更動才有辦法。
大部分複雜的更動還是會紅紅綠綠的看不懂在改什麼,所以還是先把實際更動 commit 後再 format 再 commit 會比較好。

這動作應該是比較多人覺得煩躁而不想做,畢竟很多編輯器在儲存時會自動幫你排版。
但試想,如果大家都可以把 commit 拆乾淨,對你我都好,不然下次你也會遇到明明是很簡單的更動卻非常難 review。
只要把儲存時自動排版改成手動用快捷鍵排版就可以了,舉手之勞對大家都好,將來 debug 看到這個 commit 也不會亂糟糟。

總結

其實說到底都是第一點的衍伸,因為上述這些舉例都是有明確目的的,所以都可以被當成個別事件來 commit。
這邊列出來的就是常見如果你混進去這些動作會造成一大片紅紅綠綠來混淆實際更動的情境。

拆 commit 主要目的就是想辦法把關鍵更動獨立出來,讓 review 的人快速且清楚的知道整個 PR 的重點是什麼。
一來效率高,二來 review 的準確性也高。
剩下的那些就是改改名縮縮排換換順序的,都是可以被忽略不用花心思去 review 的更動。
所以希望大家可以保持對 reviwer 友善的拆 commit,對未來 debug 時也是有幫助的。