Semantic Versioning 2.0.0

本文章翻譯自 https://semver.org/
中文版在這里 https://semver.org/lang/zh-CN/豆胸,但讀起來太困難。這里搞一版更教程化, 但又不失嚴謹?shù)摹?/p>

一個良好的版本號的結(jié)構(gòu)與改動規(guī)則,向用戶傳達了我們軟件中改動的影響級別踱稍。
作者在這篇官方文檔里鼠冕,給出了對 semver 的精準定義。

搬運正文

概述

給定一個版本號: MAJOR.MINOR.PATCH (主版本號.次版本號.補丁版本號):

  1. 當你修改了 API,使其(與之前版本)不兼容時溅漾,遞增 MAJOR,
  2. 當你用向后兼容的方式加了些功能時山叮,遞增 MINOR,
  3. 當你用向后兼容的方式解決了幾個 Bug 時,遞增 PATCH添履。

預發(fā)布版本 附加的標簽屁倔,以及與編譯相關的額外信息,可以作為 MAJOR.MINOR.PATCH 這種格式的擴展暮胧,加到版本號的后面锐借。

引言

在軟件管理的世界里, 有個可怕的地方, 叫 "Dependency Hell"[1]. 你的系統(tǒng)規(guī)模增長的越大, 集成到系統(tǒng)里的軟件包越多, 你就越有可能發(fā)現(xiàn), 某天, 你已經(jīng)深深的陷入了這種絕望之地.

在那些有很多依賴包的系統(tǒng)里, 發(fā)布新的軟件包版本很快就會變成一個夢靨. 如果依賴要求太緊, 你可能會陷入 "版本鎖定" [2]. 如果版本要求太松, 你又不可避免的遭受"版本濫交"[3]之痛. [4]. 而所謂的 "Dependency Hell", 就是當 "版本鎖定" 和/或 "版本濫交" 阻止你簡單, 安全的推動項目前行的時候, 你的處境.

作為這個問題的一個解決方案, 我提議一套簡單的規(guī)則和要求, 以規(guī)定如何分配和增長版本號. 這些規(guī)定基于, 但不限于已經(jīng)在各種閉源, 開源軟件中廣泛使用的普遍慣例. 要想這套理論奏效, 首先你得聲明一個公開的 API. API 可能是由文檔組成的, 也可能是直接使用代碼實現(xiàn)的. 但不管怎樣, 重要的是這個 API 是清晰和精確的. 一旦你確定了你的 API, 使用增加特定的版本號的方式, 來傳達 API 的改動. 考慮一個 X.Y.Z (MAJOR.MINOR.PATCH) 的版本號格式: 那么, 不影響 API 的Bug修復: 遞增補丁版本號Z; 向后兼容的 API 的添加或修改: 遞增次版本號; 不向后兼容的 API 的修改: 遞增主版本號.

這套理論我稱作 "Semantic Versioning", 那些個版本號以及他們的改變傳達著與 底層代碼, 以及從一個版本到另一個版本改了什么 相關的含義.

Semantic Versioning 規(guī)范

  1. 使用 Semantic Versioning 的軟件 必須 聲明一個公共的 API. 這個 API 可能是定義在代碼里的, 或者僅僅存在于文檔里, 不論用什么方式實現(xiàn), 它都必須精確而全面.

  2. 一個正常的版本號必須使用 X.Y.Z 的格式, 其中 X, Y, 和 Z 都是非負的整數(shù), 并且 必須不能 包含前導零.
    X 是主版本號, Y 是次版本號, 而 Z 是補丁版本號. 每個元素都必須以數(shù)字的方式遞增. 舉例: 1.9.0 -> 1.10.0 -> 1.11.0.

  3. 一旦一個打了版本的包被發(fā)布出去了, 那個版本的內(nèi)容就 不能 再修改了. 任何修改 必須 作為一個新的版本重新發(fā)布.

  4. 主版本為零 (0.y.z) 的版本, 是用作初始開發(fā)階段的. 任何東西都可能在任意的時間被更改. 這時候我們不應該認為它的 API 是穩(wěn)定的.

  5. 1.0.0 版本表明對外公開 API 的形成. 從此之后, 版本號的遞增方式取決于這個公開的API, 以及它如何修訂.

  6. 補丁版本號Z (x.y.Z | x > 0) . 如果只有向后兼容的bug修復被引入的化, 補丁版本號 Z 必須 遞增. "Bug修復"是指一個修正錯誤行為的內(nèi)部修改.

  7. 次版本號Y (x.Y.z | x > 0). 如果一個新的, 向后兼容的功能被引入到了公開 API 里, 次版本號 必須 遞增. 如果公開 API 的任何功能被標記為 "已棄用的", 次版本號 必須 遞增. 如果大量的新功能或改進被引入到私有代碼里的時候, 次版本號 可以 遞增. 次版本號的改變 可以 包含補丁級別的改動. 當遞增了次版本號的時候, 補丁版本號 必須 清零.

  8. 主版本號X (X.y.z | X > 0). 如果任何的向后不兼容的改動被引入到了公開 API中, 主版本號 必須 遞增. 它的遞增 可以 包含次版本和補丁級的改動. 當主版本號遞增時, 次版本號和補丁版本號 必須 清零.

  9. 一個預發(fā)布版本 可以 通過在補丁版本號后面追加一個短線, 以及一系列的用點分割的標識符 來描述. 標識符 必須 僅包含 ASCII 的 阿拉伯數(shù)字和短線 [0-9A-Za-z-]. 標識符 必須不 為空. 數(shù)字標識符 不能 包含前導零. 預發(fā)布版本比對應的正常版本的優(yōu)先級要低. 預發(fā)布版本表明, 它不穩(wěn)定, 并且可能不滿足其對應的正常版本所預定的兼容性要求. 例子: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92.

  10. 編譯時的附加信息, 可以 通過在補丁版本號后面追加一個加號, 以及一系列的用點分割的標識符 來描述. 標識符 必須 僅包含 ASCII 的 阿拉伯數(shù)字和短線 [0-9A-Za-z-]. 標識符 必須不 為空. 在比較版本優(yōu)先級的時候, 編譯附加信息 應該 被忽略. 因此, 兩個只有編譯附加信息不同的版本, 具有相同的優(yōu)先級. 編譯附加信息的舉例: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85.

  11. 優(yōu)先級是指在排序的時候怎樣比較不同的版本. 計算優(yōu)先級的時候, 必須 將版本號以 "主版本號", "次版本號", "補丁版本號", "預發(fā)布標識符" 的順序拆分. 優(yōu)先級取決于, 在從左至右依次比較這些個標識符的時候, 發(fā)現(xiàn)的第一個差別. "主版本號", "次版本號", "補丁版本號" 總是以數(shù)字的方式參加比較. 舉例: 1.0.0 < 2.0.0 < 2.1.0 < 2.1.1.
    當"主版本號", "次版本號", "補丁版本號" 都相同的時候, 預發(fā)布版本比正常的版本優(yōu)先級要低. 舉例: 1.0.0-alpha < 1.0.0.
    如果兩個預發(fā)布版本有相同的 "主版本號", "次版本號", "補丁版本號", 優(yōu)先級就 必須 通過比較點分割的標識符來確定, 從左至右依次比較, 直到發(fā)現(xiàn)一個不同: 只有數(shù)字的標識符號以數(shù)值高低比較, 有字母或連接號時則逐字以 ASCII 的排序來比較. 數(shù)字的標識符號比非數(shù)字的標識符號優(yōu)先級低. 若開頭的標識符號都相同時, 字段比較多的預發(fā)布版本號優(yōu)先層級高. 舉例: 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.

為什么使用 Semantic Versioning ?

(我的這套理論) 并不是什么新的或者革命性的點子,實際上往衷,很可能你已經(jīng)做了些很接近這個的工作钞翔。但問題在于,僅僅是“接近”并不夠席舍。如果不遵守有點兒"官方"的協(xié)定布轿,版本號對于管理依賴來說基本沒什么用。通過給我上面的思想命名来颤,并給予其清晰的定義汰扭,將你的意圖傳達給你的軟件的用戶就變得很簡單了。一旦意圖清晰明了福铅,最終一個靈活的(但也不是過于靈活的)軟件依賴要求就可以搞定了萝毛。
我們可以通過一個簡單的例子,展示一下 Semantic Versioning 可以讓 “Dependency Hell” 成為歷史滑黔“拾考慮一個叫做 “消防車” 的版本庫,他需要一個使用了 Semantically Version 的軟件包 “梯子”略荡。當 “消防車” 剛創(chuàng)建的時候色查,“梯子”在3.1.0 版本。因為“消防車”使用了 “梯子” 3.1.0 新引入的功能撞芍,你可以簡單的指定秧了,你的“消防車” 對“梯子”的依賴要求是:大于等于 3.1.0 ,但小于 4.0.0 ⌒蛭蓿現(xiàn)在验毡,梯子 "3.1.1" 和 "3.2.0" 好了,你可以把他們發(fā)布到你的軟件包管理系統(tǒng)帝嗡,并且你知道他們跟現(xiàn)有的晶通、跟它有依賴關系的包是兼容的。
作為一個負責人的開發(fā)者哟玷,你當然想驗證任何軟件包升級都是正常的狮辽、跟你宣傳的一樣一也。但現(xiàn)實世界是一團亂麻,對此我們除了小心再小心之外沒有更好的辦法喉脖。你能做的椰苟,是讓 “Semantic Versioning” 提供你一個合理的方法去發(fā)布、升級軟件包树叽,而不必去搞許多新版的依賴包舆蝴,節(jié)省了你的時間,免去了許多麻煩题诵。
如果所有這些聽起來挺給力的洁仗,要開始使用 “Semantic Versioning” 的話,你只需要聲明你正在這么搞性锭,然后遵守這些規(guī)范就好了赠潦。把這個網(wǎng)站鏈接到你的 README 文檔里,以便其他其他人也可以了解這些規(guī)則草冈,并從中受益祭椰。

FAQ

  • 在初始開發(fā)階段,怎么去處理 0.y.z 的版本號疲陕?
    一個簡單的做法是, 使用 0.1.0 作為第一版初始開發(fā)版本號钉赁,然后為隨后的發(fā)布包遞增次版本號(minor version)
  • 我怎么知道什么時候發(fā)布 1.0.0 版蹄殃?
    如果你的軟件已經(jīng)在生產(chǎn)環(huán)境了(已經(jīng)上線了), 很可能已經(jīng) 1.0.0 了。如果你做好了一個 從此用戶可以信賴的你踩、穩(wěn)定的API版本诅岩,你應該發(fā)布1.0.0。如果你正為向后兼容的事情心煩带膜,你應該早就 1.0.0 了吩谦。
  • 這東西難道不會阻撓快速開發(fā)、快速迭代嗎膝藕?
    為零的主版本就是為了快速開發(fā)的式廷。如果你每天都在改 API,你要么還在 0.y.z芭挽,要么在另外一個開發(fā)分支上滑废,為下一個主版本做準備。
  • 如果袜爪,哪怕是微小的 API 的不兼容改動蠕趁,主版本都要蹦,我豈不是很快就到 42.0.0 版了辛馆?
    這是個關于為開發(fā)負責俺陋,以及前瞻性的問題。在有許多代碼依賴之的軟件中,不應該輕率的做不兼容的改動腊状。升級招致的代價可能是相當大的诱咏。不得不通過遞增主版本號來發(fā)行不兼容的改版,意味著你將充分考慮改動所帶來的影響寿酌,并且評估所涉及的 成本/收益 比胰苏。
  • 整理個 API 的文檔太費事兒了!
    為供他人使用的軟件編寫適當?shù)奈募继郏悄阕鳛橐幻麑I(yè)的開發(fā)者應盡的職責硕并。“管理項目復雜度” 是保持項目高效的非常重要的一部分秧荆,而如果沒有人知道如何使用你的軟件倔毙,或者不知道哪些函數(shù)可以放心的調(diào)用的話,就不好做乙濒。Semantic Versioning陕赃,以及對 良好定義的API 的堅持,可以讓每個人颁股、每件事情都順利進行么库。
  • 要是我不小心把一個不向后兼容的改動當成一個次版本號發(fā)布了怎么辦?
    一旦發(fā)現(xiàn)你破壞了 Semantic Versioning 規(guī)范甘有,馬上解決這個問題诉儒,然后發(fā)布一個新的次版本,以恢復向后兼容亏掀。即使在這種情況下忱反,直接修改已經(jīng)發(fā)行的版本也是不可接受的。如合適滤愕,在文檔里寫明這個有問題的版本温算,并將這個問題告知你的用戶,以便用戶知曉這個出問題的版本间影。
  • 如果我在沒有更新API的前提下注竿,更新了我自己(軟件)的依賴,應該怎么做魂贬?
    由于沒有影響到公共 API蔓搞,這將被當做是兼容的。那些使用了跟你一樣的依賴包的軟件随橘,應該也有自己的依賴要求喂分,并且如果有沖突的話,他們的作者會注意到的机蔗。要判定改動是屬于補丁級別還是次版級別蒲祈,要看你更新依賴包是為了修復Bug甘萧,還是添加新功能。對于后者梆掸,我通常覺著會有額外的代碼扬卷,這種情況下,顯然是一個次版本號級別的遞增酸钦。
  • 如果我變更了公共 API 但無意中未遵循版本號的改動怎么辦呢怪得?(意即在補丁級的發(fā)布中,誤將重大且不兼容的改變加到了代碼之中)
    自行做最佳的判斷卑硫。如果改回 API 預期的行為將強烈的影響你的大量受眾徒恋,那么可能最好再發(fā)一個主版本吧,即使這個修復僅僅被當做一個補丁版本欢伏。記住入挣,Semantic Versioning 所做的就是,通過版本號的改動傳達含義硝拧。若這些改變對你的使用者很重要径筏,那就通過版本號來告知他們。
  • 我該如何處理即將棄用的功能障陶?
    棄用現(xiàn)存的功能滋恬,是軟件開發(fā)中正常的一部分,也通常是向前發(fā)展所必須的抱究。當你棄用部份 API 時恢氯,你應該做兩件事:(1)更新你的文檔讓使用者知道這個改變(2)發(fā)布一個新的、仍然包含這些已經(jīng)棄用的API 的次版本媳维。在你從新的主版本里完全移除這些已棄用的功能之前,至少要有一個次版本 仍然包含這些已經(jīng)棄用的 API遏暴,這樣使用者才能平滑地轉(zhuǎn)移到新版 API侄刽。
  • Semantic Versioning 對于版本的字串長度是否有限制呢?
    沒有朋凉,但自行判斷州丹。舉例來說,一個包含255個字符的版本字符串很可能太過分了杂彭。并且墓毒,特定的系統(tǒng)對于字串長度可能會有他們自己的限制。

  1. "依賴地獄". 因為不好翻譯, 就不譯了. ?

  2. "version lock" (如果不為每一個依賴包都發(fā)布一個新版本, 就沒辦法升級某個軟件包). ?

  3. "version promiscuity" (承擔了與太多未來版本兼容的責任, 遠遠超過合理的需要). ?

  4. 依賴過緊舉例: 假設軟件 A 依賴軟件 B, 聲明 A 的當前版需要 B 的 v1.1 版本, A 的下一個版本需要 B 的 v1.2 版本. 這就過緊了. 這樣如果要將A升級到下一個版本, 你就不得不同時發(fā)布 B 的 v1.2 版本; 依賴過松舉例: 聲明 A的當前版本需要B, 只要 B 的版本大于 v1.1 即可. 這樣子A 負擔過重了, 處理與太多的B的未來版本的兼容問題, 沒什么必要. ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亲怠,一起剝皮案震驚了整個濱河市所计,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌团秽,老刑警劉巖主胧,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叭首,死亡現(xiàn)場離奇詭異,居然都是意外死亡踪栋,警方通過查閱死者的電腦和手機焙格,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夷都,“玉大人眷唉,你說我怎么就攤上這事《诠伲” “怎么了冬阳?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長治拿。 經(jīng)常有香客問我摩泪,道長,這世上最難降的妖魔是什么劫谅? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任见坑,我火速辦了婚禮,結(jié)果婚禮上捏检,老公的妹妹穿的比我還像新娘荞驴。我一直安慰自己,他們只是感情好贯城,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布熊楼。 她就那樣靜靜地躺著,像睡著了一般能犯。 火紅的嫁衣襯著肌膚如雪鲫骗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天踩晶,我揣著相機與錄音执泰,去河邊找鬼。 笑死渡蜻,一個胖子當著我的面吹牛术吝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茸苇,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼排苍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了学密?” 一聲冷哼從身側(cè)響起淘衙,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腻暮,沒想到半個月后幔翰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漩氨,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年遗增,在試婚紗的時候發(fā)現(xiàn)自己被綠了叫惊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡做修,死狀恐怖霍狰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饰及,我是刑警寧澤蔗坯,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站燎含,受9級特大地震影響宾濒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屏箍,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一绘梦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赴魁,春花似錦卸奉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至潘拱,卻和暖如春疹鳄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芦岂。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工瘪弓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盔腔。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓杠茬,卻偏偏與公主長得像月褥,于是被迫代替她去往敵國和親弛随。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容