淺談 Git Flow 與 commit 規範
前言
Git Flow 與 commit 一直都是許多 Git 新手的痛,畢竟一開始學習是很少會有機會碰到多人協作,因此來寫一篇筆記記錄一下什麼是 Git Flow 以及為什麼要做 commit 規範。
Git Flow
Git Flow 是在 2010 年被推出的一個觀念,注意!是觀念。
A successful Git branching model
在原文中我們可以看到這一張圖
首先我在這邊假設你已經懂什麼是 Git Branch (分支),因此上圖中的一條一條都是一個 Branch,而那條一條的並不是我們的重點,而是它上面標註的名稱
- main
master- GitHub 已於 2020/10 將 master 改叫 main,因此只要是新的儲存庫的分支都會主要改成 main,可參閱此連結。
- develop
- feature
- hotfix
- release
這五大分支就是 Git Flow 的精髓。
main
main 分支基本上可以區分為兩種狀況
代表分支名稱:main
初始化 main
這個分支是所有系統開發時的正式分支,當我們初始環境架設完畢時,也都會從 main 分支開始,但是當環境架設完畢之後就會進入正式開發階段
開發階段 main
正式開發時,我們就會禁止開發者直接 commit push 到開分支,因為 main 是一個正式部署 or 正式上線中的分支。
因此當我們環境初始化部署完畢之後,就會從 main 拉出 develop 分支,而該分支接下來就只會接受其他分支的 merge 而不會有任何直接 commit 行為這非常重要。
develop
develop 是 main 分支拉出來的開發分支,該分支是我們所有開發分支基礎分支,什麼意思呢?若我們需要開發什麼功能,例如新增文章功能,就會從 develop 分支拉出 feature 分支(稍後會介紹)。
因此通常來講 main 與 develop 都會長期在 Git 上,因此這兩個又稱之為長期分支,而這個分支我們也會盡可能避免直接 commit,當功能開發完畢之後就會合併回 develop 分支,例如 feautre 合併回 develop。
代表分支名稱:develop
feature
feautre 這個分支會從 develop 拉出來,而在這邊開分支時必須注意一件事情,千萬不要直接輸入 git branch feature
,如果你直接輸入這個指令還上傳到遠端儲存庫(ex: GitHub),那麼你會有很高機會被請出去喝咖啡。
主要原因是 Git 再開分支時是採用結構樹的概念去開,如果你直接建立一個分支叫做 feature
那就會導致其他人無法開立開發用的分支,因此正確開 feature 的方式是帶上斜線並命名預計要開發的功能,例如我今天要開發一個上傳功能,那麼命名就會是 git branch feature/upload
。
所以在開發一個專案時,你會看到一大推 feature/xxxx
是正常的。
而當 feature 功能開發完畢之後才會合併回去 develop。
最後你可能會說那 feature 不用刪除嗎?通常來講是不用,因為如果你刪除的話就會無法追蹤當初的分支,因此 feature 分支是不會刪除的(反正 GitHub 分支開免錢的)。
代表分支名稱:feature/xxxx,ex: feature/index
hotfix
這個分支稍微比較特別一點,這個分支通常只會在上線中的專案(main)出現 bug 時才會拉出來的,因此 hotfix 分支會直接從 main 拉出來,因此 hotfix 分支會專門針對 main 與 develop 分支修正。
而接下來當 hotfix 修正完畢之後就會直接 merge 回去到 main 與 develop 分支,那為什麼要回到 develop 分支呢?因為如果不回到 develop 分支的話,到時候 develop 回到 main 分支一樣會出現 bug。
而最後通常我們不會直接從 develop 分支拉 hotfix 出來,因為 develop 分支在前面有說過,它是屬於開發分支,如果你從這邊拉出來,許多功能都還沒完成及測試之前就 merge 回去 main 就很容易出現更嚴重的 bug。
代表分支名稱:hotfix
release
release 分支則是會從 develop 分支拉出來,而這個分支簡單來講就是正式上線前的測試分支,通常只會在 develop 準備要合併回到 main 時所使用的分支,因此 develop 會拉出 release,當測試通過時,就會將 release 合併到 main 與 develop,確保兩邊同步,所以 release 分支也會同時修正一些問題。
代表分支名稱:release
Git Flow 回顧
上面基本觀念吸收之後你就可以比較看得懂這張圖
當然比起文謅謅的說明,我個人會建議可以參加一些開源專案,透過實作會更清楚,因此這部分在實作上會更了解其觀念,畢竟 Git Flow 這東西說抽象是也很抽象,說不抽象也很難不抽象,而 Git Flow 有時候會因為公司性質而不同,所以這部分就要看公司自己有無自己的 Git 規範哩~
Git Commit 規範
當我們在多人開發時雖然可以透過 Git Flow 規範避免一些問題(例如:開發衝突。),但是 commit 訊息若沒有去做一些規範的話,其實在尋找一些 bug 發生點就會很困難,而且 code review 的人也會不知道你幹了哪些事情,變成必須點開程式碼一個一個去看才知道你做了什麼,所以如果你沒有一定的 commit 規範,那麼就會像我這份專案一樣
雖然圖片上看起來我都有描述我做了什麼,但是當若你是多人開發時,如果每個人都是像我這樣子填寫 commit message,那麼就會搞不清楚你目前這個「加入動態路由 title」到底是新增功能還是修正功能?
因此在國外的 AngularJS 團隊就有一篇 Git Commit Message 規範
Git Commit Message Conventions
Commit 的 type
依照 AngularJS 團隊提供的規範來講,有這些 type
- feat - 新增/修改功能 (Feature)
- fix - 修正 Bug (bug fix)
- docs - 修改/新增文件 (documentation)
- style - 修改程式碼格式或風格,不影響原有運作,例如 ESLint (formatting, missing semi colons, …)
- refactor - 重構 or 優化,不屬於 bug 也不屬於新增功能等
- test - 增加測試功能 (when adding missing tests)
- chore - 增加或修改第三方套件(輔助工具)等 (maintain)
透過這些 Commit Type 可以讓 Code Review 的人可以一眼明白目前這一個 commit 做了哪些事情,而觀看者也可以採用不同的心情去面對(囧,難不成你要我拿 code review 的方式去看 docs?)。
Commit 方式
接下來講講如何將 commit 規範導入到專案中,通常我們在上傳 commit message 之前都會輸入 git commit -m 'xxxx'
,當你導入之後你必須依照 commit 功能來改寫,例如我要新增一個上傳功能,那麼就要打 git commit -m 'feat: add to upload feature'
。
當然這是一個比較懶惰的方式,當你如果直接輸入 git commit
你會進入 commit 編輯階段(記得先 git add .
),如下圖:
依照 Git Commit Message 規範 來說,你必須將內容改成以下
1 | # 這是寫文章特別新增的 commit 測試用 |
那有可能會有人不知道該如何編輯,其實這是 vi 編輯器,因此要按下英文間的 「I
」(代表:insert
),輸入完畢之後按下「:
」號按鈕在輸入 wq
就可以儲存上傳 commit 了。
w
> 儲存q
> 退出
接下來當你上傳到遠端儲存庫時就可以看到這樣子的詳細內容,並且對應到特定 Issues
(你會發現有加上 #
並不會呈現在 GitHub 上唷~)
除此之外在看 git log
也可以非常詳細看到這個 commit 做了哪些事情
當然 commit 的規範也會因為公司的不同而變化哩。