最近發現終於有 GitFlow for Visual Studio 擴充套件可以用了,這讓使用 GitFlow 版控流程的團隊可以更方便的將流程整合到 Visual Studio 之中,本篇文章將完整說明 GitFlow for Visual Studio 擴充套件的使用方法與注意事項。如果你還不了解 Git 或 GitFlow 的話,也歡迎到 多奇教育訓練課程一覽 報名【Git 版本控管實戰】相關課程。
學習前的準備
- 請先在 Visual Studio 2013 中安裝 GitFlow for Visual Studio 擴充套件
※注意:你至少要先安裝 Visual Studio 2013 Update 3 以上版本才能安裝這個擴充套件
- 各位可以拿 https://github.com/doggy8088/MVC5_Add_WebAPI 專案回來練習,本篇文章將會以這個 GitHub 專案當成教學的範本。
- 版控功能都已經整合進 Visual Studio 2013 的 Team Explorer 工作窗格中,請透過 [檢視] –> [Team Explorer] 開啟這個工作窗格。

- 要使用 GitFlow for Visual Studio 擴充套件之前,請務必先行了解 GitFlow 運作原理,否則用起來會很不順利,請各位務必先行理解。
複製 Git 專案 ( git clone ) 並開啟專案
在 Team Explorer 中點擊「連接到 Team 專案」的圖示

點擊「本機 Git 儲存機制」的「複製」

貼上 GitHub 專案網址,並按下「複製」按鈕

滑鼠雙擊剛剛 複製 (clone) 回來的專案

滑鼠雙擊 *.sln 方案,就可以開啟此專案

專案開啟後,請先進行一次成功的建置 (Build)!
初始化 GitFlow 版控環境
目前,你得到一個只有 master 分支的 Git 本地儲存庫,我們可以從 Team Explorer 窗格中先進入 Git 版控的「首頁」,然後點擊 GitFlow 進入 GitFlow 的相關操作畫面。

點選 Initialize 準備初始化 GitFlow 版控環境

由於 GitFlow 版控流程會有兩個主要分支 (master, develop) 與三個支援分支 (feature, release, hotfix),基本上預設值都可以不用改,直接按下 OK 按鈕即可讓 GitFlow 初始化完成,這些設定都會儲存在 .git\config 設定檔之中。預設他會自動幫你額外建立一個 develop 分支。

此時你可以看到 GitFlow 設定完成後的畫面,未來 GitFlow 版控流程也都會在這裡操作!

我改用 TortoiseGit 的 Show log 你可以看見如下圖示,目前 Git 工作目錄將會自動切換到 develop 分支上。
- 初始化 GitFlow
- 功能分支 ( Feature Branch )
- Start: 從 develop 建立 Feature 分支
- Finish: 將 Feature 分支合併回 develop 分支
- 發行分支 ( Release Branch )
- Start: 從 develop 建立 Release 分支
- Finish: 將 Release 分支依序合併回 master 與 develop 分支
- 修補分支 ( Hotfix Branch )
- Start: 從 master 建立 Hotfix 分支
- Finish: 將 Hotfix 分支依序合併回 master 與 develop 分支
※ 注意:有合併,就會有衝突的可能,GitFlow 原則上不會幫你處理衝突,有衝突要自行處裡,所以上述說明的版控流程很重要,使用 GitFlow 的人務必牢記!
完成一個 Feature 分支開發的版控流程
假設我們現在想要開發一個新的 ASP.NET MVC 控制器,這時我們將會建立一個 Feature 分支,以下就是透過 GitFlow for Visual Studio 建立 Feature 分支的步驟。
在 Team Explorer 的 GitFlow 畫面點擊 Start Feature 並輸入一個新的 Feature 分支名稱,並點擊 Create Feature 建立分支。


假設你想建立的 Feature 分支名稱為 add_profile_controller 的話,這個過程 GitFlow for Visual Studio 就會自動幫你建立起一個名為 feature/add_profile_controller 分支,我們可以利用 TortoiseGit 的 Show log 看到這個真正的分支名稱,而且目前工作目錄也已經自動切換到這個新分支了。

接著我們在專案中新增一個 Controllers/ProfileController.cs 控制器,並且新增一些 View 上去,然後建立一個新版本。
註:不熟悉在 Visual Studio 操作基礎 Git 版控的人,可以先從 Visual Studio Online 與 Git 版本控管實戰 學習到相關知識。
當執行完 認可 (Commit) 動作後,你將會在 feature/add_profile_controller 分支中建立起一個新版本,這時的版本線圖 (Version Graph) 如下圖示:

假設你的所有變更已經完成,這時我們就要準備進入 GitFlow 版控流程的另一個動作,也就是完成這個 Feature 分支。此時請你參考下圖,點選這個下拉選單,將畫面切換到 GitFlow 去。

通常這個時候,你可能會有幾種選擇:
- 將現有的 feature/add_profile_controller 分支發行 (Publish) 到遠端儲存庫 (讓其他人看的到你正在開發中的分支)

- 完成這個 feature/add_profile_controller 分支,並刪除本地分支

- 完成這個 feature/add_profile_controller 分支前先 Rebase develop 分支,然後刪除本地分支

假設我們選擇第二種,並按下 OK 按鈕,你會發現所有 Feature 已經都完成了合併,而且是合併回 develop 分支。

如果透過 TortoiseGit 的 Show log 查看版本線圖,你會發現 develop 在合併 feature/add_profile_controller 分支時,自動引發了 Git 的快轉機制 (Fast-Forward),所以你會看見 develop 分支直接往上跳一個版本。

因為 GitFlow for Visual Studio 骨子裡其實就是執行 git flow 指令而已,因此所有的版控操作其實都是在下指令罷了,關於這點你可以透過「輸出」窗格得知所有 git flow 執行的細節與訊息。

如果你想要強迫指定 No Fast-Forward 的方式進行合併,則必須去修改 "C:\Program Files (x86)\Git\bin\git-flow-feature" 這個檔案,這是一個 Shell Script 檔案,git flow 在執行的時候,會去呼叫這支程式出來執行,所以如果要強迫使用 No Fast-Forward 方式合併,請搜尋到以下字串:
git_do merge --ff "$BRANCH"
並且修改成以下即可:
git_do merge --no-ff "$BRANCH"
在了解完一整個 Feature 分支的版控流程,其他支援分支的操作方式也都大同小異,必較需要注意的地方,應該就是開發人員必須先了解 GitFlow 的版控流程,不要光只是用工具,因為 Git 版控的觀念遠比透過工具操作來的重要多了!
處裡 Feature 分支完成時的衝突問題
上一個例子我們很順利的完成了 Feature 分支的合併動作,當你有多條 Feature 分支同時進行中時,發生衝突的機會自然也就多了,所以學習如何處裡衝突,絕對是個必修的功課!
假設我們在此時同時建立兩個 Feature 分支,分別命名為 ErrorOn1 與 ErrorOn2



然後我們先切換到 ErrorOn1 這個 Feature 分支

然後我們打開 web.config 檔案,並加上 <customErrors> 設定如下,並建立新版本:
<customErrors mode="Off"></customErrors>


我們可以先完成 ErrorOn1 功能分支

接著我們切換到 ErrorOn2 功能分支

這次我們打開 web.config 檔案,並加上有點不太一樣的 <customErrors> 設定如下,並建立新版本:
<customErrors mode="RemoteOnly" />


這時如果你想完成 ErrorOn2 功能分支,由於 Feature 分支一定會合併回 develop 分支,而之前的 ErrorOn1 功能分支已經成功合併回 develop 分支,而這次的 ErrorOn2 功能分支因為改到完全相同的一行,且內容還不太一樣,所以這次的合併勢必會引發合併衝突,我們先來看看在完成 Feature 分支的過程中會發生什麼事。


執行完後,你會發現沒有任何錯誤訊息,從上圖也可以發現 ErrorOn2 功能分支本來應該被刪除,但是卻還存在,這種有點「怪怪的」情況,完全是個大陷阱啊!因為衝突已經發生了,等待你去解決它!
如果你 web.config 檔案還開著,就會看到 Git 在合併時修改掉原本內容的情況,也代表著你的專案已經跑不動了,因為這已經完全破壞掉 Web.config 原本的 XML 格式,所以你不會沒發現這件事,發生衝突,就是要你當下立刻解決衝突!

事實上你可以從「輸出」窗格看見完整的 git flow 指令回應的錯誤訊息:

這時我們直接對專案在執行一次「認可 (Commit)」動作,你就會發現一段【合併正在進行中,請解決衝突,並認可結果。】的提示訊息,請點選「請解決衝突」連結:

我們從「衝突」分類中選取 Web.config 衝突中的檔案,並按下「合併」按鈕,讓 Visual Studio 2013 幫我們來解決衝突的問題。

我個人覺得 Visual Studio 2013 內建的版本衝突處理工具是所有 Git 合併工具中做得最漂亮的!
你可以從左邊或右邊選擇任何一邊的內容,在某些合併的情況下,你可能會需要兩邊都選,選擇完之後,還可以手動修改中間的合併結果,最後只要按下左上角的「接受合併」即可完成衝突解決!

衝突解決之後,就可以看到 Web.config 已經被列入到「已解決」這個分類下了,請按下「認可合併」按鈕

最後輸入一些變更紀錄,並按下「認可 (Commit)」即可完成本次合併

這個時候其實 ErrorOn2 功能分支已經完成了合併,如果你要把這個功能分支刪除的話,只要再執行一次 Finish Feature 動作即可!



有了以上說明,剩下的 Release 與 Hotfix 分支,應該就不用額外說明了,不過還是建議大家多練習個幾次,以免導入 GitFlow 遇到問題時手忙腳亂的! ^_^
相關連結