如何写好 Git 提交记录

2021-06-25 ⏳4.9分钟(2.0千字)

今天总结一下如何写好 git 提交记录。主要供组内同学参考,也分享给大家。

首先,要正确设置个人信息。正确的个人信息可以帮助后来者快速联系到相关代码的提交者,非常重要‼️

git config --global --set user.name 涛叔
git config --global --set user.email [email protected]

--global 表示修改 git 全局配置。如果个别项目需要使用不同的个人信息,则可以在项目中单独设置,但设置的时候需要去掉 --global 参数。

名字要严肃设置,一个好的名字可以让别人第一时间联想到你,这对项目的持续维护非常重要。作为中国人,我建议大家统一设成自己的中文名。

邮箱要设成能正常接收邮件的邮箱,为的是可以让后来的维护者及时联系到你。有的公司要求用工作邮箱,有的公司允许用私人邮箱。我个人建议尽量使用私人邮箱。因为公司邮箱在离职的时候会被注销,别人就无法联系到你。也有人会认为用公司邮箱好,离职了就不再接收相关邮件。我个人觉得自己提交的代码是自己名声的一部分。如果有人对代码有任何疑问,很欢迎大家与我联系。所以我一般用私人邮箱。

设置好个人信息,我们就有了一个很好的工作基础。

接着,我们就需要讨论如何写提交记录了。

提交记录有两种写法。第一种是使用 -m 参数:

git commit -m '使用smtp发送邮件'

这种方法只能写单行注释。如果不是很小的改动,我不建议大家使用。

另一种方法是不指定 -m 参数:

git commit

此时 git 会打开系统默认的编辑器(可以通过 EDITOR 环境变量提供)。我用的 vim,所以会看到类似界面


# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# Changes to be committed:
#       new file:   a.txt
#

井号#开头的部分是注释,里面会显示当前提交要改动的文件,git 在提交的时候会跳过这些内容。光标会停在第一行,等待用户输入内容。

这个时候,我们需要写两部分:第一行是标题(或者叫主题、摘要),记录本次提交主要改了什么;然后空一行,后面写本次提交的前因后果,也就是为什么这么改。

下面是 nginx 的一次提交记录

[PATCH] Disabled control characters in the Host header.

Control characters (0x00-0x1f, 0x7f) and space are not expected to appear
in the Host header.  Requests with such characters in the Host header are
now unconditionally rejected.

一般来说,一次提交只应包含一个主题的改动。所有的改动可以总结成一个标题。如果你不好给自己的这次提交总结一个标题,那就说明你一次提交的内容太杂乱,不够聚集。这个时候就需要考虑拆分成多次提交了。总之,标题部分是对提交改动的总结,说的是改了什么。

光知道改了什么还不够。我们在维护项目的时候还需要知道为什么这么改。前面的例子就很典型,在提交记录中详细说明为什么要在 Host 头信息中禁用控制字符。

想想这样的场景,大家历尽千辛万苦终于定位到某一行代码导致了BUG,想看看当时为什么这么改。打开 git 提交记录却发现什么也没写或者只写了改了什么,那会是一种什么心情呀。

最近组内也发碰到了一个典型的案例。一个同学的提交记录是:

使用smtp发送邮件

代码改动也确实是把邮件发送逻辑从 AWS 的 SES 迁移到自己的 SMTP 服务。但为什么要这么做呢?提交记录只字未提。我让他重写,最终的效果是这样的:

使用smtp发送邮件

解决aws代发邮件进入垃圾箱的问题 

这就差不多了。其实离我的标准还差一些。我们在决定使用 smtp 发邮件之前还尝试将 aws ses 的服务器加到域名的 spf 记录中,结果并不理想。后来调研发现是因为 aws ses 服务器发了太多垃圾邮件,整个发件域都被列入黑名单了,所以才决定使用自己的 stmp 服务器发送。这些背景信息对后来的维护者同样重要,甚至比具体的代码改动还要重要‼️

那为什么只写「使用smtp发送邮件」不好呢?因为「使用smtp发送邮件」不过是具体代码改动的另一种表达,并没有给后来人提供更多信息,甚至还省略了很多信息(毕竟只有一句就话)。所以,问题的关键是提供更多的信息,来帮助后来的维护者更快速的理解代码改动的来龙去脉。提供不了更多信息的话就是废话。大家不要说废话。

那一定要写成两行吗?要看情况。

就刚才的案例,我们同学实际写成了:

使用smtp发送邮件解决aws代发邮件进入垃圾箱的问题

虽然只有一行,但也算提供了必要的信息,我也让通过了。但一行的长度毕竟有限(一般不应该超过80个字符),很难承载所有信息。所以说还是尽量分行写。

空行是必须的,没有分行所有的内容都会被当成标题,这个会在创建 merge request 的时候有体现。

最后再给大家分享一个经典案例。这个案例来自Brendan Gregg 大神的文章,其大意是 Linux 的平均系统负载除了统计正在运行的进程CPU消耗外,还统计了处于 uninterruptible 状态的进程。进程处于 uninterruptible 状态一般是因为在执行阻塞IO操作或者等待其他进程释放某把锁。按理说这种进程不会消耗 CPU,怎么会影响系统负载呢?经过一番搜索,大神找到了最早的提交记录(当时还没有 git,用的是邮件发的 patch):

From: Matthias Urlichs <[email protected]>
Subject: Load average broken ?
Date: Fri, 29 Oct 1993 11:37:23 +0200

The kernel only counts "runnable" processes when computing the load average.
I don't like that; the problem is that processes which are swapping or
waiting on "fast", i.e. noninterruptible, I/O, also consume resources.

It seems somewhat nonintuitive that the load average goes down when you
replace your fast swap disk with a slow swap disk...

Anyway, the following patch seems to make the load average much more
consistent WRT the subjective speed of the system. And, most important, the
load is still zero when nobody is doing anything. ;-)

--- kernel/sched.c.orig Fri Oct 29 10:31:11 1993
+++ kernel/sched.c  Fri Oct 29 10:32:51 1993
@@ -414,7 +414,9 @@
    unsigned long nr = 0;

    for(p = &LAST_TASK; p > &FIRST_TASK; --p)
-       if (*p && (*p)->state == TASK_RUNNING)
+       if (*p && ((*p)->state == TASK_RUNNING) ||
+                  (*p)->state == TASK_UNINTERRUPTIBLE) ||
+                  (*p)->state == TASK_SWAPPING))
            nr += FIXED_1;
    return nr;
 }

邮件的主题是 Load average broken ?,改动也非常小,就是把 TASK_UNINTERRUPTIBLE 和 TASK_SWAPPING 状态的进程也加到系统负载的统计中去。邮件的正文详细说明了为什么要这样做。原来 linux 的系统负载表示用户感觉到的系统忙碌程度。原来不统计TASK_UNINTERRUPTIBLE 和 TASK_SWAPPING 状态的进程,如果换用更慢的硬盘,系统负载会减小,但用户感觉系统变慢了,这不科学。所以就改了。

我们前面说的 git 提交记录要分开写,就是跟邮件对应的。提交记录的标题对应邮件的主题(subject),空一行写的背景对应邮件的正文。前景内容可以写很多段,也可以任意加空行或者空白。

从邮件的角度我们又可以引申出一条规则,即不要在提交记录的标题中添加标点符号。标题就是邮件的主题,加上标点符号是不是觉得很奇怪🤔

好了,先写到这里。如果大家有补充或不同意见,可以通过邮件联系我。