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 前可以做的事

30 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 時進行?
    或是有什麼更好的建議?

Leave a Reply

Your email address will not be published. Required fields are marked *