Per-project git commit templates

Tyler Cipriani

依專案區分的 Git commit 範本

人們應該試著比較一下核心的 Git 紀錄品質與其他專案,然後抱頭痛哭入睡。

– Linus Torvalds(林納斯·托瓦茲)

我永遠記不住你的專案的提交規範。

每個專案堅持的規範都不一樣:

不過,git commit templates(提交範本)可以幫上忙。Commit templates 為提交訊息提供了鷹架,在你最需要的地方提供說明:就在你撰寫提交訊息的編輯器裡。

什麼是 git commit template?

當你輸入git commit時,Git 會打開你的文字編輯器1。Git 可以用 commit template 預先填入編輯器——就像一份等你填寫的表單。

建立 commit template 非常簡單。

  • 建立一個純文字檔——我的檔案放在~/.config/git/message.txt
  • 告訴 Git 使用它:
git config --global \
    commit.template '~/.config/git/message.txt'

我的預設範本囊括了我對撰寫提交所知的一切。

透過 IncludeIf 設定專案專屬範本

commit templates 真正神奇之處在於,你可以為每個專案使用不同的範本。

透過 Git 的includeIf設定,不同的專案就能使用不同的範本。2

大型專案,例如the Linux kernelgitMediaWiki,都有各自的提交規範。

為了處理 Wikimedia 的工作,我把 Git 儲存庫放在~/Projects/Wikimedia,並在全域 Git 設定檔(~/.config/git/config)的最下方加入:

[includeIf "gitdir:~/Projects/Wikimedia/**"]
    path = ~/.config/git/config.wikimedia

config.wikimedia中,我指向 Wikimedia 專用的 commit template。我也會覆寫其他 Git 設定,例如user.emailcore.hooksPath

範例:我的全域範本

我的預設 commit template 包含三個區段:

  1. Subject——50 個字元以內,首字大寫,結尾不加標點。
  2. Body——每行 72 個字元換行,與 subject 之間空一行。
  3. Trailers——標準格式,與 body 之間空一行。

在每個區段中,我都加入了關於格式3與內容的提示。

對於標頭,指引很簡潔:

# 50ch. wide ----------------------------- SUBJECT
#                                                |
#     "If applied, this commit will..."          |
#                                                |
#     Change / Add / Fix                         |
#     Remove / Update / Document                 |
#                                                |
# ------- ↓ LEAVE BLANK LINE ↓ ---------- /SUBJECT

對於內文,我提醒自己回答幾個基本問題:

# 72ch. wide ------------------------------------------------------ BODY
#                                                                      |
#     - Why should this change be made?                                |
#       - What problem are you solving?                                |
#       - Why this solution?                                           |
#     - What's wrong with the current code?                            |
#     - Are there other ways to do it?                                 |
#     - How can the reviewer confirm it works?                         |
#                                                                      |

就這樣,除了 git trailers 之外。

錯綜複雜的 git trailers 迷宮

我的範本中有一個區段,是給我參與的專案所使用的 trailers。

#     TRAILERS                                                         |
#     --------                                                         |
#     (optional) Uncomment as needed.                                  |
#     Leave a blank line before the trailers.                          |
#                                                                      |
# Bug: #xxxx
# Acked-by: Example User <[email protected]>
# Cc: Example User <[email protected]>
# Co-Authored-by: Example User <[email protected]>
# Requested-by: Example User <[email protected]>
# Reported-by: Example User <[email protected]>
# Reviewed-by: Example User <[email protected]>
# Suggested-by: Example User <[email protected]>
# Tested-by: Example User <[email protected]>
# Thanks: Example User <[email protected]>

這些 trailers 就像是實用的文件線索。Git 可以使用標準指令來解析它們。

舉例來說,如果我想要一份以 Tab 分隔的提交與相關任務清單,我可以用git log來尋找Bug trailers:

$ TAB=%x09
$ BUG_TRAILER='%(trailers:key=Bug,valueonly=true,separator=%x2C )'
$ SHORT_HASH=%h
$ SUBJ=%s
$ FORMAT="${SHORT_HASH}${TAB}${BUG_TRAILER}${TAB}${SUBJ}"
$ git log --topo-order --no-merges \
      --format="$FORMAT"
d2b09deb12f     T359762 Rewrite Kurdish (ku) Latin to Arabic converter
28123a6a262     T332865 tests: Remove non-static fallback in HookRunnerTestBase
4e919a307a4     T328919 tests: Remove unused argument from data provider in PageUpdaterTest
bedd0f685f9             objectcache: Improve `RESTBagOStuff::handleError()`
2182a0c4490     T393219 tests: Remove two data provider in RestStructureTest

別再死記提交訊息規範了

Git commit templates 讓你的大腦不用再記住該寫什麼,讓你專心講好需要敘述的故事。

把腦力留給真正擅長的事吧。


  1. 從 Git 設定中的core.editor開始,接著是 shell 中的$VISUAL$EDITOR,最後則退回至vi↩︎

  2. 你也可以直接在儲存庫的.git/config中設定,如果同一個目錄下有多個採用相同規範的儲存庫,使用includeIf會很方便。↩︎

  3. 全部摘自Tim Pope(提姆·波普)↩︎

原文由 Tyler Cipriani 發布

本文章由 muse-spark-1.2-contributor 進行翻譯