1. 程式人生 > >談談原始碼管理那點事兒(一)——原始碼管理十誡(轉)

談談原始碼管理那點事兒(一)——原始碼管理十誡(轉)

引言:

 若是還有可以毫無偏見地涉及各個程式語言,比原始碼管理軟體更必要的工具,我倒是很想見識一下。原始碼管理軟體是我們工作的必備工具,是許多開發團隊的血液。那為什麼我們都會對它有所誤解呢?為什麼都很難理解版本控制系統的核心價值和基本原理呢?

 原文作者總結出10條慣例(如果你願意也可以用“戒律”)意味著必須服從它,而且一開始很難理解。它們與所有型別程式語言的版本控制軟體都有關聯。在這裡我選取了Subversion和.NET的幾個例子,不過它們也廣泛地適用於其他的一些技術。

  第一誡、如果你現在還在使用VSS,請立刻停手

  它已經死了。當然不完全對,它也存活了許多年,被全新的更實用的原始碼管理工具超越之後還在苟延殘喘地活著。準確地說當微軟(還是會堅持一段時間的),它才是真的死了。

  平心而論,VSS還是一個不錯的工具。在1995年,它的光芒被像Subversion這樣類似於Git和Mercurial的分散式軟體給遮蓋住了。微軟表示要取代它已經好多年了。

  原因是因為不支援如今的標準所導致的一系列缺陷使它一直不被看好。眾所周知它是微軟的悲劇系統,但不知何故它能堅持這麼久,儘管它有那麼多小故障,缺陷,並且不包含必需的功能(相對於今天的標準)。

  第二誡、如果程式碼沒放在原始碼管理軟體裡,等於它不存在

  每天重複讀這句話——“使用原始碼管理軟體是唯一的有效措施”。除非你在工作時使用專案的原始碼管理庫來控制程式碼版本——否則程式碼等於沒有存在過。

  顯然你曾發覺在你的本地機器上執行良好的程式碼在其他人那裡執行的效果並不理想。是不是?他們不能獲取你的最新版本,他們沒法去合併程式碼檔案,你沒有正確地部署它(參考

you're deploying it wrong)而且如果你的SSD硬碟壞了的話,你將永遠地失去你的勞動成果。

  只要你保持這個心態——程式碼只有提交後才是真的安全,才是其他良好程式設計習慣的保障。你可以把你的任務劃分成許多很小的單元以便你逐一提交。你需要頻繁地這麼做。你就不必擔心你的硬體會不會出棘手問題。

  不過更重要的意義是(至少對於你的團隊領導來說),通過原始碼管理軟體可以看到你做了什麼。使用圖表並列出項目清單是個好方法,不過怎麼知道他們實際上在做些什麼?而使用原始碼管理軟體進行工作就能看得一清二楚了。

  第三誡、要早提交,常提交,並且不要覺得麻煩

  關於前面那點,避免“幻影程式碼”(就是隻能在你的機器上看到的程式碼)的唯一方法是經常提交你的任務並且不要覺得麻煩。它可以解決你的問題,不過這樣做也會對你的工作產生其他的影響:

  1. 每個提交的修訂都會為你提供一個還原點。如果你完全把程式碼搞砸了(沒騙你,我們都這麼做過),你是希望恢復到一個小時前的工作還是一週前的工作?

  2. 合併檔案時會出現的危險會隨著時間不斷增加。合併檔案一直很麻煩。如果你不是每天都保持提交程式碼,某一天你會突然發現你和其他人的更改內容會有50多個衝突。你不會為此感到高興的。

  3. 它促使你把任務分離成分散的單元。通常人們都是快完成的時候才提交的,因為他們想把程式碼做成一個完整的邏輯單元模組。不過龐大的任務不可避免地要分離出較小的分散功能,而頻繁地提交它們會使你更瞭解它們,你可以一個個地構建並提交。

  如果你做到這些,你的提交歷史不可避免地開始類似於一種半規律的樣式,裡面每個工作日都是在提交任務。當然不總是這樣,也有停下來重構或測試,或者其他合理的活動也會中斷標準的開發週期。

  然而,當我在看一個獨立的——尤其是完整的專案時,每當發現我們在一個標準的開發週期裡,有一天或幾天什麼都沒有做,我便會非常擔憂。我之所以擔憂是因為這意味著什麼地方出問題了。一般不是有人正在想方設法要把問題搞定的話,就是因為卡在某個問題上而導致專案完全沒有進度。無論到底是什麼情況,原始碼管理軟體都會告訴你出現問題了。

  第四誡、提交前要檢查你更改了什麼

  往原始碼管理軟體裡提交程式碼的步驟其實非常簡單(你恐怕會困惑上一條為什麼說的那麼麻煩)。一般只要發現檔案內容有變更時都會不顧後果地把檔案傳上去。像這樣——“我的專案根目錄下有檔案內容變更了,我要快點提交上去!”

  如此會發生一件(或兩件)事情:首先,程式設計師會沒有意識地把目錄下的垃圾程式碼檔案也上傳上去。一些人看到類似下面的視窗時,就會點選“選擇全部”然後提交——這樣源倉庫裡就會被本不應該存在的未除錯的檔案和其他垃圾檔案給弄亂。enter image description here

  或者是,程式設計師實際上並沒有檢查他們更改過什麼就把檔案上傳了。當你在工作中處理配置檔案或專案定義檔案時很容易就不經意把那些不想提交的檔案給上傳了,而且那些檔案很可能就被別的程式設計師用到了。你真的會記住你在配置檔案裡的所有更改嗎?enter image description here

  解決方法很簡單:你必須在提交前立刻檢查你改過什麼地方。做起來其實比聽起來還要容易。使用許多系統已經提供的“忽略”特性可以大幅度地減輕“不經意上傳檔案”的危險。你可以忽略Thumbs.db檔案因為你壓根不想上傳它。你在每次修訂後可能還有其他檔案不想上傳——那麼就忽略掉它們吧!

  至於檔案裡的更改,你通常可以使用某個流行的文字比較工具來觀察差異。為什麼我又要上傳一次Web.config檔案呢?enter image description here

  噢,我想起來了,我想把嘗試密碼失敗的最大次數從5次減少到3次。啊,我差點沒注意把一個虛擬的登入頁面給上傳上去了。這種在提交前做檢查的練習可以讓你更容易理解下一節的內容。

  第五誡、寫提交資訊時一定要認真

  這是一個古老的諺語(出處不詳),大意是說“寫每一條提交資訊時就好象等下會讀到它的人是一個斧頭殺人狂,而且他還知道你住在哪裡”。如果我是那個殺人狂並在研究你的程式碼想追蹤bug的話,看到的提交資訊全部都是“程式碼更新了”,小心,我會來砍你的!

  我的解決辦法就是解釋清楚為什麼要提交新的程式碼。每次你對程式碼進行更改都是有原因的。可能什麼地方會崩潰。可能客戶不喜歡現在的主題顏色。可能你僅僅要調整一下構建配置。無論是什麼,這都是有原因的而且你要把原因用文字保留下來。

  為什麼?這樣做的原因有很多,而且在不同環境下各不相同。舉個例子,使用“歸屬”特性或其他類似的功能顯示出誰改了程式碼那些地方。如果我不記得18個月之前我對專案的Web.config檔案改過什麼地方或者我為什麼要改動應用程式的設定,是因為我沒有在當時留下一個適當的提交資訊,而現在會非常簡單:enter image description here

  這是一個可以隨時觀察程式碼更改的軟體的一種。無論我像下面那樣想了解一個檔案的完整更改歷史,還是隻想知道團隊昨天做了什麼,留下一個描述性的相關記錄意味著只要不經意一瞥就能知道是什麼情況了。enter image description here

  最後強調一下,當除錯遇到錯誤時提交資訊的重要性是無法估計的。舉個例子,在你的整合環境裡的最後更新的地方可以找到出錯的原因。我的例子是非常顯而易見的,不過把資訊表示出來可以把很多棘手的問題變得極好解決。enter image description here

  把這條牢記於心,這裡列出一些提交資訊的反面教材:

  1. 可惡
  2. 能跑了
  3. 解決了一些混帳問題
  4. 解決了
  5. 改進了一點bug
  6. 上傳了
  7. 排字錯誤
  8. 修訂1024

  好的,我從Stack Overflow網站的哪些是你寫過的最差勁的提交資訊(譯者注:帖子已經被刪除了,原因難道是出現了髒話?)帖子裡選取了以上內容,不過它們和我以前看過的提交資訊並不相同。它們沒有告訴你有關程式碼更改的任何有效資訊;它們都是垃圾資訊。

  關於提交資訊最後要注意的是;同一個程式設計師之後提交資訊絕不能和前面的完全相同。原因很好理解:你向原始碼管理軟體提交檔案是因為對於上一個版本的程式碼有東西改變了。你現在的程式碼和之前的已經不一樣了,如果你的提交資訊是完整準確的,理論上就不能和前面的相同。如果是相同的(可能有時真的會這樣),日誌就會難以閱讀,因為沒有辦法區分兩條提交有什麼區別。

  第六誡、你必須自己提交你的更改內容——不能委託他人

  聽起來很奇怪,但它的確會發生,我看過不止一次,最近的是上週。情況是這樣的,原始碼庫被視為極高的地位。因為很多原因,團隊會去追求完美程式碼的潔淨和單一。為了保持這種神聖的狀態,程式碼只能由某個領頭的程式設計師來提交,他在提交前會小心地整合,審查並(大概會)調整改善程式碼。

  即使站在很遠也能很容易評價這個方案。不太頻繁的提交(可能一週幾次),只有一個脫離團隊其他程式設計師的人來提交,而且不可避免地在這段漫長的無提交時期裡會有人的工作會導致專案混亂。非常非常不好。

  這樣做會有兩個錯誤:首先,原始碼管理軟體並不意味著它裡面程式碼是神聖不可侵犯的;至少在整個開發週期裡是這樣的。它應該是團隊頻繁整合檔案,在出錯時還原到正常並且共同解決問題的地方。不是自始至終都要這樣做,只有在應用程式週期的釋出時期為了達到某種狀態時才做的。

  另一個問題——並且真的是極為關鍵的——站在程式設計師的視角,這樣等於你壓根沒有在用原始碼管理軟體!它等於沒有同伴之間的程式碼整合,沒有還原,提交資訊沒有負責人,什麼都沒有!你們僅僅是在自己的象牙塔裡各自寫各自的程式碼然後等著未來順便某一天把它交給領導就完事了。

  不要這樣做。千萬不要。

  第七誡、一定要管理好資料庫的版本

  這一點是我們都知道必須要做的,但是很多人覺得它麻煩。問題是很多(或者是大部分)應用程式沒了資料庫就不能執行。如果你沒有管理好資料庫,那你實際上做的就是一個不完整的完全無用的應用程式。

  幾乎所有的版本控制系統的工作就是管理好檔案系統內的檔案。它只是對像HTML頁面,圖片,CSS,專案配置檔案和其他在檔案系統的獨立單元這類典型應用作用較大。問題是它確實沒法在與程式有關聯的資料庫上起到作用。你總不能替換掉龐大的資料庫,把所有舊資料檔案和包含一大堆物件和資料日誌檔案統統換掉。這樣會讓版本控制系統完全亂成一堆。

  老實說,如果你沒有管理好你的資料庫版本,你的開發會伴隨著很大的問題。在更改資料庫的時候沒有原始碼的管理,沒有還原點,並且很難和團隊密切合作。使用資料庫版本控制系統可以使開發更輕鬆。

  第八誡、編譯生成的檔案不要放進原始碼管理軟體裡

  簡單地說:在編譯執行專案時自動生成的結果檔案不要放進原始碼管理軟體裡。對於.Net開發的程式設計師,主要是"bin"和"obj"資料夾裡通常會出現的.dll和.pdb檔案。

  為什麼?因為如果你這樣做,你的同事會恨你的。這意味著每當他們從版本控制系統裡取下最新檔案時會讓你的編譯檔案覆蓋掉他們的。這是一個雙重噩夢(你絕不能這樣做),在他們下一次編譯時就會出問題。而且只要他們重新編譯後再把編譯檔案重新上傳上去,同樣的問題會以相反的方向再發生一次,不過這次你是受害者。你肯定不想這樣的。

  當然另一個問題就是這樣做很浪費。這會浪費原始碼管理伺服器的硬碟空間,會浪費頻寬並會通過網路傳送時一直潛伏著,而且這樣做造成的不可避免的衝突會極度浪費你的時間。

  所以我們繼續使用之前提到的“忽略”方案。只要把像"bin"和"obj"這樣的路徑直接忽略掉,一切就真的很輕鬆了。只要按照這種方法做一次,所有人都會感到開心的。

  其實我在寫pre-commit hooks時就說到了在版本控制的伺服器上不能提交此類檔案。當然如果有值得這麼做的原因的話,只有這種情況下你可以上傳。不過我傾向於不要這麼做以免將來會導致某個人在更新時發生衝突。

  第九誡、不要上傳你自己的使用者設定

  老實說,我認為很多人沒有注意到他們把自己的私人設定檔案上傳到原始碼管理軟體裡了。這樣會出現的問題是:許多工具會產生只管理你自己本地配置的檔案。它們只對你有用而且通常和其他人的私人設定檔案相異。如果你把它們上傳到原始碼管理軟體裡,很快你就會覆蓋掉其他人的私人設定檔案。這樣並不好。

  這是一個典型的.NET程式的例子:enter image description here

  假如你沒有立刻清理的話,多餘出來的就是擴充套件檔案和型別描述,也就是.ReSharper.user檔案和.suo(Solution User Option, 解決方案使用者選項)兩個檔案,它們只屬於你,對其他人無效。

  為了理解這點,我們來看看ReSharper檔案:

<Configuration>
  <SettingsComponent>
    <string />
    <integer />
    <boolean>
      <setting name="SolutionAnalysisEnabled">True</setting>
    </boolean>
  </SettingsComponent>
  <RecentFiles>
    <RecentFiles>
      <File id="F985644D-6F99-43AB-93F5-C1569A66B0A7/f:Web.config" 
caret="1121" fromTop="26" />
      <File id="F985644D-6F99-43AB-93F5-C1569A66B0A7/f:Site.Master.cs" 
caret="0" fromTop="0" />

  在這個例子裡,僅僅是在使用者檔案裡記錄了我啟動了解決方案分析功能。這只是針對我,我喜歡這個功能,其他人則不一定。通常因為他們用的是老化的便宜的機子,我有點跑題了。關鍵是我的設定會強制讓其他人也執行。我這麼做不代表其他人也要這麼做。

  這個原理同樣也適用於.suo檔案。不過這裡看不到裡面的內容(它不是XML格式,而是二進位制),這個檔案記錄瞭解決方案瀏覽器的狀態,釋出設定和其他一些你不讓強制用在其他人電腦的東西。

  所以我們要再次使用忽略方案來處理。前提你現在用的不是VSS。

  第十誡、附屬檔案也要整合在一起

  這是十誡中的最後一條也是最最重要的一條。當應用程式需要外部的附屬檔案存在才可以正常執行的話,把那些檔案也都放進原始碼管理軟體裡!人們傾向於犯的錯誤是,在他們擁有自己設定檔案和本地附屬檔案的環境裡一切都表現得很好就把東西都上傳了,之後覺得沒問題了就不管了。但是其他人不能從原始碼庫裡找到同樣的附屬檔案的話,所有東西都會悲劇性地報錯。

  我想到這點是因為今天從原始碼庫裡拖出某個舊專案並執行它時出現了這樣的畫面:enter image description here

  我以為NUnit一直在機器上,但這次沒有。幸運的是使用NuGet可以快速解決問題,但是沒有附屬檔案的話,不是每次都可以用同樣的方式就能輕鬆解決的。有些情況下,它們並不是公開的,你很難全部都獲取到。

  我從原始碼管理軟體裡取出的專案執行時之所以會報錯是因為我發現"C:\Program Files..."路徑下丟失了附屬的檔案。我花了不少時間用來聯絡最後更改過它的那個人(很明顯他在世界上另一個很遠的地方),獲取了那個檔案,把它放進"Libraries"資料夾下並把它上傳到了版本控制系統裡,這樣下一個提取檔案的人就不需要再這麼麻煩了。

  當然另一個重要的原因是,如果你在任何一種整合環境裡工作時,你的構建伺服器不一定安裝了那些庫。你必須有那些檔案才能執行。Doug Rathbone最近寫了一篇很好的關於這點的文章Third party tools live in your source control(原始碼管理軟體裡的第三方工具)。並不是非要那樣做(我們也善意地評價了效果),不過它確實是一個很方便的建議。

  因此推薦每個人第一天就把程式執行所需要的東西全都放進版本控制系統裡。

  小結:

  沒有哪一條是很難理解的。老實說,它們都很基礎:儘快並頻繁地提交,確認你提交的東西改了什麼,還有東西一定要放進版本控制系統裡,解釋清楚你的提交資訊和確保是你自己提交的,不要忘記資料庫和不要忘記附屬檔案。還有就是不要使用VSS:)

  總結:

  原始碼的科學有序管理,不論是對於個人還是團隊還說都是極具價值的一件事情。如此重要的事情,我們該用什麼工具來管理呢?請見一篇部落格:《SVN—TFS,雷鐘意bingo多點?》