喜欢条理吧,它能保护你的时间和精力。
简介:为什么好的提交信息那么重要?
如果你浏览任意一个GIT仓库的日志,你可能就会发现它的提交消息多少有点混乱。比如,看看spring-framework仓库的早期提交:
1 | $ git log --oneline -5 --author cbeams --before "Fri Mar 26 2009" |
然后把这些跟近期的提交做对比:
1 | $ git log --oneline -5 --author pwebb --before "Sat Aug 30 2014" |
你更喜欢哪个呢?
前者长短不一,后者干净整齐; 前者这种情况总会发生,后者绝不会突然发生;
但是大多数仓库的日志看起来像是前者,有很多问题。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 blame
、revert
,rebase
,log
,shortlog
和其他的子命令变得鲜活,查看别人的提交和请求变得更有价值,并且可以迅速完成。了解几个月甚至几年以前的事情不仅变得可能,而且非常有效。
一个工程的长期成功在于它的可维护性,维护者维护工程的时候,几乎没有任何工具比工程日志更有效果。学习怎样维护日志是很值得的。一开始可能是争论但是随后会变成习惯,最终成为所有参与者的骄傲和生产力的源泉。
自这篇文章里,我提到基本健康提交的元素:如何书写个人提交信息。还有其它重要的练习比如合并提交(commit squashing)我并没有提到。可能会在今后的文章里提到。
大多数开发语言都对习惯用语有完善的约定,例如,名称、格式等。这些公约有一些不同,但是大多数开发人员都认为选择一个并坚持使用它远比每个人都做自己的事情时所发生的混乱更好。其实团队日志也是一样的。为了创造一个有用并且可看的历史,团队应该有一个提交信息的公约,定义至少一下三件事:
- 样式。
- 内容。
- 元数据。
幸运地是,已经有一些成熟的约定规定了如何创建提交信息。实际上,其中许多都是以某些Git命令的运行方式来假设的。你不用创造什么,仅仅是遵守以下几条规则而已。
提交信息的几条规范
记住:这些都已经说过无数遍了。
- 每个主题和内容之间要空一行
- 主题最多50个字
- 主题首字母大写(英文的话)
- 不要在主题尾部使用句号
- 在主题中蕴含命令的口吻(实际上是动宾短语类)
- 内容需要优化每行文本到72个字符(因为git本身是右对齐的,而且并不会自动优化显示文字)
- 使用内容解释是什么,为什么,怎么办之类的问题
例如:
1 | Summarize changes in around 50 characters or less |
主题和内容之间要空一行
来自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 | Derezz the master control program |
这时候使用-m
选项就有点力不从心了。你最好能在一个编辑器里写这些内容。如果你并没有命令行使用的编辑器,可以看一下this section of Pro Git。
在任何情况下,在浏览日志时,主体与身体的分离都会得到回报。以下是完整的日志:
1 | $ git log |
使用git log --oneline
, 仅仅输出一行主题:
1 | $ git log --oneline |
使用 git shortlog
,通过用户分组,仅显示主题:
1 | $ git shortlog |
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 | Revert "Add the thing with the stuff" |
或者在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 | commit eb0b56b19017ab5c16c745e6da39c53126924ed6 |
看看完整的差异,想想作者节省了同事和未来提交者多少时间。 如果他没有这样做,这段提交可能会永远丢失。
在大多数情况下,您可以省略有关如何进行更改的详细信息。 在这方面,代码通常是不言自明的(如果代码太复杂,需要在内容中解释,那就是源代码注释的用途)。 只需要解释你做出改变的原因,改变之前的事情是如何运行的(并且这样运行的问题),他们现在的工作方式,以及为什么你决定以现在的方式解决它。
未来你可能会因此受益。