如何写好Git Commit

什么是好的git commit,有以下几点:

  • message清楚反应本次提交内容
  • 方便回退到某个版本
  • 反应产品演进过程

主要针对团队开发,对于开源和非开源项目要求可能不一样。个人认为,开源项目的master提交尽量反应产品演进,所以,分支合并时,可以把分支的多个commit合并为一条。但团队非开源项目,我觉得没必要这么做,多点“小步提交“的message没什么关系。

当然,对个人的提交来说,可以按照自己的习惯,从msg格式和提交上把commit写好。

message格式

feat: 添加阅读数量

给文章添加阅读数量功能
- 添加xx1
- 添加xx2

Issue #1, #2
Close #1

说明: 第一行: :header

keyword: 简要说说明

keyword:

  • feat: 新增feature
  • fix:bugfix
  • docs:文档修改
  • style: 改变编码风格
  • refactor:重构
  • perf:改善
  • test:添加测试
  • revert: 回退到前一版本

第二行:body,详细说明 第三行:footer,指向或者关闭issues

所以,在提交是尽量避免如下命令

git commit -am "xxx"

下文还是这样使用,只是为了方便演示。

修改提交

本来开发都会尽快小步提交,如果提交的message写得不好,直接通过--amend选项修改:

git commit --amend

如果是新的修改提交,也可以用相同的命令,把这次提交合并到上次的commit中。

可以使用rebase作各种变基嫁接操作,下面看一个示例

$ ls
README.md file1.txt

$ git lg
* 6ffc8d0 - (HEAD -> master) add file1 (3 minutes ago) <thoreau>
* d12e8cf - refactor(package): 提炼方法 (21 minutes ago) <thoreau>

下面添加file2并简单(方便演示)提交:

$ touch file2.txt
$ ga 
$ gcm "add file2"
$ git lg
* bc004ef - (HEAD -> master) add file2 (8 seconds ago) <thoreau>
* 6ffc8d0 - add file1 (5 minutes ago) <thoreau>
* d12e8cf - refactor(package): 提炼方法 (23 minutes ago) <thoreau>

现在,我们想把第二个提交删除,把最后一个提交的msg修改为"new file2":

git rebase -i d12e8cf

修改如下: 紧接着编辑最后一个提交的msg。执行git log 做到了我们想要的结果,删一个改一个,再看文件,发现file1.txt不存在了。

使用rebase的好处是想怎么改就怎么改,但最后是针对自己阶段性提交的修改,否则造成commit history对不上,分支合并出现问题。除非是修改历史敏感信息,这个命令需要谨慎使用。

从技术上,还是有补救办法,如果不想删除第二个提交,想回退rebase,怎么办? git reflog

git reset --hard bc004ef #撤销

分支合并时的commit

在上述三个commit的master上建一个分支:b1,并修改file2,新建file_b1

* 9bd82c9 - (HEAD -> b1) add file_b1 (82 seconds ago) <thoreau>
* 5cab28f - edit file2 (2 minutes ago) <thoreau>
* bc004ef - (master) add file2 (21 minutes ago) <thoreau>
* 6ffc8d0 - add file1 (26 minutes ago) <thoreau>
* d12e8cf - refactor(package): 提炼方法 (44 minutes ago) <thoreau>

现在把分支合并到主干,但我希望把分支的commit都合并成一个,可以使用--squash

git checkout master
git merge --squash b1
git commit -m "feat: new file_b1 and Bugfix"

远程分支合并

如果你在本地新增提交的时候,远程分支已经有新提交,此时由于commit history不一样,是不允许提交的,需要先把分支合并过来,形成一个新的提交,如下图。 可以看到,分支br上的提交6e989ff合并到master时,生成一个新提交ea74b46。我们可以使用嫁接的方式(也叫分支衍合),把6e989ff直接嫁接到master提交1becaca后,还是使用rebase,不会产生新的提交,如下,是git官方说明。


参考列表:

CONTENTS