工作流,講的是對項目版本管理的一套操作流程規范。
在SVN時代,大家別無選擇,都是從同一個分支上開發,提交,解決沖突。
用Git做版本管理后,得益于其分布式能力,大家就可以不依賴中央版本庫,各自獨立開發,提交,再在適當時候合并。因其靈活性而產生了多種多樣的工作流。
集中式工作流
當然,你也可以忽略Git的分布式能力,忽略方便快捷的分支控制能力,在Git上用出Svn的感覺,反正你開心就好啦。這種在一個分支上進行協作的方式,我們也給它起個名,就叫集中式工作流。
所有人都在一個分支上開發,優點還是有的:
- 簡單粗暴易操作,適合不太復雜的小項目
- 每一次提交,都解決一次沖突,化大沖突為小沖突。
- 當需要依賴他人的工作輸出時,或者說與他人工作的耦合度高時,能方便工作快速推進。
但是缺點也非常明顯: - 提交歷史混亂,從提交歷史上難以追蹤一個完整功能的提交情況。
- 每次提交都有沖突的可能,假如沖突不好解決,或者合并了他人有問題的代碼,就會打斷自己的工作節奏。
- 不利于code review,不利于代碼質量管理
Git Flow
我們應該在一個功能,或者叫特性,開發完成后,才與他人代碼進行合并。
這時需要為一個個特性的開發創建專門分支。
在特性分支合并進master后,并不意味著代碼就能進行發布,可能需要經過各種測試修改,這時需要再創建一個分支來完成這個步驟,它應介于master與特性分支之間,我們可以把它叫做開發分支develop。
另外,對于線上發行版,如果出現了緊急需要修復的bug,還需要一個分支hotfix來完成bug修復。
基于這些想法,Vincent Driessen同學在多年前提出了一個分支模型A successful Git branching model,詳細描述了此種工作流,后人大多把它叫做Git Flow。
- 主要分支
- master: 永遠處在production-ready狀態
- develop: 最新的下次發布開發狀態
- 支援性分支
- feature branches: 開發新功能都從develop分支出來,完成后merge回develop
- release branches: 準備要release的版本,只修bugs。從develop分支出來,完成后merge回master和develop
- hotfix branches: 等不及release版本必須馬上修復線上的問題。從master分支出來,完成后merge回master和develop
概略來講,就是開發工作在develop分支進行,然后提交到release分支,最后合并到master分支。
git工作流很標準但是使用很復雜。
Github Flow
GitHub Flow是github.com提出的方案,簡化成只有一個feature分支和一個master分支。
github有一個pull request功能,多人協作時,在feature分支開發完成后,可以向項目負責人發起pull request,請求項目負責人拉取代碼,檢閱并合并pull request指定的分支。
Gitlab Flow
Gitlab Flow是gitlab.com提出的方案,覺得git flow太復雜,而github flow又過于簡化而不能滿足項目開發需求。
它的feature分支可以直接合入master分支,而master就變成了開發主分支。對于持續集成需求,提出從master開出pre-production分支和production分支,pre-production作為一個發布前的緩存,而production就代表了線上運行的版本。
你可能會奇怪它為什么有一個發布前緩存,這個看實際應用情景可選。比如iOS應用的發布,有一個蘋果審核階段,這個階段的代碼版本就是預發版本,可放在pre-production中,待審核通過,代碼不再修改時,就隨著應用的真正發布而同步到production分支。以后當我們需要追溯歷史發布版本時,只需要查看production分支就可以了。
同樣gitlab也有像github一樣的pull request,不過在gitlab中,這個功能叫做merge request,也是請求別人來拉取我的分支代碼,code review,然后合并。
一些小Tips
- 空目錄在Git中是個無關對象,它不能通過add命令被添加到提交中。如果需要把空目錄提交并push到遠程倉庫,可以在目錄下建一個無關文件
.gitkeep
。 - 特性分支上的提交如果是比較隨意的話,它在合入主開發分支時應壓縮一下提交歷史,再比較正式地的提交一次。這時可用到squash命令,同時它可以作為merge的選項
git merge --squash branch
,這樣的合并不會產生新提交,需要你在解決完沖突后,自己提交一次。