1. 程式人生 > >自家公司關於git commit 的規範

自家公司關於git commit 的規範

程式碼提交的commit info提個建議,fix的issue是哪個issue?都要有明確的連結。
推薦方式:
1.建立issue,說明問題的背景和原因。http://git.startdt.net/payment/paycenter/issues
2.提交程式碼的時候commit info引入該issue
3.測試驗證迴歸以後close 這個issue
這樣就可以做到每一次提交都能追根溯源。提交程式碼的commit info資訊是給自己看的,也是給別人看的。內容翔實自然最好,最基本的是一定要讓別人看懂你提交的是什麼。

寫issue和單元測試很浪費時間麼?尤其是支付的程式碼,到底是浪費時間還是節約時間。

 

英文原文地址 https://chris.beams.io/posts/git-commit/

 

 

 

 

導論:為什麼說commit messages 很重要

如果你翻看某個git repo的log資訊,你可能會發現它的commit messages是一團毛線,比如,看看我在早期在Spring專案中提交的「稀世珍寶」:

$ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009"

e5f4b49 Re-adding ConfigurationPostProcessorTests after its brief removal in r814. @Ignore-ing the testCglibClassesAreLoadedJustInTimeForEnhancement() method as it turns out this was one of the culprits in the recent build breakage. The classloader hacking causes subtle downstream effects, breaking unrelated tests. The test method is still useful, but should only be run on a manual basis to ensure CGLIB is not prematurely classloaded, and should not be run as part of the automated build.
2db0f12 fixed two build-breaking issues: + reverted ClassMetadataReadingVisitor to revision 794 + eliminated ConfigurationPostProcessorTests until further investigation determines why it causes downstream tests to fail (such as the seemingly unrelated ClassPathXmlApplicationContextTests)
147709f Tweaks to package-info.java files
22b25e0 Consolidated Util and MutableAnnotationUtils classes into existing AsmUtils
7f96f57 polishing

噫。比較一下最近提交的commit messages吧:

$ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014"

5ba3db6 Fix failing CompositePropertySourceTests
84564a0 Rework @PropertySource early parsing logic
e142fd1 Add tests for ImportSelector meta-data
887815f Update docbook dependency and generate epub
ac8326d Polish mockito usage

你想讀哪一種呢?

前一種又臭又長;後一種精準一致。前一種來自「不假思索」,而後一種來自「精心組織」。

很多的repo的log資訊都是前一種風格,然而很多卻不是。比如Linux kernel 和 git 本身都是很好的例子。再看看Spring Boot專案,以及所有Tim Pope領導的專案吧。

這些專案的貢獻者都清楚,與專案開發者們(當然也包括了自己)溝通的最好方式是構建一個精巧的 commit messages 結構。diff 會告訴你哪些檔案改動了,但只有commit message能告訴你其中的原因。Peter Hutterer 很好地抓住了要點:

重構程式碼是很浪費時間的。這一點我們完全無法避免,所以我們應該儘可能地減少它,commit messages 就是為了解決這個問題而誕生,而且,它能看出一個開發者是不是一個很好的合作者。

如果你還沒有好好想過一個好的commit message是什麼樣子,那可能是因為你沒在git log以及相關的工具上花很多時間。有一個這樣的怪圈:因為commit的歷史沒有結構性、連續性,沒有人使用或關注這個專案。而又因為沒有人使用、關注這個專案,commit messages的歷史一直保持著無結構、不連續的。

但一個細心維護的log具有美感,並且能起作用。git blame, revert, rebase, log, shortlog 以及其他的子命令來源於生活。審查別人的commits,pull request是很有價值的事情,現在卻變成了獨立的行為。理解幾個月或幾年前這些是怎麼發生的不僅是有可能的,也是有作用的。

一個專案的長時期成功依賴於它的維護性,而專案維護者找不到比專案log更有用的工具了。花時間學習、針對性地實踐是很有用的,萬事開頭難,但一旦成為了習慣,它會成為所有參與者榮耀和生產力的源泉。

在這篇部落格中,我提出的是維護一個健康 commit 歷史資訊的基本要素: 怎麼寫一個commit message。這裡我不會寫其他的重要實踐,比如commit squashing。我可能會在隨後的博文中寫這些。

大多數程式語言有固有的慣例,形成了慣用的風格,也就是命名,格式化這些。當然這些慣例中有很多變數,但大多數程式設計師都同意堅持一種風格比每個人幹自己的、一片混亂要好得多。

一個團隊 commit 的方法也是一樣。為了維護一個有效的版本歷史,團隊首先要在commit message慣例上達成共識,最少要有下面的三項:

  • 風格。 標記語法,折行長度, 語法,大寫規則,標點符號。明確規定這些,不留下猜測空間,儘可能的簡潔。最終的結果是極其一致的log,它讓人樂於閱讀,當然,也實現了基本的功能。

  • 內容。commit message的內容應該包含何種資訊,不應該包含何種資訊。

  • 元資料。 issue 的ID, pull request的數字應該怎麼記錄,索引等等。

幸運的是,有一些完善的慣例指導我們寫 git commit 資訊。當然,很多都是用git命令來解決的。你不需要重新造輪子。遵循下面的七條準則,你就可以像專業人士一樣commit了。

七條準則,寫給力的git commit message

記著, 這都是前人智慧

  • 用空行分開主題和正文

  • 限制主題在50個字母

  • 主題行首字母要大寫

  • 不要用句號結束主題行

  • 主題行用祈使語氣

  • 每行72個字

  • 在正文部分解釋什麼,為什麼,以及怎麼做的

舉個例子

 用不超過50個字簡述一下有哪些改變  

 如果必要的話,寫更多的細節。每行不要超過72個字。第一行被視為 commit 資訊以及餘下正文的主題。空行分開概要和正文是非常必要的(除非你不寫正文);如果你把 log, shortlog, rebase這樣的工具混著用會讓人迷惑。

 解釋一下這個commit解決了什麼問題。專注於為什麼這麼做而不是怎麼做的(程式碼已經解釋了)。這個改變是否有副作用或其他不直觀的後果。這裡就是解釋這些事情的地方。

 空行之後還有段落。

  - 要點符號也是可以的

  - 通常用連字元,星號來表示要點符號。用一個空格起頭,用空行隔開,當然,慣例沒有這麼詳細

如果你用了 issue tracker, 把這些引用放在底部,就像這樣:

解決了:#123
參考: #456, #789

1. 用空行分開主題和正文

來自git commit的幫助文件:

雖不強求,用一個單行(不超過50個字)概述一下改動,跟著一個空行,更多一點描述,這就很好。在第一個空行上的文字會被作為commit的標題,git中會使用到。舉個例子,git-format-patch命令可以把commit轉為郵件,標題就會作為郵件的主題,正文就會當做郵件的正文。

首先,並不是每一個commit都需要標題,正文。有時候一行也可以的,特別是改動比較小,不需要更多的資訊的時候。舉個例子:

修改使用者導讀中的拼寫錯誤

不需要說太多;如果讀者想知道什麼拼寫錯誤,他可以自己看改動,即,用git show,git diff 或 git log -p

如果你在命令列終端中提交,用git commit -m 就很簡單:

git commit -m"Fix typo in introduction to user guide"

但是,如果你的 commit 需要一點點解釋文字,你就需要寫正文了,比如:

Derezz the master control program

MCP turned out to be evil and had become intent on world domination.
This commit throws Tron's disc into MCP (causing its deresolution)
and turns it back into a chess game.

這個用 -m 就沒那麼容易了。你需要一個合適的編輯器,如果你還沒有在終端中給 git 設定編輯器,讀Pro Git(https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#Basic-Client-Configuration)的這一章。

在任何情況下,看log的時候,主題和正文是分開的。這有個完整的log:

$ git log
commit 42e769bdf4894310333942ffc5a15151222a87be
Author: Kevin Flynn <[email protected]>
Date:   Fri Jan 01 00:00:00 1982 -0200

 Derezz the master control program

 MCP turned out to be evil and had become intent on world domination.
 This commit throws Tron's disc into MCP (causing its deresolution)
 and turns it back into a chess game.

如果是git log --oneline, 只輸出主題行:

$ git log --oneline
42e769 Derezz the master control program

或者,用git shortlog, 按照貢獻者分組,按行輸出主題:

$ git shortlog
Kevin Flynn (1):
      Derezz the master control program

Alan Bradley (1):
      Introduce security program "Tron"

Ed Dillinger (3):
      Rename chess program to "MCP"
      Modify chess program
      Upgrade chess program

Walter Gibbs (1):
      Introduce protoype chess program

git中有一些命令可以將主題和正文區分開 ----但主題、正文沒有空行可不行。

2. 限制主題在50個字母

50個字不是硬性標準,只是一個大致的準則。確保主題行是可讀的,讓開發者一眼就知道有哪些改變。

小技巧:如果你概述的時候發現很困難。可能是因為你一次 commit 太多改動了。儘可能做到 atomic commits(每次post一個主題)

GitHub 的使用者介面很注意這些慣例。如果你超過了50個字的限制它會警告你:

github_commit_changes

超過69個字的主題就會用省略號截斷:

truncate_subject

所以,儘可能不要超過50個字,把69個字元當做上限。

3. 主題行首字母要大寫

就這麼簡單。主題行首字母大寫。
比如:

  • Accelerate to 88 miles per hour
    而不是:

  • accelerate to 88 miles per hour

4. 不要用句號結束主題行

主題行結尾的句號是不必要的。而且,要少於50個字元的話,空間是很寶貴的。

比如:

  • Open the pod bay doors
    而不是:

  • Open the pod bay doors.

5. 主題行用祈使語氣

祈使語氣意味著,以命令或指示的語氣說話或寫作。舉幾個例子:

  • 打掃你的房間

  • 把門關上

  • 把垃圾倒了

  • 你正在讀的七條準則就是祈使語氣(例如,正文部分每行72個字)

祈使語氣聽起來有點粗魯;所以我們不常用。但 git commit 的主題行就很合適,一個理由是:無論何時你建立commit,git 本身就是祈使語氣的

比如,git merge 建立的預設資訊是:

 Merge branch 'myfeature'

當你用 git revert 時:

Revert "Add the thing with the stuff"

This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

在 GitHub 上pull request 點「Merge」按鈕的時候:

Merge pull request #123 from someuser/somebranch

所以,當你以祈使語氣 commit messages 的時候,你遵循的正是 git 自身的傳統。 比如:

  • Refactor subsystem X for readability (重構子系統X,增強可讀性)

  • Update getting started documentation (更新初始文件)

  • Remove deprecated methods (移除將廢棄的函式)

  • Release version 1.0.0 (釋出 1.0.0 版本)

用這種方式一開始可能有點不適應。我們更習慣於指示性的語氣,像是報告事實一樣。 因此,commit messages 經常像這樣:

  • Fixed bug with Y (用 Y 解決了bug)

  • Changing behavior of X (改變了 X 的行為)

有時候 commit messages 只是在描述 commit 的內容:

  • More fixes for broken stuff (更多修復)

  • Sweet new API methods (優雅的新API)

為了消除困惑,這有一條簡單的準則:

**一個合理格式化後的 git commit 主題行總能替換到下面的句子中: **

如果應用了,這個 commit 會你的主題行
比如:

  • 如果應用了,這個 commit 會重構子系統X,增強可讀性

  • 如果應用了,這個 commit 會更新初始文件

  • 如果應用了,這個 commit 會移除將廢棄的函式

  • 如果應用了,這個 commit 會發布 1.0.0 版本

  • 如果應用了,這個 commit 會合並來自 user/branch 的pull request #123

注意,在非祈使的條件下就不適用了,如:

  • If applied, this commit will fixed bug with Y

  • If applied, this commit will changing behavior of X

  • If applied, this commit will more fixes for broken stuff

  • If applied, this commit will sweet new API methods

記著,在主題行中用祈使句很重要。在寫正文的時候就不用在乎這個限制了。

6. 每行72個字

Git 不會自動折行,當你寫 commit message 的正文時,你必須考慮右邊的長度,人工地折行。

推薦每72個字就折行,讓 git 滿足80個字的限制的時候有足夠的空間縮排正文。

一個好的編輯器就起作用了。配置 Vim 是很簡單的, 比如,設定折行為72個字。一般來說,IDE在智慧折行上表現就很糟糕了(在近期的版本中,IntelliJ IDEA 終於有了比較好的支援)

7. 在正文部分解釋什麼,為什麼,以及怎麼做的

這一Bitcoin Core 的commit很好的說明了什麼改動了,以及為什麼改動:

commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <[email protected]>
Date:   Fri Aug 1 22:57:55 2014 +0200

   Simplify serialize.h's exception handling

   Remove the 'state' and 'exceptmask' from serialize.h's stream
   implementations, as well as related methods.

   As exceptmask always included 'failbit', and setstate was always
   called with bits = failbit, all it did was immediately raise an
   exception. Get rid of those variables, and replace the setstate
   with direct exception throwing (which also removes some dead
   code).

   As a result, good() is never reached after a failure (there are
   only 2 calls, one of which is in tests), and can just be replaced
   by !eof().

   fail(), clear(n) and exceptions() are just never called. Delete
   them.

看看完整的 diff,想想這個 commit message 給隊友以及後繼的開發者節約了多少時間吧。如果他沒有這樣寫,這些變動可能就永遠都看不到了。

在大多數情況下,你可以忽略變動的細節,程式碼基本上是不言自明的(如果程式碼很複雜,就需要文字解釋,這就需要註釋了),首先說清楚改動的原因----改動前程式碼是怎麼工作的(有什麼問題),現在又是怎樣的,你為什麼要解決這個問題,又是怎麼解決的。

未來感謝你的軟體維護者可能就是你自己!

小技巧

享受命令列,遠離IDE

git 有很多子命令是不無理由的,擁抱命令列是明智的選擇。Git 太TM強大了;IDE 當然也是,但每一種有不同的方式。我每天都用IDE(IntelliJ IDEA),也用其他(如Eclipse), 但我從沒見過能與強大、簡單的終端媲美的集成了git的IDE(你懂得)

誠然,集成了 git 的IDE 很難得,比如可以刪除檔案時呼叫git rm,重新命名檔案是呼叫相關的git命令。但要完成 commit, merge, rebase,或複雜的歷史版本分析時,IDE就捉襟見肘了。

要想充分發揮 git 的威力,那就必須命令列滿螢幕飛了。

記著,不管是用 Bash 或是 Z shell,Tab 補全能讓你減輕記命令的痛苦。

讀《Pro Git》

Pro Git(https://git-scm.com/book/en/v2)是線上,免費的,真是極好的。好好利用!