昨天,我們把本機的存檔送上 GitHub,也看懂了一個基本協作流程:
功能分支(Feature Branch)
↓
git push
↓
拉取請求(Pull Request,PR)
↓
審查(Review)
↓
合併(Merge)
到這裡,好像已經可以跟隊友一起開發了。
但 BuJo 真的開始多人合作後,我才發現另一件事:
會開分支,不代表大家自然會用同一套方式開分支。
如果每個人都照自己的習慣來,有人從 main 開功能,有人從 dev 開功能,有人做完直接合回正式分支,有人修程式錯誤(Bug)又不知道要同步到哪裡。
每個 Git 指令單獨看可能都沒錯。
但整個專案會開始變得很難管理。
所以多人協作時,分支不只是把程式碼分開放而已。
更重要的是,團隊要先講清楚:
一份修改要從哪裡開始、先去哪裡被整合和檢查,最後才怎麼進到正式版本。
這就來到今天的主題:
Git Flow(Git 分支工作流程)。
Git Flow 是一套經典的 Git 分支模型。
它不是一個新的 Git 指令,也不是 GitHub 才有的功能。
比較精準地說,Git Flow 比較像一套開發流程參考:它提供一種分支規劃方式,但實務上每個團隊會依照專案規模、發布節奏和部署方式調整,不一定要完整照做。
它替團隊回答這幾個問題:
平常開發要在哪條分支?
新功能要從哪裡開?
修完後要合回哪裡?
準備發布時要怎麼整理?
正式環境出問題時,要從哪裡修?
如果 Day11 講的是「我怎麼在自己的電腦裡留下版本」,Day12 講的是「我怎麼把版本送到 GitHub 跟別人協作」,那 Day13 的重點就是:
大家都會開分支之後,團隊要約定分支怎麼使用。
我覺得可以先用一句話記:
會 Git,是個人能力;Git Flow 則是在幫團隊把分支規則講清楚。
Git Flow 裡常見的分支角色,可以分成兩大類:
長期分支
- master / main
- develop
短期分支
- feature/*
- release/*
- hotfix/*
長期分支會一直存在,像是專案裡固定的主線。
短期分支則是為了某個任務暫時開出來,任務完成後通常會合回對應的目標分支,再把這條短期分支刪掉。
如果繼續用前幾天的遊戲比喻來想:
main 像正式公開的主線進度develop 像下一版正在整合中的主線feature/* 像平常開新功能的支線任務release/* 像正式上線前的準備區hotfix/* 像正式版本出問題時的緊急修復線重點不是把名字背起來。
重點是看懂:
每一種分支都有自己的責任,以及它應該從哪裡來、回到哪裡去。
在 Git Flow 的原始模型裡,正式分支叫 master。
現在很多專案會改用 main,意思可以先理解成同一個位置:
放穩定、可發布版本的地方。
這條分支通常代表可正式發布(Production-ready),也就是隨時可以部署到正式環境的狀態。
所以一般功能開發不會直接在這裡進行。
比較理想的狀況是:
其他分支完成開發與驗證
↓
合併回 main / master
↓
形成正式可發布版本
正式發布時,也常會在這條分支上建立版本標籤,例如:
v1.0.0
v1.0.1
v1.1.0
這些版本標籤(Tag)就像替某個正式版本插上一支旗子。
之後如果要回頭看「這次上線到底是哪一份程式碼」,就比較容易找到。
develop 是 Git Flow 裡另一條長期分支。
如果 main 代表正式穩定版本,那 develop 可以理解成:
下一個版本正在整合中的開發線。
平常的新功能不會直接從 main 開出去,而是從 develop 開出功能分支(Feature Branch)。
功能完成後,也會先合回 develop。
流程大概像這樣:
develop
↓
feature/login
↓
develop
也就是說,develop 像是團隊把各種已完成功能先集中起來的地方。
它不一定已經是正式上線版本,但它應該代表「下一版正在慢慢成形」。
feature/* 是平常最常碰到的短期分支。
它主要用來開發新功能。
例如:
feature/login
feature/activity
feature/chat
這裡的重點是:不是只有一條固定叫 feature 的分支。
feature/* 裡的 * 代表不同功能可以各自有自己的分支名稱。
在 Git Flow 裡,功能分支(Feature Branch)通常會從 develop 開出來,完成後再合回 develop:
develop
↓
feature/activity
↓
develop
這樣做的好處是,每個人可以在自己的功能分支(Feature Branch)上工作,不會把還沒完成的修改直接丟進共同開發線。
等功能完成、測試通過、審查沒問題,再合回 develop。
release/* 是準備發布正式版本時使用的短期分支。
它通常會從 develop 開出來。
到了這個階段,代表下一版大致已經準備好了,接下來主要做的是:
最後測試
修小程式錯誤(Bug)
調整版本號
補文件
準備正式發布
它不像功能分支(Feature Branch)那樣繼續塞大量新功能。
比較像是:
「這一版要準備出門了,先在門口最後整理一下。」
完成後,release/* 會合併到 main / master,成為正式版本。
同時,也要把發布階段(Release)做的修正合回 develop,避免下一版開發線漏掉這些修補。
流程大概是:
develop
↓
release/*
↓
main / master
release/*
↓
develop
hotfix/* 是正式環境出問題時用的短期分支。
它和功能分支(Feature Branch)最大的差別是來源不同。
功能分支(Feature Branch)通常從 develop 開。
緊急修正分支(Hotfix Branch)則是從 main / master 開。
因為正式環境出問題時,要修的是目前正在正式上線的那份程式 Code。
流程大概是:
main / master
↓
hotfix/*
↓
main / master
hotfix/*
↓
develop
為什麼修完後除了合回 main,還要合回 develop?
因為正式環境修掉的 Bug,下一版開發線也要有同樣的修正。
不然現在正式版修好了,下一版從 develop 發布時,又可能把同一個 Bug 帶回來。
這也是我覺得 Git Flow 很有意思的地方:
它不是只管「這次怎麼修好」。
它也在管:
這次修好的東西,會不會被下一次版本更新弄丟。
整理一下,把前面五種分支放回同一張圖裡:

如果只看單一分支,可能會覺得名字很多。
但放在一起之後,就會發現 Git Flow 真正規定的是:
每一種修改要從哪裡出發,又應該回到哪裡。
所以 Git Flow 不是為了讓分支變多。
它是為了讓每種修改都有一條團隊約定好的路可以走。
回到 BuJo,我們當時使用的是 main / dev / feature/* 這樣的分支方式。
feature/*
↓
拉取請求(Pull Request,PR)
↓
dev(測試/整合/部署驗證)
↓
拉取請求(Pull Request,PR)
↓
main(正式部署)
平常做功能時,會從 dev 開出 feature/* 分支;功能完成後先合回 dev,確認穩定後再合到 main。
這和 Git Flow 裡「功能先進開發線,穩定後再進正式線」的精神很接近。
在 BuJo 裡,合併進 dev 會部署到測試網址,合併進 main 會部署到正式網址。
所以 dev 和 main 不只是兩個分支名稱,而是把「先驗證、再正式上線」這件事放進流程裡。
開發過程中,我們就遇過一個很典型的狀況:本機測試明明正常,但部署到測試環境後,活動時間顯示卻固定差了 8 小時。
當下真的超慌張,也超困惑:
「嗯?奇怪了,剛剛測試明明都沒問題,怎麼會這樣?」
如果修改直接進 main,這類問題就可能直接影響正式使用者。
但因為有 dev 這個中間環境,問題可以先在比較接近部署的地方被看見。
另外,BuJo 是四人團隊,所以我們也設定至少半數成員 Approve 後才能合併。
這不是 Git Flow 原始模型的一部分,而是團隊自己的審查(Review)規則;但它讓分支流程不只是畫在圖上的路線,而是真的有人一起看過、確認過。
我以前看 Git Flow,第一反應其實是:
也太多分支了吧。
但重新整理 BuJo 的開發流程後,我才發現,Git Flow 真正重要的不是叫什麼名字,也不是每個團隊都要把五種分支完整照做。
它真正有價值的地方,是讓團隊對「修改怎麼流動」有共同想像。
一人專案可以靠自己腦中對齊;但多人合作時,流程不能只存在某個人的腦袋裡。
尤其現在有 AI 協助開發,修改速度會變得更快。
如果沒有清楚的分支、審查(Review)和合併(Merge)規則,混亂也會更快累積。
所以分支規則不是為了拖慢開發,而是讓大家知道:
專案裡的分支不是隨便長出來的路,而是團隊一起約定好的行進路線。
下一篇,我們就要從「修改怎麼流動」,進到另一個我以前也很容易忽略的問題:
開始寫 Code 以前,功能規格要先怎麼定下來?