VSTS2010版本控管

VSTS2010版本控管

1 前言

版本控管主要用於管控程式碼異動,對於開發、測試階段以及後續維護階段,都是不可或缺的角色。VSTS2010提供了十分成熟完整的程式碼管控(Source Control)功能,並與開發工具Visual Studio深度整合,對於開發團隊提供很大的助益。

2 相關工具介紹

2.1 Solution Explorer

透過它可以進行簽入、簽出、取得新版本動作,並可從Solution、Project角度了解相關檔案版本管控狀態,如檔案是否納入程式碼管控狀態、簽入或簽出。

clip_image002

圖1 Solution Explorer

2.2 Source Control Explorer

在Team Explorer視窗,點選您的Team Project -> Source Control節點,點擊兩下即可顯示。它用於顯示TFS上程式碼管控目錄結構與狀態,您可以透過它設定權限、進行Branch與Merge、利用Workspace設定與本機目錄的對應關係。

clip_image004

圖2 Source Control Explorer

2.3 Pending Changes

點選Menu -> View -> Other Windows -> Pending Changes,即可叫出此視窗。它是以平面方式(Flat Mode)、不分目錄階層展現所有正在異動的檔案列表,您可以一目瞭然了解目前有那些檔案正在異動中。並可透過它連結Work Item、Check-in Notes、執行Shelve、Unshelve等動作。

clip_image006

圖3 Pending Changes視窗

3 相關功能介紹

clip_image008

圖4 程式碼管控功能架構

Changeset(變動集)是VSTS2010程式碼管控的最基本單位,每一次的簽入(Check In)皆會自動產生一組編號,代表本次的異動,Changeset裡包含所有相關檔案的異動,如新增檔案、刪除檔案、修改檔案內容,更改檔名、更改目錄等。Changeset一旦產生後便無法刪除。ChangeSet之間可以互相比較,顯示差異的內容。

Label(標籤)用於標註Changeset,因為Changeset只是一組編號,不具可讀性,透過Label您可以使用有意義的名稱加以標示,如Beta1、Beta2,Versio1.0等。

Branch(分支)的應用時機在於多個版本同時發展的情境,例如我們完成了版本1.0,並且上線了,後續仍有維護的工作進行,但是我們仍須持續發展版本2.0,加上新功能,此時透過Branch分出兩個版本,其實是兩個不同目錄,如此兩個版本便不會互相干擾。過了一段時間,在版本1.0會修改一些Bug,想當然耳,這些Bug一定也存在版本2.0,此時可透過Merge(合併)功能進行比對,將異動部份更新至版本2.0。

Shelve用於下列情境:

l 當您的開發工作做到一半,是您的程式碼需要別人幫您檢視或驗證

l 半成品的程式碼想要備份

您可以透過此功能分享程式碼給其他人,而不會干擾到實際版本管控裡的程式碼。

Check-in Policy用於當程式碼簽入之前,您可以應用一些規則來檢查是否有違反,若有不符合之處,便不允許簽入。

Changeset與Shelveset都可以跟Work Item進行連結,這樣的好處是後續可以追溯當初修改這段程式碼是為了什麼目的。

4 程式碼管控步驟

為什麼要刻意提供程式碼管控流程?因為VSTS提供了很大的彈性,同樣的功能,您可以透過不同的方法執行,以簽入(Check In)程式碼為例,您可以在Solution Explorer 對欲任一檔案按右鍵選”Check In”,也可以對某一目錄、某一專案或整個Solution按右鍵選”Check In”,或是在Pending Changes視窗,勾選檔案後按[Check In]鈕。因為有這麼多種方式都能執行簽入(Check In)動作,但執行結果其實是有差異的,如透過Pending Changes視窗只會簽入(Check In)勾選項目,但是透過Solution根節點簽入,會遞迴簽入(Check In)所有異動的項目。

所以若沒有流程規範程式碼管控,會導致簽入(Check In)檔案是不一致,如程式碼已簽入,但相關專案檔卻未簽入(Check In),造成其他專案成員拿不到完整專案程式碼,無法編譯程式,最後程式碼管控會變成垃圾堆,專案成員想到就丟進去,但它不是最新、完整、且一致的程式碼儲存庫。

以下介紹的流程是筆者自身的經驗,並經多年試鍊證明,確實可以達成程式碼管控的目標。

clip_image010

圖5 程式碼管控步驟

4.1 簽入Solution

時機:在系統設計階段尾聲及系統實作階段初始之間,系統設計人員架構出整個系統雛型時。

說明:完整性很重要,Solution檔、專案檔、資源檔一個都不可漏。目標是讓專案開發人員只要執行後續”取得最新程式碼”動作,不須額外步驟即可編譯、執行程式碼,進行測試。

步驟:

  • 將Solution整理好,並確定可正常編譯。
  • 在Solution Explorer,對根節點選”Add Solution to Source Control”
  • 確認程式碼管控目錄名稱(The Solution Folder),預設為Solution名稱,按[OK]鈕。

clip_image012

圖6 確認程式碼管控目錄

此時所有目錄與檔案前面皆有”+”符號,表示這些目錄或檔案屬於新增項目,對Solution根節點按右鍵選”Check In”,完成後”+”會變成鎖頭符號,表示整個Solution簽入(Check In)成功。

clip_image014

圖7 整個Solution加入版本管控

4.2 取得完整Solution

時機:開發人員首次取得完整程式碼時。

說明:透過這個步驟,開發人員完成本機測試環境設置,如安裝Visual Studio、安裝SQL Server,接下來取得完整專案程式碼後,便可直接進行程式編譯,開始他的開發工作。

步驟:

  • 在Source Control Explorer選擇對應的.sln檔,按右鍵選”Get Latest Version”。

clip_image016

圖8 選擇.sln檔

  • 選擇本機路徑,然後按[Map]鈕。

clip_image018

圖9 選擇本機路徑

  • 在Source Control Explorer,對.sln檔滑鼠點擊兩下。如此.sln檔會自動取得相關的專案檔,如.csproj檔、.vbproj檔,接下來連接到相關目錄與檔案,如同一串粽子,只要提起最上面繩頭,一整串都提起來了。

4.3 取得最新程式碼

時機:每日開發工作開始前,或程式碼有重大更新,需要所有開發人員馬上同步更新時。

說明:透過這個步驟,開發人員完成本機測試環境設置,如安裝Visual Studio、安裝SQL Server等,接下來取得完整專案程式碼後,便可直接進行程式編譯,開始他的開發工作。

步驟:

  • 在Solution Explorer視窗點選Solution根節點,按右鍵選擇"Get Latest Version"。若有發生衝突,請務必解決!
  • 若發生衝突,會在Pending Changes視窗之最後一頁”Conflicts”,有四個選項可用。

clip_image020

圖10 Pending Changes視窗之”Conflicts”頁

功能

說明

AutoMerge

TFS自動幫您進行合併動作,筆者強烈建議不要使用此選項,因為自動合併無法考慮到真實邏輯,合併後的結果可能會變成不合邏輯、無法執行的程式碼。

Merge Changes In Merge Tool

使用Merge Tool功能,讓使用者手動進行合併動作,筆者建議儘量使用此功能解決衝突。

Take Server Version

放棄本機端的異動,以伺服器端最新版本來取代本機端的。

Keep Local Version

保留本機端的異動,屆時可直接覆蓋掉伺服器端版本。

表1 解決衝突選項

點選[Merge Changes In Merge Tool]鈕,會出現以下畫面,左上角代表伺服器端版本,右上角是本機端版本,下方則是編輯窗格,是您解決衝突後的結果,TFS會嘗試自動合併,如兩個版本雖然修改同一檔案,但是不同列,自動合併的結果會顯示在編輯窗格;若不幸兩個版本異動在同一列,則必須由讀者自行決定最終結果,您可以使用下方[Previous Change]、[Next Change]鈕來移動各個程式碼有異動的地方,若所有衝突皆已解決,[OK]鈕會Enable。

注意!衝突解決後的結果會先保留在本機端,讀者仍須執行下一步驟完成簽入動作。

clip_image022

圖11 Merge Tool視窗

4.4 簽入程式碼

時機:程式已完成實作,並完成相關程式碼檢查,如命名規則,以及單元測試。

說明:透過這個步驟,您可以將完成的程式碼置入TFS程式碼管控系統。檔案從程式碼管控系統取出後,在Solution Explorer裡會顯示鎖頭標記,並且這些檔案會是唯讀的。

步驟:

  • 執行上一步驟”取得最新程式碼”。
  • 在"Pending Changes"視窗,檢查是否有檔案是您不小心改到的或只是用於測試的修改,您可以選擇它們按右鍵選”Undo”,以回復到程式碼管控系統裡的最新版本。
  • 編譯程式,確認程式可正常編譯。
  • 在"Pending Changes"視窗,勾選所有該簽入的檔案,基本上除了web.config,及一些您很確認是因為本機測試環境差異所引起的修改,其他檔案請一律勾選,不管是不是您親自改過,因為一些控制檔修改,如.sln、.csproj、.vbproj,是由Visual Studio引發的,但它們仍需要簽入(Check In)。

注意!建議不要透過Solution Explorer進行簽入(Check In)動作,因為會很容易遺漏該簽入(Check In)的檔案。

clip_image024

圖12 勾選須簽入(Check In)檔案

  • 連結對應的Work Item,表示本次Check In是為了那一項工作而做。先選[Work Items]鈕,勾選對應Work Item,Check-in Action請選”Associate”選項,最後按[Check In]鈕。

注意!此動作並不是強制要求的,但筆者建議它是一個好習慣,因為後續程式碼維護時,您會有充足的資訊可用。

您可以讓此動作變成強制要求,請參考”Check-in Policy”(會放在專案管理章節)

clip_image026

圖13 連結Work Item

5 執行擱置(Shelve)步驟

時機: 當您的程式碼完成一半,想要請其他專案成員幫忙偵錯或檢視、或想要在正式簽入(Check In)程式碼管控系統前,備份程式碼,以防萬一。

說明:執行此步驟不會干擾到程式碼管控系統裡的程式碼。

步驟:

  • 在Pending Changes視窗,勾選您欲擱置(Shelve)的檔案,然後按[Shelve]鈕。

clip_image028

圖14 進行擱置(Shelve)動作

  • 輸入Shelveset名稱,筆者建議以模組名稱加入日期來命名,如”Module1 100302”,然後按[Shelve]鈕,到此完成擱置(Shelve)動作。

clip_image030

圖15 輸入Shelveset Name

注意!其他專案成員若要取得您的Shelveset,首先須確認他沒有異動到相同的檔案,若有他必須先進行上一步驟—先擱置(Shelve) 他自已的異動部份,然後放棄(Undo)這些異動,才能進行Unshelve動作,因為執行Unshelve時並不提供解決衝突的功能。

  • 輸入這個Shelveset擁有者帳號,再按[Find]鈕,會列出此帳號相關的Shelveset,若您要取得所有人的Shelveset,可輸入”*”。選擇您要的Shelveset後按[Unshelve]鈕。

clip_image032

圖16 進行Unshelve動作

6 執行分支(Branch)步驟

時機:需要一個系統多個版本同時發展時,如版本1.0已經上線了,但我們需要向前發展版本2.0,且同時需要維護版本1.0。

說明:執行分支(Branch)步驟後會在程式碼管控系統複製一份到另外一個目錄,之後兩個目錄彼此獨立,程式碼管控不會互相干擾,但後續可以執行合併(Merge)動作將其中一版本差異部份分享給另一版本。例如版本1.0修正了一些Bug,版本2.0是以版本1.0為基底分支出來的,所以這些Bug一定也存在於版本2.0,透過合併(Merge)功能可以回饋修正程式給版本2.0。

注意!執行合併(Merge)後並不會將兩個分支版本合併成一個版本,僅是內容同步而已,筆者認為合併(Merge)這個詞並不適切,容易造成誤解,同步化(Synchronize)應該比較合適。

步驟:

  • 在Souce Control Explorer,對您欲執行Branch的目錄按右鍵選”Branching and Merging” -> “Branch”。
  • 輸入Branch後的目錄名稱,建議名稱可以是系統名稱加上新版本編號,如”DemoVersionControl20”:

clip_image034

圖17 輸入Branch後的目錄名稱

  • 輸入新Branch之本機對應目錄,完成後按[Map]鈕:

clip_image036

圖18 輸入新Branch之本機對應目錄

它會以遞廻方式將欲分支(Branch)目錄下所有檔案進行複製動作,所有新複製的目錄與檔案皆會出現在Pending Changes視窗,此時這些檔案尚未完成分支 (Branch)動作。若確認無誤,請按[Check In]鈕簽入(Check In)所有分支(Branch)異動。

clip_image038

圖19 所有新複製的目錄與檔案會出現在Pending Changes視窗

  • 簽入後在Source Control Explorer視窗會出現兩個目錄有分支(Branch)標示。

clip_image040

圖20 目錄有Branch標示

在Source Control Explorer選擇某一分支(Branch)目錄,按右鍵選”Branching and Merging” -> “View Hierarchy”,會顯示各分支(Branch)的階層關係,若您的系統已經超過三個以上分支(Branch),這張圖可以讓您明瞭各個分支(Branch)的來龍去脈。

clip_image042

圖21 View Hierarchy

7 執行合併(Merge)步驟

時機:執行過分支(Branch)後,兩個分支(Branch)目錄已各自發展一段時間,例如有一些Bug修正,我們想要將這些修正同步更新至另一個分支(Branch)目錄。

注意!執行合併(Merge)步驟的頻率建議不要隔太久時間,一兩個禮拜時間為宜,因為若差異過大,發生衝突機會愈高,程式碼會難以合併。

說明:執行Branch步驟後會在程式碼管控系統複製一份到另外一個目錄,之後兩個目錄彼此獨立,程式碼管控不會互相干擾,但後續可以執行Merge動作將其中一版本差異部份分享給另一版本。例如版本1.0修正了一些Bug,版本2.0是以版本1.0為基底,所以這些Bug一定也存在於版本2.0,透過Merge功能可以回饋修正程式給版本2.0。

步驟:

  • 在Souce Control Explorer,對您欲執行Merge的目錄按右鍵選”Branching and Merging” -> “Merge”,會出現以下畫面,預設Target branch為您所選擇的目錄,Source branch預設為其關聯的分支(Branch)目錄,如父階分支(Branch)目錄。

注意!執行合併(Merge)方式有兩種,第一種是選擇更新至指定版本;第二種是選擇更新那些Changeset,系統會列出那些Changeset是未曾同步過的。

clip_image044

圖22 輸入來源、目的分支(Branch)目錄

  • 選擇Version type如下表,請選”Latest Date”:

功能

說明

Changeset

以指定的Changeset進行合併。

Date

以指定的日期進行合併。

Label

以指定的標籤(Label)進行合併。

Latest Date

為預設值,以程式碼管控系統裡最新版本進行合併。

Workspace Version

以本機端版本進行合併。

表2 Version type選項

clip_image046

圖23 選擇Version type

  • 在Pending Changes視窗會因合併(Merge)而異動的檔案,按[Check In]鈕以完成最後的確認動作。

8 執行標籤(Label)步驟

時機:當您的系統已經發展到一個里程碑,如程式已實作完畢,並完成單元測試,準備進入整合測試階段時。

說明:透過標籤(Label)來標註Changeset,因為Changeset只是一組流水編號,不具可讀性,透過標籤(Label)您可以使用有意義的名稱加以標示,如Beta1、Beta2,Version1.0等,後續我們可以透過標籤(Label)取得特定版本進行相關測試。

步驟:

  • 執行標籤(Label)前首先確認所有Pending Changes都已簽入。
  • 在Source Control Explorer裡,對欲標註Label的目錄按右鍵選”Apply Label”,並輸入Label名稱,建議名稱為專案里程碑名稱或階段名稱,如Beta1,預設”Version”欄位為”Latest Version”,再按[Create]鈕,到此便完成Label標註。

clip_image048

圖24 輸入Label名稱

  • 接下來我們要透過標籤(Label)取出程式碼,在Solution Explorer,對根節點按右鍵選”Get Specific Version”,接著在Version Type欄位選”Label”,再按右邊按鈕進行查詢。

clip_image050

圖25 依標籤(Label)取指定版本

  • 按[Find]進行查詢,Find options可讓您輸入一些條件進行過濾。找到您要的Label,選擇後按[Ok]鈕。

clip_image052

圖26 Find Label

  • 在Label欄位會出現查詢結果,最後按[Get]鈕以取得指定程式碼。

clip_image054

圖27 按[Get]鈕以取得指定程式碼

9 疑難排解

9.1 如何變更本機端程式碼管控目錄?

說明:本機端程式碼管控目錄是由Workspace來管理,所以當您的本機端程式碼目錄想要重整,如C糟硬碟空間不夠,想移至D糟,就必須變更您的Workspace對應關係。

步驟:

  • 在Source Control Explorer裡,下拉選擇右上角”Workspace”欄位,選擇”Workspaces..”,再按[Edit]鈕。

clip_image056

圖28 管理Workspaces畫面

  • 在編輯Workspace畫面裡,下方之Working folders窗格區域有:”Source Control Folder”為程式碼管控系統之目錄;”Local Folder”為本機端對應目錄,按右方按鈕進行變更,完成後請按[OK]鈕。

clip_image058

圖29 變更本機端目錄

  • 詢問是否重新從程式碼管控系統取得一份最新程式碼置於新目錄,請按[是(Y)]鈕,如此即開始取得最新程式碼,完成後之前的舊目錄並不會自動清除,您仍須自行手動刪除。

clip_image060

圖30 詢問是否重新從程式碼管控系統取得一份取新程式碼置於新目錄

9.2 如何將某一檔案回復至上一版本?

說明:有時某個已簽入的程式碼異動(Changeset)經過測試發現有問題,此時需要回復上一個穩定的版本,再進行後續的測試或修改。雖然我們透過”Get Specific Version”暫時取得舊版本,但是無法強制要求所有專案成員直接回復舊版本。透過本步驟可以達成永久回復舊版本的效果。

注意!我們無法刪除在TFS裡的任何一個Changeset,所以只能透過覆蓋的方式來達成我們要的目的。

步驟:

  • 在Solution Explorer,對欲回復上一版本的檔案按右鍵選”View History”,查詢此檔案所有的簽入紀錄,如下圖:

clip_image062

圖31 View History

  • 假設我們要回復的上一版本是Changeset 8,而最新版本是Changeset 11,回到Solution Explorer,對欲回復上一版本的檔案按右鍵選”Get Specific Version”,輸入”Changeset”欄位,如”8”,按[Get]鈕。

clip_image064

圖32 取得舊版本

  • 在Solution Explorer裡,對此檔案按右鍵選”Check Out for Edit”,再按[Check Out]鈕,此時此檔案會標示成修改中。

clip_image066

圖33 Check Out檔案

  • 在Solution Explorer裡,對此檔案按右鍵選”Check In”。

clip_image068

圖34 進行Check In動作

  • 此時一定會發生衝突,請直接按[確定]鈕。

clip_image070

圖35 發生衝突

  • 在Pending Changes視窗裡,按[Keep Local Version]鈕,意思是以目前本機端版本覆蓋掉伺服器端版本,接著要[Check In]鈕。

clip_image072

圖36 以目前本機端版本覆蓋掉伺服器端版本

  • 完成後再以View History查詢,會多出一個新的Changeset,它的內容會與上上一個Changeset相同,如此即達成我們要的版本回復效果。

clip_image074

圖37 再以View History查詢

9.3 程式碼管控進入離線狀態後如何回復?

說明:當碰到網路斷線時,我們仍然可以開啟Visual Studio進行程式編輯與執行,不過後續再連上TFS,Visual Studio並不會自動回復連線狀態,並將離線期間的異動更新回TFS。

步驟:

  • 當您的機器與TFS斷了網路連線時,開啟Visual Studio會出現以下畫面:

clip_image076

圖38 Visual Studio無法連上TFS之訊息

  • 接下來會詢問您是否要進入離線模式(Offline),請按[確定]鈕。

clip_image078

圖39 詢問您是否要進入離線模式

注意!Visual Studio的離線模式是指此Solution暫時脫離程式碼管控,之後所有程式碼管控相關功能都不能用,如Check In、Check Out等,後續仍可執行”Go Online”功能回復程式碼管控相關功能。

  • 在Solution Explorer裡,您可以發現關於程式碼管控相關標誌都不見了,如鎖頭,勾勾等。此時您仍可以進行程式碼編輯與編譯等功能。

clip_image080

圖40 離線模式

  • 待與TFS連線回復後,記得要重新開啟Visual Studio,在Solution Explorer裡,對根節點按右鍵選”Go Online”,會出現以下視窗,列出離線期間所有異動的檔案,可能會包含許多執行檔(.exe)、函式庫(.dll)等,您僅需要勾選您確實有異動的檔案即可,執行檔、函式庫請略過,然後按[Go Online]鈕。

clip_image082

圖41 選擇已變更的檔案,然後按[Go Online]鈕

  • 回復線上(Online)模式成功後,程式碼管控相關標誌都回來啦,如下圖。後續即可進行簽入(Check In)動作。

clip_image084

圖42 回復至線上(Online)模式

9.4 如何檢視程式碼異動情形?

說明:檢視程式碼異動紀錄、分支(Branch)紀錄,同一檔案裡每一區段之異動人員與相應Work Item,從Work Item查詢相關程式碼異動。

步驟:

  • 在Solution Explorer裡,對欲查詢的檔案按右鍵選”View History”,會顯示所有的Changeset清單,您可以任選兩者進行比較,按[Ctrl]鈕進行選擇,再按右鍵選[Compare]。

clip_image086

圖43 View History

  • 差異視窗會分成兩邊,上方列出其所屬Changeset編號,內容差異的部份會成不同顏色標示:綠色代表新增內容;藍色代表修改內容;紅色代表刪除內容。

clip_image088

圖44 差異視窗

  • 若您想要查詢某一Changeset實際異動內容,在Visual History視窗,選擇欲查詢之Changeset,按右鍵選”Changeset Details”,即可查到此Changeset所有異動檔案清單。若選擇某一檔案,按右鍵選”Compare” -> “With Previous Version”,即可查詢此檔案之異動內容。

clip_image090

圖45 查詢相關異動檔案

  • 點選[Work Items]鈕,可查詢相關Work Item。

clip_image092

圖46 查詢相關Work Item

  • 回到View History視窗,若您要查詢相關分支(Branch)紀錄,選擇某一Changeset,按[Track Change]鈕,會列出所有相關的Branch清單,請都勾選起來,再按[Visualize]鈕。

clip_image094

圖47 選擇Branch

  • 會發現此Changeset目前只有套用於”DemoVersionControl”這個Branch(DemoVersionControl方塊裡有Changeset編號且底色是比較深的),而沒有在”DemoVersionControl20”分支,若您想把這個Changeset合併至”DemoVersionControl20”,可直接從”DemoVersionControl”拖曳至”DemoVersionControl20”,即會出現合併(Merge)精靈。

clip_image096

圖48 Tracking Changeset

clip_image097

圖49 合併(Merge)精靈

  • 若您要查詢同一檔案裡每一區段之異動人員與相應Work Item,請開啟欲查詢的檔案內容,對任一處按右鍵選”Source Control” -> “Annotation”,會顯示一個唯讀視窗,右半邊是程式碼內容;左半邊是每一區段最後異動的Changeset編號、修改人員、修改日期,對Changeset連結處點選即可進一步查詢Changeset細節。

clip_image099

圖50 Annotated畫面

  • 若Changeset有連結到Work Item的話還可以查詢到對應的Work Item,以了解修改此段程式碼是為了什麼目的。

clip_image092[1]

圖51 從Changeset查詢Work Item

  • 從Work Item也能查詢相關程式碼異動,切換至Team Explorer,點選您的Team Project -> Work Items -> Team Querys -> 任一查詢,開啟某一Work Item,再切換至”All Links”頁。

clip_image101

圖52 Work Item查詢

clip_image103

圖53 Work Item之”All Links”頁

10 結語

程式碼管控系統相關功能滿多的,且相當複雜,對於初學者需要一些時間練習才能熟悉,對於專案經理而言,落實版本管控流程是很重要的,不然很容易流於形式,變成一個垃圾堆就可惜了。