良好的Commit Message有利于代码审查,能更快速查找变动记录,而且能够直接生成Change log。html
Commit Message的写法规范:conventional-changelog 为了规范代码提交的说明,这里咱们使用angular的规范写法:前端
<type>(<scope>): <subject>
<空行>
<body>
<空行>
<footer>
复制代码
其中 head((): )是必须的,body和footer是可选的。 若是只须要输入header,能够直接使用:java
git commit -m
复制代码
命令提交。linux
若是须要输入body、footer这样的多行日志,须要输入:git
git commit
复制代码
跳出文本编辑器进行编写。github
commit的类别,包涵如下七种:shell
feat:新功能(feature)
fix:修补bug
docs:文档(documentation)
style: 格式(不影响代码运行的变更)
refactor:重构(即不是新增功能,也不是修改bug的代码变更)
test:增长测试
chore:构建过程或辅助工具的变更
复制代码
commit的影响范围,好比会影响到哪一个模块/性能/哪一层(业务层,持久层,缓存,rpc),若是是特性代码,能够写特性名称express
commit的简短描述,不超过50个字符。npm
跟subject同样,使用如今式,祈使句。应该说明提交代码的动机,以及跟前一个版本的对比。segmentfault
Foot包含能够包含如下信息:
以 BREAKING CHANGE 开头,后面是变动的具体描述,如
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.
To migrate the code follow the example below:
Before:
scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}
After:
scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor } The removed `inject` wasn't generaly useful for directives so there should be no code using it.
复制代码
如:
Closes DB-1001, DB1002
复制代码
feat($browser): onUrlChange event (popstate/hashchange/polling)
Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available
Breaks $browser.onHashChange, which was removed (use onUrlChange instead)
---------
fix($compile): couple of unit tests for IE9
Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.
Closes #392
Breaks foo.bar api, foo.baz should be used instead
---------
eat(directive): ng:disabled, ng:checked, ng:multiple, ng:readonly, ng:selected
New directives for proper binding these attributes in older browsers (IE).
Added coresponding description, live examples and e2e tests.
Closes #351
---------
feat($compile): simplify isolate scope bindings
Changed the isolate scope binding options to:
- @attr - attribute binding (including interpolation)
- =model - by-directional model binding
- &expr - expression execution binding
This change simplifies the terminology as well as
number of choices available to the developer. It
also supports local name aliasing from the parent.
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.
To migrate the code follow the example below:
Before:
scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}
After:
scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor } The removed `inject` wasn't generaly useful for directives so there should be no code using it.
复制代码
若是是特性开发,则能够这样:
feat(短视频播放优化): 全屏播放动画效果优化
复制代码
在NodeJS项目中,咱们能够经过使用 ghooks + validate-commit-msg进行提交日志校验,校验不经过的将被拒绝提交。原理是经过NodeJs项目编译,把NodeJS的校验脚本写到.git/hooks/
目录下的勾子文件中,这样每次执行git commit
命令都会执行这个校验,不过这种方式依赖于Node环境,而且每一个Git项目都须要引入对应的npm模块进行编译,对于比较多微服务项目的状况来讲使用不太方便。
为此,编写了git-hook-maven-plugin插件, 该插件有以下特色:
Maven
的生命周期中的某个阶段, 方便的经过项目编译自动安装或者升级脚本;validate-commit-message
钩子脚本, 用于提交日志的规范, 遵循AngularJS Git Commit Message Conventions的格式。配置完这个,当咱们经过maven编译完项目以后,下一次提交代码,若是提交日志不符合规范,则会报错:
➜ project-1 git:(master) ✗ git commit -m "test"
Commit log error: First commit message line (commit header) does not follow format: type(scope): subject
- Refer commit guide: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
复制代码
对于独自完成的特性,可能在开发过程当中会产生多个提交,为了让提交整洁,须要对这个特性的全部提交进行压缩合并。咱们先看看压缩合并以前的代码:
* be6e32d (HEAD->master)feat(测试提交): 修改第二个文件
* 4a7615e feat(测试提交): 修改第一个文件
* 721064e feat(测试提交): 提交第四个文件
* e20968e feat(测试提交): 提交第三个文件
* b7160b3 feat(测试提交): 提交第二个文件
* 0c90fcl feat(测试提交): 提交第一个文件
* e618321 fix(页面展现): 展现错误修复
复制代码
如图,能够发现压缩合并测试
特性有多个提交,能够进行合并,如今准备把e618321
前面的提交都进行合并,执行git rebase -i
命令进行压缩合并:
git rebase -i e618321
其中命令后面的hash值是压缩合并开始的那个提交的hash值:
pick 0c90fcl feat (测试提交): 提交第一个文件
pick b7160b3 feat(测试提交): 提交第二个文件
pick e20968e feat(测试提交): 提交第三个文件
pick 721064e feat(测试提交): 提交第四个文件
pick 4a7615e feat(测试提交): 修改第一个文件
pick be6e32d feat(测试提交): 修改第二个文件
# Rebase e618321..be6e32d onto e618321 (6 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
复制代码
注意:这个界面里面的提交是按照提交时间顺序往下排的,最新提交的在最后面,跟git lg
的相反,平时查看日志是最新提交的排在最前面。
咱们把低2行到6行改成 s(squash),第一个行改成 r(reword),把第2到6行合并到第一个提交里面,调整下提交信息:
r 0c90fcl feat (测试提交): 提交第一个文件
s b7160b3 feat(测试提交): 提交第二个文件
s e20968e feat(测试提交): 提交第三个文件
s 721064e feat(测试提交): 提交第四个文件
s 4a7615e feat(测试提交): 修改第一个文件
s be6e32d feat(测试提交): 修改第二个文件
复制代码
而后输 :wq 保存并退出编辑模式继续处理。
若是遇到有冲突,须要解决完冲突以后,修改冲突的提交日志。
最后是一个压缩合并以后的提交日志确认界面,看看第一行的日志是否符合咱们的需求,没有问题则输入 :wq 保存并退出编辑模式。
# This is acombination of 7commits.
# The first commit'smessage is:
feat(测试提交): 测试代码
# This is the 2nd commit message:
feat(测试提交): 提交第二个文件
# This is the 3rd commit message:
feat(测试提交): 提交第三个文件
复制代码
这样咱们就合并完成了,再次查看提交日志,发现已经合并程了一个提交:
* eb0121a (HEAD->master) feat(测试提交): 测试代码
* e618321 fix(页面展现): 展现错误修复
复制代码
注:git lg中 lg = log --graph --oneline --decorate,特别注意,本次演示代码直接在master上面进行,实际上须要在 feature-xxx 分支上面进行。
提交代码和压缩合并的原则:
开发过程当中的提交代码原则: 尽可能减小commit的次数; 在push以前,须要把本次特性全部的代码都压缩成一个提交; 在提交代码审查以前,最好把本次特产压缩成一个提交
假设咱们开发一个新的特性,而且已经把代码进行了压缩合并,提交日志以下:
* 69b4ffb (HEAD -> feature-test) feat(测试特性): 测试特性代码
* eb0121a (HEAD->master) feat(测试提交): 测试代码
* e618321 fix(页面展现): 展现错误修复
复制代码
而此时,master代码也有了新的修复代码提交:
* 69b4ffb (HEAD -> master) fix(缓存): 修复产品接口缓存bug
* eb0121a (HEAD->master) feat(测试提交): 测试代码
* e618321 fix(页面展现): 展现错误修复
复制代码
为了保持合并以后,咱们当前特性点仍然在提交日志的最新位置,达成效果以下:
咱们使用rebase
进行合并代码:
git rebase master
合并以后效果以下,咱们当前特性分支的提交仍然在最前面:
* 69b4ffb (HEAD -> feature-test) feat(测试特性): 测试特性代码
* 69b4ffb (HEAD -> master) fix(缓存): 修复产品接口缓存bug
* eb0121a (HEAD->master) feat(测试提交): 测试代码
* e618321 fix(页面展现): 展现错误修复
复制代码
rebase代码原则:
特性分支合并master代码使用 rebase,总让当前特性处于最近提交; 若是一个特性有多个同事开发,rebase以前记得让其余同事提交全部代码,rebase以后记得让其余同事强制更新本地代码;
Git 提交的正确姿式:Commit message 编写指南 你可能会忽略的 Git 提交规范 Git钩子:自定义你的工做流 用 Node.js 写前端本身的 Git-hooks gist.github.com/jasonrobert…
首次发布于:一个维护版本日志整洁的Git提交规范