中心化的工做流
優點
- 首先它讓每一個開發者都有本身的本地的完整項目副本。隔離的環境使得每一個開發都的工做獨立於項目的其它修改 —— 他們能夠在本身的本地倉庫中添加提交,徹底無視上游的開發,直到須要的時候。
- 其次,它讓你接觸到了 Git 分支和合並模型。Git 分支被設計爲故障安全的機制,用來在倉庫之間整合代碼和共享更改。
如何工做
- 中心化的工做將中央倉庫做爲項目中全部修改的惟一入口。默認的開發分支叫作 master,全部的更改都被提交到這個分支。這種工做流不須要 master 以外的其它分支。
- 開發者將中央倉庫克隆到本地後開始工做。在他們的本地項目副本中,他們能夠像 SVN 同樣修改文件和提交更改;不過這些新的提交被保存在本地 —— 它們和中央倉庫徹底隔離。這使得開發者能夠將和上游的同步推遲到他們方便的時候。
- 爲了向官方項目發佈修改,開發者將他們本地 master 分支「推送」到中央倉庫。這一步等同於 svn commit,除了 Git 添加的是全部不在中央 master 分支上的提交。

管理衝突
- 中央倉庫代碼官方項目,所以它的提交歷史應該被視爲不可更改的。若是開發者的本地提交和中央倉庫分叉了,Git 會拒絕將它們的修改推送上去,由於這會覆蓋官方提交。

- 在開發在提交功能以前,須要 fetch 更新中央提交,在它們之上 rebase 本身的更改。
- 若是本地修改和上游提交的衝突時,Git 會暫停 rebase 流程,給你機會手工解決這些衝突。Git 很讚的一點是,它將 git status 和 git add 命令同時用來生成提交和解決合併衝突。這使得開發可以垂手可得的管理他們的合併。另外,若是他們改錯了什麼,Git 能讓他們輕易的退出 rebase 過程,而後重試。
例子
-
項目管理員生成一個空的版本庫git
ssh user@host git init --bare /path/to/repo.git
-
三我的 A, B, C 同時編寫同一個項目,須要先在本地建立一個完整的項目副本。shell
git clone ssh://user@host/path/to/repo.git
此時,Git 自動添加了一個名爲 origin 的運程鏈接,指向中央倉庫,以方便提交。
A 可使用標準 Git 提交流程開發功能:編輯、緩存、提交。segmentfault
git status
git add <some file>
git commit
同時,B 也在本地進行本身的開發工做。緩存
-
A 發佈了他們修改安全
git push origin master
此時中央倉庫會將 master -> origin/master服務器
-
B 試圖發佈修改框架
git push origin master
可是由於 A 已經提交了功能到中央倉庫,致使 B 的本地歷史和中央倉庫分叉,Git 會拒絕本次提交。ssh
可使用 git pull 來拉取並修改,svn
git pull --rebase origin master
- --rebase 命令告訴 Git,在同步中央倉庫的修改以後,將 B 的全部提交移到 master 分支的頂端。

一樣的,若是此時不知道本身作了什麼,能夠回滾一次操做。
git rebase --abort
基於功能人分支的工做流
Feature 分支工做流
- 掌握了中心化工做流的使用姿式,在你的開發流程中添加功能分支是一個簡單的方式,來促進協做和開發者之間的交流。這種封裝使得多個開發專一本身的功能,而不會打擾主代碼庫。它還能保證 master 分支永遠不會包含損壞的代碼,給持續集成環境帶來了很大的好處。
- 封裝功能的開發使得 pull request 的使用成爲可能,用來啓動圍繞一個分支的討論。它給了其餘開發者在功能併入主項目以前參與決策的機會。或者,若是你開發功能時卡在一半,能夠發起一個 pull request,向同事尋求建議。重點是:pull request 使得團隊在評論其餘人的工做時,變得很是簡單。
如何工做
- Feature 分支工做流一樣使用中央倉庫,master 一樣代碼官方的項目歷史。可是與其直接提交在本地的 master 分支,開發者每次進行新的工做時建立一個新的分支。Feature 分支應該包含描述性的名稱,好比 animated-menu-items(菜單項動畫)或 issue-*1061。每一個分支都應該有一個清晰、高度集中的目的。
- Git 在技術上沒法區別 master 和功能分支,因此開發者能夠在 feature 分支上編輯、緩存、提交,就和中心化工做流中同樣。
- 此外,feature 分支能夠被推送到中央倉庫。這使得你和其餘開發者共享這個功能,而又不改變官方代碼。既然 master 只是一個「特殊」的分支,在中央倉庫中儲存多個 feature 分支不會引出什麼問題。固然,這也是備份每一個開發者本地提交的好辦法。
Pull Request
- 除了隔離功能開發以外,分支使得經過 pull request 討論修改爲爲可能。一旦有人完成了一個功能,他們不會當即將它併入 master。他們將 feature 分支推送到中央服務器上,發佈一個 pull request,請求將他們的修改併入 master。這給了其餘開發者在修改併入主代碼庫以前審查的機會。
- 代碼審查是 pull request 的主要好處,但他們事實上被設計成爲討論代碼的通常場所。你能夠把 pull request 看做是專一某個分支的討論版。也就是說他們能夠用於開發流程以前。好比,一個開發者在某個功能上須要幫助,他只須要發起一個 pull request。感興趣的小夥伴會自動收到通知,看到相關提交中的問題。
- 一旦 pull request 被接受了,發佈功能的行爲和中心化的工做流是同樣的。首先,肯定你本地的 master 和上游的 master 已經同步。而後,將 feature 分支併入 master 已經同步。而後能夠將 feature 分支併入 master,將更新的 master 推送回中央倉庫。
Gitflow 工做流
- GitFlow 工做流圍繞項目發佈定義了一個嚴格的分支模型。有些地方比功能分支工做流更復雜,爲管理大型項目提供了框架。
- 和功能分支工做流相比,這種工做流沒有增長任何新的概念或命令。它給不一樣的分支指定了特定的角色,定義它們應該如何、何時交流。除了功能分支以外,它還爲準備發佈、維護髮布、記錄發佈分別使用了單獨的分支。固然,還能享受到功能分支工做流帶來的全部好處:pull request、隔離實驗和更高效的協做。
如何工做
- GitFlow 工做流仍然使用中央倉庫做爲開發者溝通的中心。和其它工做流同樣,開發者在本地工做,將分支推送到中央倉庫。惟一的區別在於項目的分支結構。
歷史分支
- 和單獨的 master 分支不一樣,這種工做流使用兩個分支來記錄項目歷史。master 分支儲存官方發佈歷史,develop 分支用來整合功能分支。同時,這還方便了在 master 分支上給全部提交打上版本號標籤。

功能分支
- 每一個新功能都放置在本身的分支中,能夠在備份/協做時推送到中央倉庫。可是與其合併到 master,功能分支將開發分支做爲父分支。當一個功能完成時,它將被合併回 develop。功能永遠不該該支持在 master 上交互。

- 功能分支加上 develop 分支就是咱們以前聽說的功能分支工做流。
發佈分支

- 一旦 develop 分支的新功能足夠發佈,你能夠從 develop 分支 fork 一個發佈分支。這個分支的建立開始了下個發佈週期,只有和發佈相關的任務應該在這個分支進行,如修復 bug、生成文檔等。一旦準備好發佈,發佈分支將合併進 master,打上版本號的標籤。另外,它也應該合併回 develop,後者可能在發佈啓動以後有了新的進展。
- 使用一個專門的分支來準備發佈確保一個團隊完善當前的發佈,其它團隊能夠繼續開發下一個發佈的功能。它還創建了清晰的開發階段。
-
一般約定:
- 從 develop 建立分支
- 合併進 master 分支
- 命名規範 release-* 或者 release/*
維護分支

- 維護或者「緊急修復」分支用來快速給產品發佈打上補丁。這是惟一能夠從 master 上 fork 的分支。一旦修復完成了,它應該被併入 master 和 develop 分支,master 應該打上更新的版本號的標籤。
- 有一個專門的 bug 修復開發線使得團隊可以處理 issue,而不打斷其它工做流或是要等到下一個發佈週期。你能夠將維護分支看做在 master 分支上工做的臨時發佈分支。
例子
建立一個開發分支
-
爲默認的 master 分支建立一個互補的 develop 分支。最簡單的辦法是在本地建立一個空的 develop 分支,將他推送到服務器上:
git branch develop
git push -u origin develop
-
這個分支將會包含項目中全部的歷史,而 master 將包含不徹底的版本。其餘開發者應該將中央倉庫克隆到本地,建立一個分支來追蹤 develop 分支:
git clone http://xxx/xx/repo.git
git checkout -b develop origin/develop
開始了新的功能
-
當兩我的都須要在不一樣分支上開始工做,即爲本身的功能建立單獨的分支。且他們的分支都是基於 develop 而不是 master:
git checkout -b some-feature develop
-
他們都使用「編輯、緩存、提交」的通常約定來向功能分支添加提交:
git status
git add <some-file>
git commit
完成功能
發佈新功能
-
當另外的開發人員,仍在他本身的分支上工做時,開始準備項目的第一個官方發佈。和開發功能同樣,新建一個分支來封裝發佈的準備工做。這也正是發佈的版本號建立的第一步:
git checkout -b release-0.1 develop
- 這個分支用來整理提交,充分測試,更新文檔,爲即將到來的發佈作各類準備。它就像是一個專門用來完善發佈的功能分支。
-
一旦發佈準備穩妥,即將其併入 master 和 develop,而後刪除發佈分支。合併回 develop 很重要,由於可能已經有關鍵的更新添加到發佈分支上,而開發新功能須要用到它們。一樣的,若是團隊重視代碼審查,如今將是發起 pull request 的完美時機。
git checkout master
git merge release-0.1
git push
git checkout develop
git merge release-0.1
git push
git branch -d release-0.1
-
發佈分支是功能開發(develop)分支和公開發布(master)之間的過渡階段。不論何時,將提交併入 msater 時,你應該爲提交打上方便引用的標籤:
git tag -a 0.1 -m "Initial public release" master
git push --tags
- Git 提供了許多鉤子,即倉庫中特定事件發生時被執行的腳本。當你向中央倉庫推送 master 分支或者標籤時,你能夠配置一個鉤子來自動化構建公開發布。
終端用戶發現一個 Bug
-
正式發佈以後,兩個開發一塊兒爲下一個發佈開發功能。這時,一個終端用戶開了一個 issue 抱怨說當前發佈中存在一個 Bug。爲了解決這個 bug,先從 master 建立一個維護分支,用幾個提交修復這個 issue,而後直接合並回 master。
git checkout -b issue*001 master
##Fix the bug
git checkout master
git merge issue-*001
git push
-
和發佈分支同樣,維護分支包含了 develop 中須要的重要更新,所以須要執行一樣的合併。接下來,能夠刪除這個分支:
git checkout develop
git merge issue-*001
git push
git branch -d issue-*001
各分支的意義
- feature (多個) 主要是本身玩了,差很少的時候要合併回 develop 去。不與 master 交互。
- develop (同時間一個) 主要是和 feature 以及 release 交互
- release (同時間一個) 老是基於 develop,最後又合併回 develop。固然對應的 tag 要合併到 master 分支,生命週期短,僅是爲了發佈程序
- hotfix (同一時間一個) 老是基於 master,並最後合併到 master 和 develop。生命同期較短,用來修復 bug 或小粒度修改發佈
- master (僅一個) 關聯 tag 和發佈
模型中各個模塊內容的使用
- 在這個模型中,master 和 develop 都具備象徵意義。master 分支上的代碼老是穩定的 (stable build),隨時能夠發佈出去。develop 上的代碼老是從 feature 上合併過來的,能夠進行 Nightly Builds,但不直接在 develop 上進行開發。當 develop 上的 featur 足夠多以至於能夠進行新版本的發佈時,能夠建立 release 分支。
- release 分支基於 develop,進行委陰簡單的修改後就被合併到 master,並打上 tag,表示能夠發佈了。緊接着 release 將被合併到 develop;此時 Develop 可能往前跑了一段,出現合併衝突,須要手工解決衝突後再次合併,這步完成後就刪除 release 分支
- 當從已發佈版本中發現 bug 要修復時,就應用到 hotfix 分支了。hotfix 基於 master 分支,完成 bug 修復或者緊急修改後,要 merge 回 master,打上一個新的 tag,並 merge 回 develop,刪除 hotfix 分支。
- 因而可知 release 和 hotfix 的生命週期都較短,而 master 和 develop 雖然老是存在,但去不常使用。
文章首發於:https://www.zucchiniy.cn