淺談 Git Flow 與 commit 規範

前言

Git Flow 與 commit 一直都是許多 Git 新手的痛,畢竟一開始學習是很少會有機會碰到多人協作,因此來寫一篇筆記記錄一下什麼是 Git Flow 以及為什麼要做 commit 規範。

Git Flow

Git Flow 是在 2010 年被推出的一個觀念,注意!是觀念

A successful Git branching model

在原文中我們可以看到這一張圖

Git Flow

首先我在這邊假設你已經懂什麼是 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 Flow 有時候會因為公司性質而不同,所以這部分就要看公司自己有無自己的 Git 規範哩~

Git Commit 規範

當我們在多人開發時雖然可以透過 Git Flow 規範避免一些問題(例如:開發衝突。),但是 commit 訊息若沒有去做一些規範的話,其實在尋找一些 bug 發生點就會很困難,而且 code review 的人也會不知道你幹了哪些事情,變成必須點開程式碼一個一個去看才知道你做了什麼,所以如果你沒有一定的 commit 規範,那麼就會像我這份專案一樣

不清楚用途的 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 .),如下圖:

commit 編輯

依照 Git Commit Message 規範 來說,你必須將內容改成以下

1
2
3
4
5
6
7
# 這是寫文章特別新增的 commit 測試用
feat: 新增上傳功能

express add to upload feature...

# 這是搭配 GitHub 的 issues 所使用
issue #2

commit

那有可能會有人不知道該如何編輯,其實這是 vi 編輯器,因此要按下英文間的 「I」(代表:install),輸入完畢之後按下「:」號按鈕在輸入 wq 就可以儲存上傳 commit 了。

w > 儲存
q > 退出

接下來當你上傳到遠端儲存庫時就可以看到這樣子的詳細內容,並且對應到特定 Issues

超詳細 commit

(你會發現有加上 # 並不會呈現在 GitHub 上唷~)

除此之外在看 git log 也可以非常詳細看到這個 commit 做了哪些事情

log

當然 commit 的規範也會因為公司的不同而變化哩。

參考文獻

可以給點牡蠣。
Google AD