- 主版號:當你做了不相容的 API 修改,
- 次版號:當你做了向下相容的功能性新增,
- 修訂號:當你做了向下相容的問題修正。
- 先行版號及版本編譯資訊可以加到「主版號.次版號.修訂號」的後面,作為延伸。
為了讓這套理論運作,你必須先有定義好的公共 API
這可以透過文件定義或程式碼強制要求來實現
無論如何,這套 API 的清楚明瞭是十分重要的
一旦定義了公共 API,就可以透過修改相應的版號來向大家說明你的修改
-
遞增修訂號:修復問題但不影響 API 時
-
遞增次版號:API 保持向下相容的新增及修改時
-
遞增主版號:進行不向下相容的修改時
-
「必須 MUST」採用 X.Y.Z 的格式
-
X、Y 和 Z 為非負的整數
-
「禁止 MUST NOT」在數字前方補零
-
標記版號的軟體發行後,「禁止 MUST NOT」改變該版本軟體的內容
-
任何修改都「必須 MUST」以新版本發行。
-
主版號為零(0.y.z)的軟體處於開發初始階段,一切都可能隨時被改變
- 這樣的公共API 不應該被視為穩定版。
-
1.0.0 的版號用於界定公共 API 的形成
- 這一版本之後所有的版號更新都基於公共 API及其修改內容。
-
修訂號 Z(x.y.Z | x > 0)「必須 MUST」在只做了向下相容的修正時才遞增
-
次版號 Y(x.Y.z | x > 0)「必須 MUST」在有向下相容的新功能出現時遞增
- 「可以 MAY」包括修訂級別的改變。每當次版號遞增時,修訂號「必須 MUST」歸零。
-
主版本號 X(X.y.z | X > 0)「必須 MUST」在有任何不相容的修改被加入公共 API 時遞增
- 「可以 MAY」包括次版號及修訂級別的改變
- 每當主版號遞增時,次版號和修訂號「必須 MUST」歸零
-
任何公共 API 的功能被標記為棄用時也「必須 MUST」遞增
-
也「可以 MAY」在內部程式有大量新功能或改進被加入時遞增
-
先行版號「可以 MAY」被標注在修訂版之後,加上連接號再加上一連串以句點分隔的標識符號來修飾
-
標識符號「必須 MUST」由 ASCII 碼的英數字和連接號[0-9A-Za-z-] 組成
- 且「禁止 MUST NOT」留白
- 數字型的標識符號「禁止 MUSTNOT」在前方補零
- 先行版的優先級低於相關聯的標準版本
- 被標上先行版號則表示這個版本並非穩定而且可能無法達到相容的需求
- 範例:1.0.0-alpha、1.0.0-alpha.1、1.0.0-0.3.7、1.0.0-x.7.z.92。
-
版本編譯資訊「可以 MAY」被標注在修訂版或先行版號之後,先加加號再加上一連串以句點分隔的標識符號來修飾
- 標識符號「必須 MUST」由 ASCII 的英數字和連接號 [0-9A-Za-z-]組成
- 「禁止 MUST NOT」留白
- 當判斷版本的優先層級時,版本編譯資訊「可 SHOULD」被忽略
- 因此當兩個版本只有在版本編譯資訊有差別時,屬於相同的優先層級
- 範例:1.0.0-alpha+001、1.0.0+20130313144700、1.0.0-beta+exp.sha.5114f85。
判斷優先層級時,「必須 MUST」把版本依序拆分為主版號、次版號及修訂號以數值比較
- 例如 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1
- 當主版號、次版號及修訂號都相同時,改以優先層級比較低的先行版號決定
- 例如:1.0.0-alpha <1.0.0
- 有相同主版號、次版號及修訂號的兩個先行版號,其優先層級「必須 MUST」透過由左到右的每個被句點分隔的標識符號來比較,直到找到一個差異值後決定
- 只有數字的標識符號以數值高低比較
- 有字母或連接號時則逐字以 ASCII 的排序來比較
- 數字的標識符號比非數字的標識符號優先層級低
- 若開頭的標識符號都相同時,欄位比較多的先行版號優先層級比較高
- 範例:1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta <1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0。
最簡單的做法是以 0.1.0 作為你的初始化開發版本,並在後續的每次發行時遞增次版號。
- 當你的軟體被用於正式環境,它應該已經達到了 1.0.0 版
- 如果你已經有個穩定的 API 被使用者依賴,也會是 1.0.0 版
- 如果你很擔心向下相容的問題,也應該算是 1.0.0 版了。
- 主版號為零的時候就是為了做快速開發
- 如果你每天都在改變 API,那麼應該仍在主版號為零的階段(0.y.z)
- 或是正在下個主版本的獨立開發分支中。
- 這是開發的責任感和前瞻性的問題。不相容的改變不應該輕易被加入到有許多相依性程式碼的軟體中
- 升級所付出的代價可能是巨大的
- 要遞增主版號來發行不相容的改版,意味著你必須為這些改變所帶來的影響深思熟慮,並且評估所涉及的成本及效益比。
- 為供他人使用的軟體編寫適當的文件,是專業開發者應盡的職責
- 保持專案高效一個非常重要的部份是掌控軟體的複雜度,如果沒有人知道如何使用你的軟體或不知道哪些函數的呼叫是可靠的,要掌控複雜度會是困難的
- 長遠來看,使用語意化版本控制以及對於公共 API 有良好規範的堅持,可以讓每個人及每件事都運行順暢。
- 發現自己破壞了語意化版本控制的規範,就要修正這個問題
- 並發行一個新的次版號來更正這個問題並且恢復向下相容
- 即使是這種情況,也不能去修改已發行的版本
- 可以的話,將有問題的版號記錄到文件中,告訴使用者問題所在,讓他們能夠意識到這是有問題的版本。
如果我更新了自己的相依性但沒有改變公共 API 該怎麼辦? 由於沒有影響到公共 API,這可以被認定是相容的。若某個軟體和你的套件有共同相依性,則它會有自己的相依性規範,作者也會告知可能的衝突。要判斷改版是屬於修訂等級或是次版等級,是依據你更新的相依性關係是為了修復問題或是加入新功能。對於後者,我經常會預期伴隨著更多的程式碼,這顯然會是一個次版號級別的遞增。
如果我變更了公共 API 但無意中未遵循版號的改動怎麼辦呢?(意即在修訂等級的發佈中,誤將重大且不相容的改變加到程式碼之中) 自行做最佳的判斷。如果你有龐大的使用者群在依照公共 API 的意圖而變更行為後會大受影響,那麼最好做一次主版本的發佈,即使嚴格來說這個修復僅是修訂等級的發佈。記住,語意化的版本控制就是透過版號的改變來傳達意義。若這些改變對你的使用者是重要的,那就透過版號來向他們說明。
當你棄用部份公共 API 時,你應該做兩件事
- 1)更新你的文件讓使用者知道這個改變
- 2)在適當的時機將棄用的功能透過新的次版號發佈 在新的主版本完全移除棄用功能前,至少要有一個次版本包含這個棄用資訊,這樣使用者才能平順地轉移到新版 API。
- 沒有,請自行做適當的判斷。舉例來說,長到 255 個字元的版本已過度誇張
- 特定的系統對於字串長度可能會有他們自己的限制。