為什么使用 git 和 git flow,這篇文章 深入理解學習Git工作流 的內容相信能夠給你一個完整的答案。
- 我們以使用SVN的工作流來使用git有什么不妥?
- git 方便的branch在哪里,團隊多人如何協作?沖突了怎么辦?如何進行發布控制?
- 經典的master-發布、develop-主開發、hotfix-不過修復如何避免代碼不經過驗證上線?
- 如何在github上面與他人一起協作,star-fork-pull request是怎樣的流程?
這篇文章分為兩部分,一部分引用 深入理解學習Git工作流 文章中的 git flow 工作流內容,一部分是使用 SourceTree 中的 git flow 工具來實現可視化的 git flow 流程管理,避免我們在使用 git 命令時遇到的坑。而且 SourceTree 的所有可視化操作都會展示相應的執行命令。
SourceTree Win10 安裝過程及配置
Gitflow 工作流
Gitflow工作流通過為功能開發、發布准備和維護分配獨立的分支,讓發布迭代過程更流暢。嚴格的分支模型也為大型項目提供了一些非常必要的結構。

這節介紹的Gitflow工作流借鑒自在nvie的Vincent Driessen。
Gitflow工作流定義了一個圍繞項目發布的嚴格分支模型。雖然比功能分支工作流復雜幾分,但提供了用於一個健壯的用於管理大型項目的框架。
Gitflow工作流沒有用超出功能分支工作流的概念和命令,而是為不同的分支分配一個明確的角色,並定義分支之間如何和什么時候進行交互。
除了使用功能分支,在做准備、維護和記錄發布時,也定義了各自的分支。
當然你可以用上功能分支工作流所有的好處:Pull Requests、隔離實驗性開發和更高效的協作。
2.3.1 工作方式
Gitflow工作流仍然用中央倉庫作為所有開發者的交互中心。和其它的工作流一樣,開發者在本地工作並push分支到要中央倉庫中。
2.3.2 歷史分支
相對於使用僅有的一個master分支,Gitflow工作流使用兩個分支來記錄項目的歷史。master分支存儲了正式發布的歷史,而develop分支作為功能的集成分支。
這樣也方便master分支上的所有提交分配一個版本號。

剩下要說明的問題圍繞着這2個分支的區別展開。
2.3.3 功能分支
每個新功能位於一個自己的分支,這樣可以push到中央倉庫以備份和協作。
但功能分支不是從master分支上拉出新分支,而是使用develop分支作為父分支。當新功能完成時,合並回develop分支。
新功能提交應該從不直接與master分支交互。

注意,從各種含義和目的上來看,功能分支加上develop分支就是功能分支工作流的用法。但Gitflow工作流沒有在這里止步。
2.3.4 發布分支

一旦develop分支上有了做一次發布(或者說快到了既定的發布日)的足夠功能,就從develop分支上checkout一個發布分支。
新建的分支用於開始發布循環,所以從這個時間點開始之后新的功能不能再加到這個分支上——
這個分支只應該做Bug修復、文檔生成和其它面向發布任務。
一旦對外發布的工作都完成了,發布分支合並到master分支並分配一個版本號打好Tag。
另外,這些從新建發布分支以來的做的修改要合並回develop分支。
使用一個用於發布准備的專門分支,使得一個團隊可以在完善當前的發布版本的同時,另一個團隊可以繼續開發下個版本的功能。
這也打造定義良好的開發階段(比如,可以很輕松地說,『這周我們要做准備發布版本4.0』,並且在倉庫的目錄結構中可以實際看到)。
常用的分支約定:
用於新建發布分支的分支: develop 用於合並的分支: master 分支命名: release-* 或 release/*
2.3.5 維護分支

維護分支或說是熱修復(hotfix)分支用於給產品發布版本(production releases)快速生成補丁,這是唯一可以直接從master分支fork出來的分支。
修復完成,修改應該馬上合並回master分支和develop分支(當前的發布分支),master分支應該用新的版本號打好Tag。
為Bug修復使用專門分支,讓團隊可以處理掉問題而不用打斷其它工作或是等待下一個發布循環。
你可以把維護分支想成是一個直接在master分支上處理的臨時發布。
2.3.6 示例
下面的示例演示本工作流如何用於管理單個發布循環。假設你已經創建了一個中央倉庫。
創建開發分支

第一步為master分支配套一個develop分支。簡單來做可以本地創建一個空的develop分支,push到服務器上:
git branch develop
git push -u origin develop
以后這個分支將會包含了項目的全部歷史,而master分支將只包含了部分歷史。其它開發者這時應該克隆中央倉庫,建好develop分支的跟蹤分支:
git clone ssh://user@host/path/to/repo.git git checkout -b develop origin/develop
現在每個開發都有了這些歷史分支的本地拷貝。
小紅和小明開始開發新功能

這個示例中,小紅和小明開始各自的功能開發。他們需要為各自的功能創建相應的分支。新分支不是基於master分支,而是應該基於develop分支:
git checkout -b some-feature develop
他們用老套路添加提交到各自功能分支上:編輯、暫存、提交:
git status
git add <some-file>
git commit
小紅完成功能開發

添加了提交后,小紅覺得她的功能OK了。如果團隊使用Pull Requests,這時候可以發起一個用於合並到develop分支。
否則她可以直接合並到她本地的develop分支后push到中央倉庫:
git pull origin develop
git checkout develop
git merge some-feature
git push
git branch -d some-feature
第一條命令在合並功能前確保develop分支是最新的。注意,功能決不應該直接合並到master分支。
沖突解決方法和集中式工作流一樣。
小紅開始准備發布

這個時候小明正在實現他的功能,小紅開始准備她的第一個項目正式發布。
像功能開發一樣,她用一個新的分支來做發布准備。這一步也確定了發布的版本號:
git checkout -b release-0.1 develop
這個分支是清理發布、執行所有測試、更新文檔和其它為下個發布做准備操作的地方,像是一個專門用於改善發布的功能分支。
只要小紅創建這個分支並push到中央倉庫,這個發布就是功能凍結的。任何不在develop分支中的新功能都推到下個發布循環中。
小紅完成發布

一旦准備好了對外發布,小紅合並修改到master分支和develop分支上,刪除發布分支。合並回develop分支很重要,因為在發布分支中已經提交的更新需要在后面的新功能中也要是可用的。
另外,如果小紅的團隊要求Code Review,這是一個發起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分支)間的緩沖。只要有合並到master分支,就應該打好Tag以方便跟蹤。
git tag -a 0.1 -m "Initial public release" master git push --tags
Git有提供各種勾子(hook),即倉庫有事件發生時觸發執行的腳本。
可以配置一個勾子,在你push中央倉庫的master分支時,自動構建好版本,並對外發布。
最終用戶發現Bug

對外版本發布后,小紅小明一起開發下一版本的新功能,直到有最終用戶開了一個Ticket抱怨當前版本的一個Bug。
為了處理Bug,小紅(或小明)從master分支上拉出了一個維護分支,提交修改以解決問題,然后直接合並回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
到了這里,但願你對集中式工作流、功能分支工作流和Gitflow工作流已經感覺很舒適了。
你應該也牢固的掌握了本地倉庫的潛能,push/pull模式和Git健壯的分支和合並模型。
記住,這里演示的工作流只是可能用法的例子,而不是在實際工作中使用Git不可違逆的條例。
所以不要畏懼按自己需要對工作流的用法做取舍。不變的目標就是讓Git為你所用。
SourceTree 實現 git flow
通過文章《SourceTree Win10 安裝過程及配置》 正確安裝 SourceTree 以及管理示例源碼,界面如下。

初始化 Git flow
點擊右上角的 “Git 工作流” ,初次會提示我們 “使用 Git Flow 來初始化此倉庫”,已經幫助我們預定義好了一些配置,我們只需要點擊 “確定” 按鈕即可。

點擊“確定”按鈕后,我們會發現 SourceTree 為我們自動創建了 develop 分支,並且切換到了 develop 分支。

Git flow: 建立新功能
繼續點擊右上角的 “Git 工作流” ,這次會提示我們選擇具體的下一個流程動作,這里我們演示一個 “建立新的功能” 流程。

點擊 “建議新的功能” ,會讓我們對即將要開發的功能進行命名(名稱請使用英文),這里我們輸入 simple-git-flow,點擊確定按鈕,會自動幫助我們創建 feature/simple-git-flow 分支,並切換到該分支上。

同時我們也能看到 SourceTree 幫助我們執行了什么命令來達到這樣的效果。

已經自動切換到 feature/simple-git-flow 分支。

提交代碼
此時我們可以在分支上開發我們的新功能,可以在分支上管理代碼,而不影響到其他同事的開發工作。
為了簡單演示,我們修改下 readme.md 的內容如下:

在 SourceTree 界面,我們需要在 未暫存文件 區域選中 readme.md 並點擊 暫存所選 按鈕,此時 readme.md 文件會進入到 已暫存文件 區域。只有 已暫存文件 的文件會進行 提交操作 。
在下方的空白區域輸入本次提交的說明:a simple git flow 后點擊提交按鈕,就會提交源碼。

如下圖所示:可以看到剛剛提交的代碼記錄

完成新功能開發
經過不斷的代碼完善,並且經過單元測試后,代碼已經完成后,此時就可以完成 新功能的開發 ,繼續點擊 Git 工作流

點擊 “完成功能”,默認會如下圖所示,在正常的開發流程下,我們不需要更改任何設置,直接點擊確定即可。

SourceTree 展示所執行的命令及結果。

完成后,我們會發現 feature/simple-git-flow 分支已經不見了,同時在 develop 分支上多了一個 a simple git flow的提交信息。

至此整個 “建議新功能” 的 git flow 流程就完畢了。
總結
實際開發過程中,會遇到各種情況,無法通過簡短的文章來說明所有的情況,具體需要在實踐過程中不斷學習。
再次總結下為什么要使用 SourceTree
- 降低入門門檻。很多應屆生並不知道版本管理工具和 git,通過可視化工具,可以避免初學者在使用過程中因為不熟悉命令而產生的問題。
- 使用 SourceTree 的所有操作,都會展示響應的執行命令,也能讓初學者了解到具體的操作是通過什么命令來實現的。
- 在完全不熟悉命令的情況下,也可以通過 SourceTree 來參與團隊協作開發。
並且在我們的 Centos 服務器部署中,我們使用 docker 來管理版本和發布,也基本用不到復雜的 git 命令,對於初學者的快速入門 SourceTree 足夠了。
