【GIT】规范提交信息的七大法则

  1. 1. 简介:为什么好的提交信息那么重要?
  2. 2. 提交信息的几条规范
    1. 2.1. 主题和内容之间要空一行
    2. 2.2. 主题最多50个字
    3. 2.3. 主题首字母大写(英文的话)
    4. 2.4. 不要在主题尾部使用句号
    5. 2.5. 在主题中蕴含命令的口吻
    6. 2.6. 内容需要优化每行文本到72个字符
    7. 2.7. 使用内容解释是什么,为什么,怎么办之类的问题

简介:为什么好的提交信息那么重要?

如果你浏览任意一个GIT仓库的日志,你可能就会发现它的提交消息多少有点混乱。比如,看看spring-framework仓库的早期提交:

1
2
3
4
5
6
7
$ 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

然后把这些跟近期的提交做对比:

1
2
3
4
5
6
7
$ 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

你更喜欢哪个呢?

前者长短不一,后者干净整齐;
前者这种情况总会发生,后者绝不会突然发生;

但是大多数仓库的日志看起来像是前者,有很多问题。Linux kernel仓库和GIT本身仓库就是很好的实例。看看Spring Boot,或者任何由Tim Pope管理的仓库。这些仓库的贡献者知道精心设计的提交信息是交流上下文改变的最好方式。diff将会告诉你改变了什么,但是只有提交信息能正确的告诉你为什么。Peter Hutterer这样说:

Re-establishing the context of a piece of code is wasteful. We can’t avoid it completely, so our efforts should go to reducing it [as much] as possible. Commit messages can do exactly that and as a result, a commit message shows whether a developer is a good collaborator.

如果你对GIT的提交信息没有什么想法,那一定是你并没有花费太多时间使用git log和相关工具。这里有一个恶性循环:由于提交历史的杂乱无章,一个人就不会花时间去使用维护它,即而,导致更多杂乱无章的纪录。

精心设计的日志是美好的,有用的。git blamerevertrebaselogshortlog和其他的子命令变得鲜活,查看别人的提交和请求变得更有价值,并且可以迅速完成。了解几个月甚至几年以前的事情不仅变得可能,而且非常有效。

一个工程的长期成功在于它的可维护性,维护者维护工程的时候,几乎没有任何工具比工程日志更有效果。学习怎样维护日志是很值得的。一开始可能是争论但是随后会变成习惯,最终成为所有参与者的骄傲和生产力的源泉。

自这篇文章里,我提到基本健康提交的元素:如何书写个人提交信息。还有其它重要的练习比如合并提交(commit squashing)我并没有提到。可能会在今后的文章里提到。

大多数开发语言都对习惯用语有完善的约定,例如,名称、格式等。这些公约有一些不同,但是大多数开发人员都认为选择一个并坚持使用它远比每个人都做自己的事情时所发生的混乱更好。其实团队日志也是一样的。为了创造一个有用并且可看的历史,团队应该有一个提交信息的公约,定义至少一下三件事:

  • 样式。
  • 内容。
  • 元数据。

幸运地是,已经有一些成熟的约定规定了如何创建提交信息。实际上,其中许多都是以某些Git命令的运行方式来假设的。你不用创造什么,仅仅是遵守以下几条规则而已。

提交信息的几条规范

记住:这些都已经说过无数遍了。

  • 每个主题和内容之间要空一行
  • 主题最多50个字
  • 主题首字母大写(英文的话)
  • 不要在主题尾部使用句号
  • 在主题中蕴含命令的口吻(实际上是动宾短语类)
  • 内容需要优化每行文本到72个字符(因为git本身是右对齐的,而且并不会自动优化显示文字)
  • 使用内容解释是什么,为什么,怎么办之类的问题

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Summarize changes in around 50 characters or less

More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of the commit and the rest of the text as the body. The
blank line separating the summary from the body is critical (unless
you omit the body entirely); various tools like `log`, `shortlog`
and `rebase` can get confused if you run the two together.

Explain the problem that this commit is solving. Focus on why you
are making this change as opposed to how (the code explains that).
Are there side effects or other unintuitive consequences of this
change? Here's the place to explain them.

Further paragraphs come after blank lines.

- Bullet points are okay, too

- Typically a hyphen or asterisk is used for the bullet, preceded
by a single space, with blank lines in between, but conventions
vary here

If you use an issue tracker, put references to them at the bottom,
like this:

Resolves: #123
See also: #456, #789

主题和内容之间要空一行

来自git commit的消息:

Though not required, it’s a good idea to begin the commit message with a single short (less than 50 character) line summarizing the change, followed by a blank line and then a more thorough description. The text up to the first blank line in a commit message is treated as the commit title, and that title is used throughout Git. For example, Git-format-patch(1) turns a commit into email, and it uses the title on the Subject line and the rest of the commit in the body.

第一步,并不是每一个提交都需要主题和内容。有时候一行就足够了,特别是修改非常简单的时候。例如:

1
Fix typo in introduction to user guide

不用说很多;如果说读者想要知道究竟怎么回事,她完全可以看一下修改内容,比如使用git show或者git diff或者git log -p

如果你提交了这些信息,可以使用-m直接提交信息:

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

然而,当一个提交需要解释和内容的时候,你就需要写内容了。例如:

1
2
3
4
5
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选项就有点力不从心了。你最好能在一个编辑器里写这些内容。如果你并没有命令行使用的编辑器,可以看一下this section of Pro Git

在任何情况下,在浏览日志时,主体与身体的分离都会得到回报。以下是完整的日志:

1
2
3
4
5
6
7
8
9
10
$ git log
commit 42e769bdf4894310333942ffc5a15151222a87be
Author: Kevin Flynn <kevin@flynnsarcade.com>
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, 仅仅输出一行主题:

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

使用 git shortlog,通过用户分组,仅显示主题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ 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有很多上下文需要主题和内容,但是如果没有空行的话,上下文就不会很好的工作。

主题最多50个字

50个字符并不是硬性标准,仅仅是经验之谈。这样能确保可读性,强制作者思考组织语言。

Tip: If you’re having a hard time summarizing, you might be committing too many changes at once. Strive for atomic commits (a topic for a separate post).(简而言之,如果描述太长就分开提交)

Github就有这些规则,如果太长他就会提醒你:

并且会截断超过72个字符的主题。

所以限制到50个字符, 考虑将长度硬性限制到72个字符。

主题首字母大写(英文的话)

就像标题写的,很简单,首字母大写。例如:

1
Accelerate to 88 miles per hour

代替

1
accelerate to 88 miles per hour

不要在主题尾部使用句号

主题行中不需要使用句号。 此外,当你试图将它们保持在50个或更少字符时,空间是宝贵的。

1
Open the pod bay doors

代替

1
Open the pod bay doors.

在主题中蕴含命令的口吻

命令的口吻意思是“表达的时候就好像是在发出命令或指示”。下面是几个例子:

  • 收拾你的房间
  • 关门
  • 把垃圾带出去

你现在正在阅读的七条规则中的每一条都在使用命令的口吻。

命令听起来有点粗鲁;这就是为什么我们不经常使用它。但它对于Git提交主题来说是完美的。其中一个原因是,只要代表作者创建提交,Git就会使用命令

例如,当你使用git merge时创建的默认消息是:

1
Merge branch 'myfeature'

使用时git revert

1
2
3
Revert "Add the thing with the stuff"

This reverts commit cc87791524aedd593cff5a74532befe7ab69ce9d.

或者在GitHub拉取请求上单击“合并”按钮时:

1
Merge pull request #123 from someuser/somebranch

因此,当你在命令式中编写提交消息时,你需要遵循Git自己的内置约定。例如:

  • Refactor subsystem X for readability
  • Update getting started documentation
  • Remove deprecated methods
  • Release version 1.0.0

一开始以这种方式书写可能有点尴尬。我们更习惯于在指示性情绪中说话,这完全是事实。这就是为什么提交消息最​​终会像这样读取:

  • Fixed bug with Y
  • Changing behavior of X

有时候,提交消息会被写成对其内容的描述:

  • More fixes for broken stuff
  • Sweet new API methods

为了消除所有的混淆,以下是一个简单的规则去纠正问题。

正确的Git提交主题应始终能够完成以下句子:If applied, this commit will your subject line here

例如:

  • If applied, this commit will refactor subsystem X for readability
  • If applied, this commit will update getting started documentation
  • If applied, this commit will remove deprecated methods
  • If applied, this commit will release version 1.0.0
  • If applied, this commit will merge pull request #123 from user/branch

注意:这不适用于其他非命令性的主题:

  • 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

Remember: Use of the imperative is important only in the subject line. You can relax this restriction when you’re writing the body.

内容需要优化每行文本到72个字符

GIT从来不自动包装文本。当你在文本编辑器中写内容的时候,记得注意右边距,手动包装文本。

建议以72个字符执行此操作,以便Git有足够的空间来缩进文本,同时仍然保持整体不超过80个字符。

一个好的文本编辑器可以在这里帮到你。 例如,在编写Git提交时,可以很容易地配置Vim以将文本行限制为72个字符。然而,IDE为提交消息中的文本提供智能支持方面非常糟糕(尽管在最近的版本中,IDEA终于在这方面做得更好了)。

使用内容解释是什么,为什么,怎么办之类的问题

Bitcoin Core的提交就是一个解释改变了什么和为什么改变的很好的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
commit eb0b56b19017ab5c16c745e6da39c53126924ed6
Author: Pieter Wuille <pieter.wuille@gmail.com>
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.

看看完整的差异,想想作者节省了同事和未来提交者多少时间。 如果他没有这样做,这段提交可能会永远丢失。

在大多数情况下,您可以省略有关如何进行更改的详细信息。 在这方面,代码通常是不言自明的(如果代码太复杂,需要在内容中解释,那就是源代码注释的用途)。 只需要解释你做出改变的原因,改变之前的事情是如何运行的(并且这样运行的问题),他们现在的工作方式,以及为什么你决定以现在的方式解决它。

未来你可能会因此受益。

阅读原文

欢迎访问博客地址:https://www.zhoyq.com