git flow 實戰經驗談 part2 - 可能更好的 gitflow

在上一篇 part 1 中指出了 gitflow 帶來的不方便,這篇文章會介紹目前團隊採用的方式,原則很簡單—所有的新增及修正都基於 master 分支

在開始以前,你必須對 git 有基本的了解,包括 (no-)fast-forward merge 及 rebase 的觀念。

最單純的情況(無環境因素)

假設沒有開發環境的需求,所以移除了 develop 分支。

A 是上一次出版的 commit,可以看到所有分支(feature/release/hotfix)都是由此 commit 出發。

# 每次產生新 branch 之前
git checkout master
# features
git checkout -b feature/1
git checkout -b feature/2
# release
git checkout -b release/v0.1.0
# hotfix
git checkout -b hotfix/v0.0.1

在兩個 feature branch 開發差不多之後,merge 進 release

git checkout release/v0.1.0
git merge feature/1
git merge feature/2

修正或確認沒有 bug 之後,merge 回去 master 加上 tag 完成這次開發流程。

git checkout master
git merge release/v0.1.0
git tag -a v0.1.0

AA' 也可以看出,整個開發流程是一個完整的循環。

如何處理 hotfix

在正式環境或版本出現緊急要修正的東西就會 hotfix,對開發流程來說,就表示 master 變了,這時候根據目前開發的狀況可以有三種選擇:

  1. 如果你本地端有開發中的 feature 分支,可以 rebase 到 C,可以想成 AC 取代,然後繼續流程。
git checkout feature
git rebase master
  1. 如果 feature 分支已經上到遠端或在進行 code review 了,就不太適合 rebase(因為整個分支的 commit 會 rewrite),這時要 merge master
git checkout feature
git merge master
  1. 如果已經作出了 release 分支就可以直接把 master merge 進去。
git checkout release
git merge master

處理相依性

現在的情況是如果這次的出版週期有一個功能 feature/3,而同一出版週期的 feature/1feature/2 都需要它的功能。

一個作法可以把兩個分支都 rebase 到 feature/3。但我比較推薦用 merge,有兩個好處:

  1. 不會 rewrite commit,
  2. 如果最後你不想要 feature/3 也比較容易 revert。

merge 的結果如下圖。
A 會有 feature/2feature/3,而 B 會有全部三個分支的功能;這樣也表示說無論你只出版 feature/1 或者 feature/2,都會有 feature/3 的內容。

上面是各個 feature 分別都 merge feature/3,有人會問說怎麼 feature/3 不直接進去 release 就好?我是覺得在每個 feature 分支都可以看到該功能相關的 commit 會比較明確,但相對的比較繁瑣,直接進去 release 看整合效果的作法當然也可以,所以可以依情況作調整。

有開發環境的情況

這邊加入了 develop 分支
develop 對應到 test 環境(如 A),release 對應到 staging 環境。

完成出版後,develop 可以 merge master

git checkout develop
git merge master

這邊可以發現它會 fast forward,如 B
ps. 發現很多人不懂 fast forward 是什麼意思,請一定要先了解它

實務中會發生的情況

上面講的只是理想,現實中的開發尤其是用戶端的應用程式,很常出現一種情況 — 已經進到 develop 的 feature 沒有要出版 🙄🙄🙄。

下面圖表所表示的情況是:在此開發週期中同時開發了 feature/1/2,並已經在 test 環境上讓 QA 驗證上述兩個功能。接著要出版本時,PM 說 feature 2 先不要上,因此只發表 feature 1。
A 這點同時有 feature 1 跟 2,並且在 test 環境上。

B 只 merge 了 feature/1,會部屬到 staging 環境讓 QA 驗證後出版。

這邊有一件事要提醒:在 A 驗證沒問題,並不表示 B 沒問題,因為 B 沒有 feature/2 的東西,所以即使 test 環境驗證 ok,出版前仍必須在 staging 驗證一次。

好,接下來的問題就只剩下怎麼處理 developfeature/2 這兩個分支。
圖中實色的部份是 develop 目前的內容。有 feature/1feature/2feauture/1 已經出版了就不討論。

(2018/4/20 更新,原本的想法是直接重新從 master 開一個 develop 分支,再強制覆寫回 origin,理由是 develop 只對應到 CI,因此是可拋棄的。但後來想想,推到 remote 的分支不應該任意覆寫,因此還是保留 develop 的歷史比較恰當。)

develop 及未出版的 feauture/2 都需要 master 中的內容,因此他們分別 merge master 即可。要注意因為 feature/2 可能會新增內容並 merge 進去 develop,因此不可以 rebase master

如果你堅持要用 develop 來開發

當然也可以。但有個前提,你不能再把 develop 對應到 CI 的測試環境,要取另一個名稱,下圖中該分支是命名為 test-env

從這個圖表可以看出幾件事:

  • 除了 hotfix 之外其餘分支都由 develop 建立
  • tag 仍然作在 master 上面
  • master 會是 develop 的前一個 commit,而且絕對可以 fast-forward

因為 hotfix 仍然從 master 產生而不是 develop,這表示因為堅持 develop 這個分支名稱必須多加這一項常規,個人認為是多此一舉。可行但不推薦。

結語

從上面的介紹,可以看出,即使規範了一套常規,在很多時候,還是有需要因應現實情況作調整的地方:

  • 在 hotfix 或處理相依性時,可以選擇用 rebase 或者 merge
  • 要不要保留對應到測試環境的分支的歷史
  • 整個開發建構在其之上的基礎分支要不要命名為 master

所以一切都是團隊的選擇,沒有對錯也沒有一定要怎麼作。

這篇文章我盡量列出了會遇到的情境和可能的應對方法,給大家參考。如果有什麼部分是我沒有思考到的,也歡迎跟我反應。

Happy coding!