养成良好的 Git 使用习惯
本文将介绍一些 Git 的最佳实践,帮助你更好地使用 Git。
提交信息
提交信息是 Git 中最重要的一环。一个好的提交信息可以让你的团队更好地了解你的提交。一个好的提交信息应该包含以下内容:
- 提交的目的
- 提交的内容
- 提交的原因
虽然包含的内容还挺多,但是请尽量控制在 50 个字符以内。这样可以让你的提交信息更加简洁,也更容易阅读。 如果一定要添加更多的解释,请用足够简短的语言来解释,然后换行,用更详细的语言来解释。
分支管理
分支是 Git 中最重要的概念之一。分支可以让你在不影响主分支的情况下进行开发。在开发时,你应该遵循以下原则:
- 主分支是稳定的,不应该直接在主分支上进行开发。
- 每个功能应该在一个独立的分支上进行开发,这样可以更好地管理代码。
- 开发完成后,应该将分支合并到主分支上。
这是我在前面的教程中一定要求大家在语义分支上进行开发的原因。这样可以更好地管理代码,也更容易回滚。
代码审查
代码审查是一个非常重要的环节。代码审查可以让你的代码更加稳定,也可以让你的团队更好地了解你的代码。在代码审查时,你应该遵循以下原则:
- 代码审查应该在开发完成后进行。
- 代码审查应该在一个独立的分支上进行。
- 代码审查应该由其他人进行,这样可以更好地发现问题。最好是一群擅长不同领域的人进行代码审查。
合并分支
通常来说,在本地合并分支时,应该使用 rebase
来合并分支。这样可以让你的提交历史更加清晰,避免出现不必要的合并提交。
在 Pull Request 合并时,应该使用merge
来合并分支。这样可以让你的提交历史更加清晰,也更容易回滚。
Commit 时机
很多新手在使用 Git 时,要么提交太多次。这样会让你的提交历史变得混乱,也会让你的团队很难理解你的提交。要么提交太少,这样会让你的提交历史变得不够详细,也会让你的团队很难理解你的提交。
一个好的提交时机是在你完成一个功能后提交。这样可以让你的提交历史更加清晰,也更容易回滚。
要理解,commit 的本质是patch,当你的 commit 较为复杂时,就不容易patch apply。所以,尽量保持 commit 的简单,但是简单的前提是保证一项功能的完整性。
Git 使用最佳实践
注:以下内容翻译自Git Best Practices – How to Write Meaningful Commits, Effective Pull Requests, and Code Reviews
作者: Grant Riordan
编写有意义的提交信息
在提交代码时,编写有用的提交信息是很有帮助的。以下是一些提示和最佳实践,帮助你做到这一点。
使用祈使句
在提交信息前缀中使用祈使句,例如:fix、refactor、add 和 remove。
这应该是你提交信息的第一个单词,因为它可以很容易地告诉你的同事这个提交的目的:
- “If applied, this code will…”
并告知其他开发人员它将做什么,例如:
- If applied, this code will fix issue with login button not showing
保持简洁
你不是在写独白,所以保持简洁。一般来说,提交信息不应超过 50 个字符。
站在开发人员或审查者的角度思考。如果你在查看这个仓库的 Git 日志时,你会想知道什么?
- 你完成了什么工作?
- 你为什么这样做?
- 它对代码库有什么影响?
以下是一个简洁但信息丰富的提交信息示例:
fix issue with login button not showing
保持简洁但是有意义
在你的提交中,你可以包含提交描述,允许我们添加更多的细节/上下文说明你做了什么。
在提交信息下方添加一个空行,并在第 3 行开始编写描述。它看起来像这样:
fix issue with login buttton not showing
- update login form validation
- update login styling for showing the button
现在,当其他开发人员查看提交历史,或回滚代码时,他们会更清楚地了解会发生什么,以及是否会产生任何副作用。
反面教材
fixed bug – 没有提到具体修复了什么 bug,因此它对 git 历史/日志没有任何价值。这将使审查以前的提交变得极其困难和痛苦。作为开发人员,你必须打开每个这样的提交才能理解它实际上在做什么。
refactored due to PR comments – 此信息没有提供有关更改的任何信息。我们必须追踪 Pull Request 以收集有关所做更改的任何上下文,或者再次打开提交。
fixing previous commit – 同样,缺乏上下文
made tests pass – 更新了哪个测试文件?你至少应该提供已修复的测试名称或区域。 所有这些都是不良提交信息的示例,因为它们含糊不清、缺乏信息和上下文。它们迫使团队成员做更多的工作来理解发生了什么,这是任何团队都不能接受的。
如何制定提交策略
你可能认为提交代码就是简单地提交和推送代码。但实际上,这里面还有一些细微的差别。
让我们来谈谈如何制定一个有用的提交策略,以保持一致性并做出有价值的提交。
进行小而具体的提交
小规模的提交使得在出现问题时,能够更容易地将代码恢复到之前的状态。如果你的提交影响了太多的区域,那么回退可能意味着丢失大量的代码。
对于代码审查者来说,如果提交只与一个特定的目的相关,他们会更容易理解代码的作用。
让我们来看一个实际的例子,看看这是如何运作的。首先,我们需要添加相关的文件更改。我们可以通过运行 git status
来查看当前分支中哪些文件已被更改。
On branch: master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.DS_Store
login.test.ts
login.ts
product.ts
registeration.test.ts
registeration.ts
validation.test.ts
validation.ts
no changes added to commit (use "git add" and/or "git commit -a")
如你所见,有多个文件已在项目中被更改或添加。然而,这些文件分别属于项目的不同部分。遵循保持提交小而相关的黄金法则,让我们看看如何将其付诸实践。
我们可以使用 git add
命令加上文件名,仅提交那些相关的文件。具体操作是使用 git add
命令,然后逐一添加我们希望提交的文件名,例如:
git add login.test.ts login.ts
如果我们现在检查 git status
,就会看到这两个已暂存的文件:
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: login.test.ts
new file: login.ts
我们已经暂存了这些文件,现在要创建提交。一如既往,我们将使用 git commit
,这会在 VS Code 中打开 git 编辑器(因为我们之前已经这样设置过)。如果你跳过了这一步,提交信息会在你首选的编辑器中打开。
接下来,我们添加一个描述更改的提交消息:
Fix issue with login button not showing
这样就完成了一个小而相关的文件提交。提交消息明确地告诉我们进行了什么更改、问题出在哪里,并提供了一些关于问题的小背景信息。
反面教材
不良提交示例
既然我们已经成功完成了一个良好的提交,让我们来看看一个不良提交的例子:
假设我们已经完成了所有工作,开发者使用 git add -A
命令一次性暂存了所有更改或添加的文件。
多个不相关文件被暂存以提交的示例
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .DS_Store
new file: product.ts
new file: registeration.test.ts
new file: registeration.ts
new file: validation.test.ts
new file: validation.ts
然后,他们使用一行命令创建了提交消息:
git commit -m 'Updated various areas such as validation, registration and products pages'
为什么这是一个糟糕的提交?
首先,这个提交包含了太多更改。过多的文件意味着如果我们需要回退验证部分的更改时,将无法只回退那一部分。我们不得不回退整个提交,从而丢失产品和注册部分的更改。
其次,提交消息过于冗长。我们可以去掉诸如“various areas such as”这样的无意义的词语。这些词语对提交消息没有任何贡献,还占用了本可以用于更多背景信息的字符数。
此外,我们没有使用前面提到的祈使语态。我们应该将“Updated”改为“Update”。
如何创建高效的 Pull Requests
决定何时推送
推送是将你的提交发送到服务器/远程仓库,以准备创建 Pull Request (PR)的过程。我建议在当前功能或修复完成后立即进行推送。
此外,保持你的 PR 小而精简,仅包含相关的提交是个好主意。例如,如果你有以下提交:
- 添加新产品搜索组件
- 为产品搜索组件添加单元测试
- 添加产品搜索组件的文档
由于所有这些提交都与同一组件相关,建议将它们合并到一个 PR 中。
而像这样的提交:
- 修复登录屏幕中的错误
- 为提高性能重构注册页面
- 更新登录表单的验证测试
- 更新登录测试以支持忘记密码功能
- 更新产品搜索组件的单元测试
不应放在同一个 PR 中,因为这些提交涉及太多不同的内容。这些提交应该根据相关性分组为多个 PR。
如果这是一个分支的 Git 日志,你将无法仅使用相关文件创建 Pull Request ,因为提交的顺序已经固定,你不能简单地告诉 Git 你希望将第 1、3 和 4 个提交放入这个 PR 中。
保持小规模
记住——就像你的提交一样,保持 PR 小而精简。没有人愿意处理一个包含 50 多个文件的 Pull Request 。这样做只会让你的审查陷入常见的“看起来没问题”的陷阱。
当你创建一个大型 PR 时,实际上是在传达“我不想仔细检查所有这些文件,但粗略看了一下,好像还行”的信息。相比之下,一个小型 PR 则更容易得到确切的审查意见。
有时,大型 Pull Request 是不可避免的,比如在更新基础功能时。然而,你应该尽量考虑如何减少对其他开发人员的影响。
如何为代码审查做好分支准备
创建 Pull Request 的具体流程会因所使用的版本控制托管平台而有所不同,但基本概念是相同的。
首先,你应该从代码库中检出主分支(通常是 main
或 master
)。然后运行 git pull
,这会将主分支的最新代码拉取到你的本地开发系统中。
完成后,你可以使用 git checkout
命令切换回你自己的分支,例如:
git checkout login-fixes
现在,我们需要将主分支的代码合并到你的分支中。可以使用 git merge
命令来实现这一点:
git merge main
如果存在更改,即从主分支拉取的文件中有更新,你需要创建一个“合并提交”。这是在你的分支上包含合并更改的另一个提交。
只需创建另一个提交,并附上解释你已经从主分支合并的消息,例如:
git commit -m 'Merge main into login-fixes'
最后,使用 git push
将你的更改推送回远程服务器。
PR 代码审查
审查 PR 时需要注意什么
在审查 PR 时,首先要退一步,考虑良好代码审查的关键要素。以下是一些需要考虑的要点:
代码是否遵循团队的编码规范? 确保提交的代码符合团队的编码标准和惯例。这是维护代码库一致性的重要步骤。
代码是否达到了预期目标/验收标准? 审查代码是否实现了它所承诺的功能或修复了特定的问题,并符合相关的验收标准。
代码是否易读易懂? 代码是否易于理解,而无需大量注释或文档?这点非常重要,尤其是当函数和变量名称具有描述性时,可以大大提高代码的可读性。
代码是否需要重构? 从安全性、性能或可读性角度考虑,代码是否需要重构?通过重构,代码可以变得更简洁、更高效。
代码是否遵循简单的设计模式/原则? 例如单一职责原则、抽象、封装等。如果没有遵循,可以提出建议,或者向不熟悉这些概念的开发者解释其含义及其带来的好处。
是否存在“magic 数字/字符串”? 检查代码中是否有未命名的常量或字符串,考虑将其替换为命名常量或变量,以提高代码的可维护性。
及时审查 PR
虽然不必马上查看 PR,但也不要让作者久等。这个 PR 可能会阻碍后续工作,或者它可能很重要(如果是这样,作者应该明确说明)。
尽量保持讨论和 PR 评论的顺畅。如果方便的话,可以通过电话(如果是远程工作)或在办公室里一起审查 PR,这可能会加快流程,减少来回等待的时间。
尽管如此,也不要急于完成代码审查。要仔细、认真地阅读每个文件和更改。我建议你检出包含更改的分支,查看整个项目,而不仅仅是更改的几行代码。
很多时候,仅仅查看一两行代码的更改,你可能无法准确理解代码的意图。但如果查看整个文件,你可以更好地理解代码的整体逻辑。
如果你使用的是 VS Code 和 GitHub,可以利用它们的扩展功能,在 VS Code 内部查看 PR、发表评论,并同时检出 PR 分支。
记住我们都是人
记住,我们都是人,编写代码时人们经常会犯错误,也可能忽略一些细节。
并不是每个人的编码方式都和你一样,所以不要仅仅因为别人的做法和你的不同就要求修改。这并不意味着他们做错了,也不意味着你的方式就是最好的。
清晰描述修改意见,谨慎措辞
拉取请求(PR)不是考试,也不是你严厉批评别人工作的机会。这是一个学习的机会,也是确保最佳代码进入主分支的机会。重点在于代码质量以及代码是否符合验收标准。
在提出建议时,考虑一下你使用的语言。PR 评论与 git 提交消息恰恰相反。在 PR 评论中,我们不再使用祈使语态。不要命令对方做出更改,而是使用虚拟语气来提出更柔和的建议。
由于你是在批评别人可能付出了很多努力的工作,使用一些委婉的表达方式,比如:
- “如果是我,我会将这个 if 语句改为 switch case 语句,因为它更易读。”
- “或许可以考虑将这个变量重命名为一个更直观的名称,例如 {alternative},这样可以更容易理解它的作用。”
如上所述,尝试添加你提出修改建议的原因。这样会使建议更有影响力,并让作者思考是否应该做出更改,或者引发讨论以达成折中方案。
提供改进建议
大多数 Git 系统允许你点击需要更改的代码行并添加评论,这样更容易指定你希望修改的确切代码行。
像 GitHub 这样的托管平台有“建议”功能,允许你在评论中直接添加代码建议,这些建议可以在 PR 中立即接受并提交。
如果没有这个功能,确保你请求的内容清晰简明。你甚至可以在评论中重写或写出你的建议,例如:
“或许可以考虑将这个 if/else 语句改为三元表达式,如下所示:”
var backgroundColor = isError ? 'red' : 'blue'
这样可以使建议更加明确,并加快重新编写的过程(通过复制粘贴)。
不要害怕为你的代码辩护
记住,PR 是一种讨论。这是一个双向的过程,给你机会为你的代码辩护,并用更多的背景信息解释你的想法。
尽管代码可能看起来不完美,但可能有原因。可能存在你无法控制的因素,迫使你以某种方式编写代码。
不要害怕提出反驳意见,但要准备好合理的理由,尤其是在你确实相信你的解决方案是最佳的情况下。
传达 PR 已被批准
如今,许多人会将 GitHub 或其他版本控制系统的电子邮件通知过滤到一个文件夹里,由于仓库、提交、分支等的更新量太大,通常很少查看这些通知。
为了加快进程,并使作者的体验更愉快,可以简单地给他们发个消息。许多公司现在都有即时消息服务,为什么不利用这一点呢?