從 TFVC 轉換到 Git,初學者第一個想問的通常是「要怎麼 Check In?」

Git 記錄版本異動的方式與 TFVC 不同。TFVC 的 Check In (簽入)是指將本地檔案修改存入伺服器;而 Git 屬分散式版控,在工作資料夾就本機儲存庫(Repository,放在 .git 隱藏目錄裡),版本異動要先存入本機儲存庫, 再視需要送上伺服器。因此,TFS 的 Check In 對映到 Git 可分成三個動作:
(註:英文後方括號內是 Visual Studio 的中文翻譯,有點彆扭,還是切成英文吧,大給供厚母厚? 而後續說明會用英文為主)

  1. Stage (暫存)
    將工作目錄(Working Directory)中新增、修改或刪除動作放入暫存區(Staging Area)
  2. Commit (認可)
    指將暫存區的異動寫入儲存庫(Repository)保存,Commit 後即可比對、回溯特定版本
  3. Push (推送)
    將 Commit 內容送上伺服器,集中保存並開放其他開發者取回

用一個模擬情境說明:團隊接到新任務,TFS 管理員伺服器上建好專案,給了類似 http://tfs:8080/tfs/ColName/_git/GitDemo 的網址,開發人員在 Visual Studio 的 Team Explorer 用 Clone 建立 X:\Lab\GitDemo 目錄:

開發人員在 X:\Lab\GitDemo 下新增 ASP.NET 專案,修改好第一個版本,準備放入版控。在 Changes (變更) 功能看到以下畫面:

Changes (變更)清單顯示有 141 個修改,上面貼心地提供了 Commit All (全部認可)鈕,是不是按一下就大功告成? 要注意,這裡有個 TFS 轉 Git 新手易踩到的陷阱。

Visual Studio 簽入 TFVC 時預設會排除 bin 等不需納入版控的目錄及檔案,但 Git 不會。故如上圖 .vs、bin 資料夾都在清單中,混入版控將造成困擾。Git 靠 .gitignore 檔案排除不需要的檔案,使用 Settings / Repository Settings / Ignore File / Add 加入 .gitignore 後,Visual Studio 就會排除這些不需加入版控的項目:

加入 .gitignore 後,Changes 清單項目減少為 11 個:

此外,專案若有特定需要額外排除的項目,可使用右鍵選單 Ignore this local item (忽略這個本機項目) 將其納入 .gitignore:

有點比 TFVC 麻煩的是 Git 不會自動排除 TypeScript 編譯結果(.js、.js.map),可借用 TypeScript 檔固定放在 app 目錄的特性,加上**/Scripts/app/**/*.js**/Scripts/app/**/*.map將其排除。

最後再介紹一個技巧,你不一定要將所有 Changes 項目整批 Commit,尤其是其中可能摻雜不同功能的修改或 Bug 修正。將相關修改項目集合起來分成多個 Commit 放入版控是個好主意,有助於讓版本歷程更清晰易管理。做法是在 Changes 清單選擇相關的修改,呼叫右鍵選單執行「Stage」(暫存):

如此選取項目會移至上方「Staged Changes」(暫存的變更)清單:

填寫 Commit 註解後按下「Commit Staged」(暫存認可),這幾項修改會包成一個 Commit 存入。比起混雜 A 功能修改、B Bug 修正、C 參數調整幾十個檔案包成一個 Commit,單一 Commit 只專注一項目標,有利於日後管理(例如,只想將 A 功能合併入分支時,抓取該次 Commit 即可)。

而在 Commit 時,Visual Studio 有三種選項:

  1. Commit Staged (暫存認可)
    將修改存入本機儲存庫
  2. Commit Staged and Push (暫存認可並推送)
    將修改存入本機儲存庫並推送到伺服器保存
  3. Commit Staged and Sync (暫存認可並同步)
    將修改存入本機儲存庫並推送到伺服器保存,再從伺服器取得其他人更新的結果

我建議的做法是:若修改尚未告一段落,將版本異動存在本機就好(選 Commit Staged),可以不用馬上推送到伺服器。 Git 在 Commit 到本機儲存庫後即具有版本比較、還原上一版等能力,不像 TFVC 靠 Check In 寫回伺服器才有版控功能。 而在開發過程中難免反覆修改,每改一點就 Commit 一次可確保任何動作都可以反悔,但這類瑣碎 Commit 在程式寫好後便不再有意義,沒必要上傳到伺服器。而例如打錯字修改、客戶改規格、反悔砍掉重練之類的 Commit, 對團隊其他成員或長久維護毫無幫助,先 Commit 到本機,工作完成後再一次 Push, 讓我們有機會整理 Commit 歷程,移除無意義的過程,一來避免家醜外揚,二來是該程式修改記錄不會太雜亂, 提高 Commit 的品質,這點是 Git 勝過 TFVC 的優勢之一。

以下用個實例示範,假設我不小心在 CSHTML 打錯字,修改時又打錯,錯了又錯,前後搞出三次 Commit 才寫對。 當修改告一段落時,進入 Sync (同步選單),下方 Outgoing Commits(傳出的認可) 會列出所有待 Push 的 Commit。 VS2019 有個我很愛的功能,可以在 Outgoing Commits 選取連續多筆 Commit,用右鍵選單「Squash Commits」合成一筆並重寫 Commit 註解,抺去改了又改的黑歷史並讓 Commit 整潔好讀:

(註:VS2017 UI 未提供 Squash Commits 功能,需使用命令列工具或第三方工具,參考:【狀況題】把多個 Commit 合併成一個 Commit)

除了直接 Squash Commits,Git 還有個無敵指令 - Rebase 允許你重新組裝 Commit 內容,幾乎是無所不能,什麼都能改,什麼都不奇怪,但 Rebase 操作相對複雜,需靠指令或第三方工具,屬進階技巧。

以上是我使用 Visual Studio Git 至今關於 Commit 與 Push 的心得,未來有新體會再更新。

Tips of how to use Visual Studio 2017/2019's Git suppoer to commit and push project changes.


Comments

# by Antony

黑暗大大你好: 請問我的 VS2015 Update3 Update3 沒有 " Ignore this local item " 是需要額外安裝其他套件還是 要2017以上才有? 我查了一下 Stack Overflow 的討論,似乎是為了符合 Git 的理念及流程,所以用 stage 的機制來避免特定的 ignore item 請大大指點迷,謝謝

# by Jeffrey

to Antony, Ignore this local item 的動作其實是去修改 .gitignore (參考: https://gitbook.tw/chapters/using-git/ignore.html ),VS2017 以前的版本你可以手動修改達成同樣效果。(參考: https://marcus116.blogspot.com/2018/12/setup-gitignore-for-visual-studio-projects.html )

# by David Lan

請問各位前輩,如果專案下臨時有Bug要先修正,這時候是否有辦法只傳送部分"Bug修正檔案"上去呢? 使用暫存還是得等全部項目都commit完,才能推送 煩請各位前輩指點,感謝

# by Jeffrey

to David Lan, 可以參考這篇 https://gitbook.tw/chapters/faq/stash.html 。 若想簡單點不想切分支,就用 Stash。我自己的 SOP: 1. 修改一律在開發分支上處理,先 Commit 做一半的東西 2. Reset 回線上版本 Commit 3. 開一個修 Bug 分支 4. 修 Bug、Commit、Push 5. 切回開發分支,Rebase 修好 Bug 的最新版本

Post a comment