Git flow 開發流程

Update: 2011/3/19 受邀有場分享 Git介紹,使用與開發流程 at Facebook 軟體開發團隊工具心得分享

大家都知道 Git 開 branch 很方便,非常鼓勵 topic branch,但有沒有一套模型流程告訴我們應該怎麼管理 branch 呢? 有人便整理出一套最佳實踐慣例 A successful Git branching model我們團隊就採用了這套流程。簡單來說,他將 branch 分成兩個主要分支,三種支援性分支:

  • 主要分支
    • master: 永遠處在 production-ready 狀態
    • develop: 最新的下次發佈開發狀態
  • 支援性分支
    • Feature branches: 開發新功能都從 develop 分支出來,完成後 merge 回 develop
    • Release branches: 準備要 release 的版本,只修 bugs。從 develop 分支出來,完成後 merge 回 master 和 develop
    • Hotfix branches: 等不及 release 版本就必須馬上修 master 趕上線的情況。會從 master 分支出來,完成後 merge 回 master 和 develop

作者還提供了 git-flow 指令工具幫助我們很容易的實踐,用法如下:

首先是初始化動作:


    git flow init

初始化動作會問你一些問題,大抵是命名慣例:


No branches exist yet. Base branches must be created now.
Branch name for production releases: [master] 
Branch name for "next release" development: [develop] 
How to name your supporting branch prefixes?
Feature branches? [feature/] 
Release branches? [release/] 
Hotfix branches? [hotfix/] 
Support branches? [support/] 
Version tag prefix? []

設定完之後,預設的 branch 就變成 develop 了。有任何開發,一律都先開 branch:


git flow feature start some_awesome_feature
(以此類推 git flow release 和 git flow hotfix)

完成之後輸入


git flow feature finish some_awesome_feature

就會合併回 develop 並幫你刪除這個 (local) branch。

關於 remote branch

這個 git-flow 工具並沒有幫我們處理 remote branch,所以如果你的 branch 要 push 出去分享給別人,就要自己打 git 指令啦 同事留言說有支援啦:

push 一個 feature branch 到遠端:


git flow feature publish some_awesome_feature 
或 git push origin feature/some_awesome_feature

追蹤一個遠端的 branch:


git flow feature track some_awesome_feature 
或 git checkout -b feature/some_awesome_feature -t origin/feature/some_awesome_feature

刪除遠端的 branch:


git push origin :feature/some_awesome_feature

我們還碰到一個問題是輸入 git flow feature finish 時出現以下錯誤:


warning: not deleting branch 'feature/some_awesome_feature' that is not yet merged to
         'refs/remotes/origin/feature/some_awesome_feature', even though it is merged to HEAD.
error: The branch 'feature/some_awesome_feature' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature/some_awesome_feature'.

原因是這個 feature branch 一開始是從遠端 checkout 出來的,以及這個 feature branch 有 commit 沒有 push 回去 ,所以 git flow 不敢幫你刪除 local branch,這時候其實 merge 動作已經完成了,所以你可以手動輸入 git branch -D feature/some_awesome_feature 強制刪除 local branch 即可。(小結論:git-flow 只是個輔助工具,了解 git 還是必要的)

關於 feature branch 的合併

如果是開發時間比較久的 feature branch,很可能會因為 1. 不定時的 merge develop 與新版同步 2. 實驗性質的修改 3. 需求的變更 等等因素,而讓這個 feature branch 的 commit 記錄變成髒髒的,這時候我們會用以下的方式來做 merge 動作:

1. 先對 feature branch 做 `git rebase develop`。會很苦,但是弄完會很有成就感,整個 branch commit history 會變成很乾淨。請學 interactive mode,可以讓你拿掉一些 commit、合併或修改,你也可以 rebase 多次直到滿意為止。
2. 在從 develop bracnh 做 `git merge feature/some_awesome_feature –no-ff`,–no-ff 的意思是會強制留一個 merge commit log 記錄,這可以讓 commit tree 看清楚發生了 merge 動作。(因為我們剛做了 rebase,而 git 預設的合併模式是 fast-forward,所以如果不加 –no-ff 是不會有 merge commit 的) 這個 merge commit 的另一個額外方便之處是,如果想要 reset/revert 整個 branch 只要 reset/revert 這個 commit 就可以了。
3. 如果此 feature branch 有 remote branch,要先砍掉 `git push origin :feature/some_awesome_feature` 再 `git push origin develop` (這是因為 rebase 一個已經 push 出去的 repository,然後又把修改的 history push 出去,會造成超級大災難啊~)

先 rebase 再 merge –no-ff 這樣做的好處到底是什麼? 看圖體會一下吧:

每一次的 merge 就代表了一個 feature 完成,也可以很清楚看到這個 feature branch 底下包含哪些 commit。

對了,如果有用 Github 的話,請記得務必用一用它的 pull request 功能,我們會在 branch 完成後發一個 pull request,好讓大家可以對一整個 branch 做 code review 留言。

註:什麼是 rebase 可以參考舊作: Git 版本控制系統(3) 還沒 push 前可以做的事

36 thoughts on “Git flow 開發流程

  1. “關於 remote branch”

    分享/發佈: git flow feature publish some_awesome_feature
    追蹤: git flow feature track some_awesome_feature

  2. Hi ihower : 不知有沒有時間與興趣? 我想邀請您來當講者分享您的團隊使用Git的經驗分享, 也可以透過這個機會分享目前您公司的專案 or 產品

  3. 想问一下,rails使用git自动部署的问题:自己的开发机和服务器,本地开发某个rails project,git repo在服务器上,希望就在这个git repo同个机器上部署这个rails project,类似heroku,本地push进repo,重启web服务器就可以直接更新了?一般怎么做的呢?现在能想到的就是在repo的这个project下面和web服务器的rails project在同个机器分开两个目录,hook一个post动作,每次这个repo一有提交,就自动去让rails project 自动从repo pull下来更新。。。好像有点麻烦哦?

  4. 請問:

    在實務上 Feature branches 是每個開發人員各自取名,分別開發其功能後再併回 Develop branches 呢?還是只有一個 Feature branch ,所有人共用此分支進行新功能開發?

    個人覺得應該是開發人員各自取名,不知理解是否正確?

  5. Feature branch 就是以功能分的意思,一個 feature 一個 branch。通常一個(小) feature branch 也就只有一兩個 developers。

  6. 抱歉,對於 git 又有一些問題請教:

    依 Oreilly 的『版本控制使用 Git 』一書所提,通常會在遠端主機上建立一個權威倉庫來放置裸 (bare) 容器供分散式開發之用,因為它說 bare 容器沒有開發工作目錄的設定,那這樣子我們還能把 develop 分支也送上去共享開發嗎?

  7. 謝謝ihower大關於git的解說,我把git一系列的教學,投影片和影片都看過了,真的是受益良多阿!!!
    讓我對git有另一層更深的體認了^^

    我看完git flow後試著去練習這樣的流程,也下載了作者的腳本來使用…
    不過後來使用Release branch時。切回master看log的線圖,感覺蠻亂的@@
    可是切回develop branch就還好…

    不知道是不是因為他是用develop branch出release branch再分別merge回master和develop的關係Orz

  8. ihower 您好, 感謝您一系列的文章, 讓我學到許多

    關於您文章中引用的圖片, 我有些問題想請教您

    release branch 是只能存在一個嗎?? 還是多個呢??
    因為圖中是寫 release branches 但卻有只有一條線
    (還是說淺灰色的線代表不同 branch 的區隔)
    如果只能存在一個話 不同 release 的版本號是用 commit 或 tag 區分嗎??
    如果是存在多個的話 release branch 的名稱該怎麼取呢???

    我是使用 source tree 裡面的 git flow 功能
    在預設上 feature branch , release branch 是有資料夾的
    意思應該是能有很多個(?)

    謝謝

  9. 請問如果使用 gitflow 並搭配 gitlab, 在團隊開發過程時, code review 應如何進行?
    feature branch merge to develop branch 時進行?
    或是有什麼更好的建議?

  10. 目前团队是走 git flow 流程
    也是dev 跟master
    之前呆过的还有一个test分支
    多个test分支是否不是最佳流程呢?我清楚这是跟团队的convention 有关
    之前多的test分支是给QA团队用

    目前团队想法是走分支来替代Test ,remote repo始终保持两个分支也就是dev 跟master
    但私以为效率偏低

Leave a Reply