--- title: 如何維護更新日誌 description: 更新日誌絕對不應該是 git log 的堆砌物 language: zh-TW version: 1.1.0 --- .header .title %h1= current_page.data.title %h2 更新日誌絕對不應該是 git log 的堆砌物 = link_to data.links.changelog do Version %strong= current_page.metadata[:page][:version] %pre.changelog{ lang: "en" }= File.read("CHANGELOG.md") .answers %h3#what %a.anchor{ href: "#what", aria_hidden: "true" } 更新日誌是什麼? %p 更新日誌(Change Log)是一個由人工編輯、以時間為倒序的列表,用於記錄專案中每個版本的顯著改動。 %h3#why %a.anchor{ href: "#why", aria_hidden: "true" } 為什麼需要提供更新日誌? %p 為了讓使用者和開發人員更簡單明確地了解各個版本之間有著哪些顯著改動。 %h3#who %a.anchor{ href: "#who", aria_hidden: "true" } 哪些人需要更新日誌? %p 大家都需要更新日誌。無論是開發人員或是使用者,都會在意軟體包含了什麼東西。當軟件有變動時,大家想知道改了些什麼以及為什麼要改。 .good-practices %h3#how %a.anchor{ href: "#how", aria_hidden: "true" } 怎樣寫出高品質的更新日誌? %h4#principles %a.anchor{ href: "#principles", aria_hidden: "true" } 撰寫原則 %ul %li 記住日誌是寫給而非機器的。 %li 每個版本都應該有獨立的入口。 %li 同類改動應該分組放置。 %li 版本與章節應「可連結化」。 %li 新版本在前,舊版本在後。 %li 每個版本都應該註記發佈日期。 %li 版本命名應遵守#{link_to "語義化版本規範", data.links.semver}。 %a.anchor{ href: "#types", aria_hidden: "true" } %h4#types 改動類型 %ul %li %code Added 當增加了新功能。 %li %code Changed 當更動了既有的功能。 %li %code Deprecated 當功能將在近期被移除。 %li %code Removed 當移除了現有的功能。 %li %code Fixed 當修復了某些錯誤。 %li %code Security 當增進了安全性漏洞。 .effort %h3#effort %a.anchor{ href: "#effort", aria_hidden: "true" } 如何提升維護「更新日誌」的效率? %p 在日誌最上方提供 Unreleased 區塊以記錄即將發佈的更新內容。 %p 這樣做有兩個好處: %ul %li 讓大家知道在未來的版本中可能會有哪些改動。 %li 在發佈新版本時,直接將 Unreleased 區塊中的內容移動至新發佈版本的描述區塊就可以了。 .bad-practices %h3#bad-practices %a.anchor{ href: "#bad-practices", aria_hidden: "true" } 有很糟糕的更新日誌嗎? %p 當然有,下面就是一些糟糕的範例。 %h4#log-diffs %a.anchor{ href: "#log-diffs", aria_hidden: "true" } 🚫 直接複製 git log 到更新日誌 %p 使用 git 日誌作為更新日誌是個非常糟糕的方式:git 日誌充滿各種無意義的信息,如合並提交、語焉不詳的提交標題、文檔更新等。 %p 提交的目的是記錄源碼的演化。一些專案會清理提交記錄,但有些不會。 %p 更新日誌的目的則是記錄重要的改動以供受衆閱讀,通常涵蓋多個提交記錄,最終目的仍然是讓看的人一目了然。 %h4#ignoring-deprecations %a.anchor{ href: "#ignoring-deprecations", aria_hidden: "true" } 🚫 忽略即將棄用的功能 %p 當從一個版本升級至另一個時,使用者應清楚(盡管痛苦)地知道哪些部分將不再被支援。應該允許先升級至一個列出哪些功能將會被棄用的版本,待去掉那些不再支持的部分後,再升級至把那些棄用功能真正移除的版本。 %p 即使其他什麼都不做,也至少要在更新日誌中列出棄用的、移除的或是任何可能導致程式碼失效的重大改動。 %h4#confusing-dates %a.anchor{ href: "#confusing-dates", aria_hidden: "true" } 🚫 容易混淆的日期格式 %p 不同區域有著不同的時間格式,要找到讓大家都滿意的日期格式不是件容易的事。使用像2012-06-02 的格式能清楚傳達日期,而且不易與其他日期格式混淆,同時也遵守 #{link_to "ISO 標準", data.links.isodate}。因此,推薦在更新日誌中使用此種日期格式。 %h4#inconsistent-changes %a.anchor{ href: "#inconsistent-changes", aria_hidden: "true" } 🚫 不一致的改動 %p 僅提到部分改動的更新日誌可能和沒有更新日誌一樣危險。 雖然許多改動也許與更新日誌無關——例如,刪除一個空格可能不需要每次都被記錄下來——但任何重要的改動都應該在更新日誌中被提及。 通過不一致地實施改動,使用者可能會錯誤地認為更新日誌是事實的唯一來源(而它也應該是)。 能力越大,責任越大——擁有一個好的更新日誌意味著擁有一個一致性更新的更新日誌。 %aside 還有更多內容?請通過 = link_to "opening an issue", data.links.issue 或是 Pull Request 協助收集。 .frequently-asked-questions %h3#frequently-asked-questions %a.anchor{ href: "#frequently-asked-questions", aria_hidden: "true" } 常見問題 %h4#standard %a.anchor{ href: "#standard", aria_hidden: "true" } 是否有一個標準化的更新日誌格式? %p 並沒有。雖然有 #{link_to "GNU 更新日誌指南", data.links.gnustyle} 以及只有兩段長的 #{link_to "GNU - The NEWS File 指南", data.links.gnunews},但這些並不足以稱為「標準」。 %p 此專案旨在提供一個 #{link_to "更好的更新日誌範例", data.links.changelog},所有點子都來自於對開源社區中優秀實例的觀察與記錄。 %p 歡迎各位#{link_to "提供", data.links.issue}有建設性的批評、討論及建議。 %h4#filename %a.anchor{ href: "#filename", aria_hidden: "true" } 更新日誌的檔案名稱應該是? %p 通常使用 CHANGELOG.md。有些專案將其命名為 HISTORYNEWS 或是 RELEASES。 %p 當然,你可能認為更新日誌的命名並不那麼重要,但為什麼要為難那些僅僅是想看到都有哪些重大改動的使用者呢? %h4#github-releases %a.anchor{ href: "#github-releases", aria_hidden: "true" } GitHub Releases 怎麼樣? %p 這是個非常好的提議。#{link_to "GitHub Releases", data.links.github_releases} 可通過手動添加發佈日誌或將帶有註釋的 git 標簽信息抓取後轉換的方式,將簡單的 git 標簽(如一個叫 v1.0.0 的標簽)轉換為信息豐富的發佈日誌。 %p GitHub Releases 產生的日誌只能在 GitHub 上瀏覽,雖然 GitHub Releases 能做出接近本專案範例的日誌格式,但這會增加些許與 GitHub 的相依性。 %p 現行版本的 GitHub Releases 不像那些典型的大寫文件(READMECONTRIBUTING 等),仍可以認為是不利於使用者探索的。另一個小問題則是目前的 GitHub Releases 界面並沒有提供不同版本間的 commit 日誌的連結。 %h4#automatic %a.anchor{ href: "#automatic", aria_hidden: "true" } 更新日誌可以被自動識別嗎? %p 非常困難,因為有各式各樣的提交訊息和檔案名稱難以完全掌握。 %p #{link_to "Vandamme", data.links.vandamme} 是一個 Ruby 程式,由 Gemnasium 團隊製作,可以解析多種(但絕對不是全部)開源庫的更新日誌。 %h4#yanked %a.anchor{ href: "#yanked", aria_hidden: "true" } 那些後來撤下的版本怎麼辦? %p 因為重大漏洞或安全性問題而被撤下(unpublished)的版本通常不會出現在更新日誌中,但仍然建議記錄下來。你可以這樣作出記錄: %p ## [0.0.5] - 2014-12-13 [YANKED] %p 因為這類更改十分重要,所以 [YANKED] 標簽應該非常醒目,讓使用者注意到它是最重要的事。。此外,用方括號包圍可使其更易被程式識別。 %h4#rewrite %a.anchor{ href: "#rewrite", aria_hidden: "true" } 可以更改過去版本的日誌內容嗎? %p 當然可以。總會有合適的原因去改進更新日誌。我也時常提 Pull Request 來為那些未維護更新日誌的開源專案加入缺失的發佈信息。 %p 另外,你很有可能發現自己忘記記錄一個重大功能更新。這種情況下顯然應該重寫更新日誌。 %h4#contribute %a.anchor{ href: "#contribute", aria_hidden: "true" } 如何貢獻? %p 本文檔並非真理。而是我經過深思熟慮、遵循蒐集到的資訊和範例之後提出的建議。 %p 源於我期望社群能達到共識,我相信討論的過程與結果一樣重要。 %p 所以歡迎#{link_to "貢獻", data.links.repo}。 .press %h3 訪談 %p 我在 #{link_to "The Changelog podcast", data.links.thechangelog} 上講述了為什麼維護者與協作者應該在意更新日誌,以及建立這項專案背後的契機。