(本文 crossposting 於 ALPHACamp Blog )
如果說有什麼是開發軟體專案一定要使用的基礎工具,使用「版本控制系統」應該可以記上一筆。無論是個人或是團隊開發,都可以透過版本控制系統獲得巨大的好處。
沒有版本控制系統的話,檔案可能被別人或自己不小心覆蓋或遺失、也不知道是誰因為什麼原因改了這段程式碼、也沒辦法可以復原回前幾天的修改。有了版本控制系統,開發人員只要將每次程式碼的變更都紀錄(Commit)起來,並且透過版本控制系統中進行更新。
有了版本控制系統,我們可以瀏覽所有開發的歷史紀錄,掌握團隊的開發進度,而且作任何修改都不再害怕,因為你可以輕易的復原回之前正常的版本。我們也可以透過分支(Branching)和標籤(Tagging)的功能來進行軟體發行的不同版本,例如穩定版本、維護版本和開發中版本。
已經沒有什麼可以阻礙你使用版本控制系統,Git 或 Mercurial 是免費開源的版本系統系統、隨處可用的網路、便宜的雲端伺服器,甚至有現成的第三方服務 Github 或 Bitbucket。
如果你還沒有使用的話,建議馬上為你的軟體專案建立版本控制。接下來是幾點使用版本控制系統的建議:
是的,「所有」專案中的產出物(Source Artifact)都放到版本控制系統之中,這包括了程式原始碼、測試程式、文件、設定檔、各種自動化腳本等等。除了新成員可以很容易拉出最新的版本馬上開始工作之外,我們也希望在測試環境、正式環境中,也可以隨時更新到我們所指定的版本,因此將所有變更的紀錄保存起來是非常重要的。
例如,資料庫綱要(Schema)的變更也必須納入版本控制。首先,我們在資料庫中紀錄它目前的版本編號。接著我們每次的修改都透過一個自動化腳本來執行,並將這個腳本放入版本控制之中,而不是手動用指令去修改綱要。這樣的好處是團隊中每個人都可以透過版本控制系統看到這個變更,並且升級他的資料庫。測試和正式的伺服器環境,也會透過這個腳本來自動進行升級。筆者熟悉的 Ruby on Rails 中就有內建這樣的 Migration 機制,其他程式語言也有類似的資料庫工具。
另外,以伺服器應用來說,光是有「程式原始碼」還是無法 100% 讓軟體正確地跑起來,我們還需要知道伺服器的配置設定,包括基礎網路設定、作業系統設定、依賴的套件版本等等。因此最好這些配置設定也可以納入版本管理系統之中。近年來雲端技術的進步,已經可以將這些基礎設施設定當作程式( Infrastructure as Code ),無縫地讓每個成員和所有環境都使用完全相同的設定,減少出錯的可能性。
如果久久才遞交(Commit)一次修改到版本控制系統,那麼你只是把版本控制系統當作一種備份工具而已,而沒有享受到它真正的好處。頻繁的遞交可以幫助團隊開發進度的透明化,減少多人開發時的程式碼衝突。當多人同時修改同一塊程式碼時,解決程式碼衝突是很麻煩的事情。還有,我們也希望每一次的遞交有適當的粒度大小,也就是每個 Commit 的內容應該有高度相關性和獨立性。例如是一個小功能或是一個小改進。如果你同時在做新功能A和修舊Bug,那麼就應該分開兩次遞交。語法錯誤無法建構的程式也不應 Commit 造成團隊困擾。
有良好大小的 Commit 的好處除了版本的歷史紀錄更加清楚之外,我們可以非常輕易的做程式碼的復原或移植,假設上述的新功能A有問題,我們可以只復原A而不影響修好的Bug,或是只挑選修Bug的移植到不同分支去。
每一次的遞交我們都必須附上一段解釋訊息,說明修改的內容和原因。這除了可以幫助團隊合作之外,更重要的是讓軟體有更好的維護性,以便將來備查,以下的場景相信開發者都不陌生:
一個好的遞交訊息應該包括一行摘要訊息,描述你為什麼做這段變更,可能是新增、移除、修正某個功能,而不是描述新增或修改哪些檔案,重點應放在 Why 而不是 What。因為修改了哪些檔案和行數我們看版本差異就知道了,無須重複描述。如果你發現很難摘要,那可能表示你包含太多變更在同一次遞交了,請試著拆開。
更多訊息細節可能包括 1. 為什麼這個修改是必要的?因為某種 Workaround? 2. 解決問題背後的原理是什麼? 3. 影響的副作用是什麼?5. 專案管理系統(Issue Tracking System)的關聯票號等等
補充: How to write the perfect pull request