什么是好的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官方说明。
参考列表: