最近在学习 Git 提交规范、发布及生成 CHANGELOG,最后实现本身的 CHANGELOG 模版并发布到 NPM,插件地址请戳这里html
以前对 Git Commit 不是很规范,想到什么提交什么,团队中每一个人的提交方式都不一样,没有很特别的指定哪些 commit 是新功能,哪些是修复 bug,查看 commit 记录比较吃力前端
对版本的概念也不熟,使用 git tag 打版本以前,都须要先查一遍远程上的版本是多少,新增完本地 tag 以后再将 tag push 到远程仓库,这也只是完成了打版本的步骤,若是须要提供 CHANGELOG.md 文件来讲明每次版本的更新内容就比较麻烦vue
这时候就须要插件来帮咱们规范 git commit 提交、自动化发布版本,自动生成 CHANGELOGnode
本文篇幅较长,图片较多,提早预警!git
使用 husky 来管理 git commit
以前的操做,为何要这么作,由于咱们能够在 git commit
以前再校验一次代码,防止提交「脏」代码,保证代码库中的代码是「干净」的,husky
不只仅能管理 commit
,git
的钩子几乎都能管理,不过用的最多的仍是 commit
和 push
github
npm install husky --save-dev
复制代码
"husky": {
"hooks": {
"pre-commit": "npm run lint"
}
}
复制代码
这里在 commit
以前,咱们先执行了 npm run lint
,这是 vue-cli3
给咱们提供的命令,会根据咱们的 eslint
规则来校验代码,而且自动修复,记得先 git add
文件vue-cli
但这样会有一个问题,就是此次提交,我可能只修改了一个文件,好比我就修改了 a.js
的内容,但它依然会校验 src 下面全部的 .js 文件,很是的不友好。npm
致使的问题就是:每次提交代码,不管改动多少,都会检查整个项目下的文件,当项目大了以后,检查速度也会变得愈来愈慢json
解决上面的痛点就须要使用 lint-staged。它只会校验你提交或者说你修改的部分内容。gulp
npm install lint-staged -D -S
修改 package.json 配置:
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/*_/_.{js,vue}": ["npm run lint", "git add"]
}
}
复制代码
如上配置,每次它只会在你本地 commit
以前,校验你提交的内容是否符合你本地配置的 eslint 规则,若是符合规则,则会提交成功。若是不符合它会自动执行 npm run lint
尝试帮你自动修复,若是修复成功则会帮你把修复好的代码提交,若是失败,则会提示你错误,让你修好这个错误以后才能容许你提交代码。
但这并非强制的,有些团队成员或者说刚来的新人没有在编辑器中配置或者无视命令行中提示的错误,强行提交,这时候就须要配置 pre-commit 这种强制性校验的东西,保证全部提交到远程仓库的内容都是符合团队规范的。
参考花裤衩大佬的文档 vue-element-admin
在多人协做项目中,若是代码风格统1、代码提交信息的说明准确,在后期维护以及 Bug
处理时会更加方便。
Git 每次提交代码,都要写 Commit message
(提交说明)
可是每一个人的提交方式不一样,没有很特别的指定哪些 commit 是新功能,哪些是修复 bug,这时须要插件来帮咱们规范化
规范 Commit message 的做用
在项目中安装插件:
npm i commitizen cz-conventional-changelog --save-dev
复制代码
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
}
复制代码
"commit": "git-cz",
复制代码
依赖安装完就能够开始秀操做了
要先 git add .
将文件加入本地暂存区后,才能 commit
npm run commit
复制代码
注意,若是以前经过 git commit
这种方式提交代码,都要改成 git-cz
注意,若是以前经过 git commit
这种方式提交代码,都要改成 git-cz
注意,若是以前经过 git commit
这种方式提交代码,都要改成 git-cz
Commit message 格式说明
Commit message 通常包括三部分:Header、Body 和 Footer
Header type(scope):subject
type(必需)、scope(可选) 和 subject(必需)
这里有几种类型能够选择
type:用于说明 commit 的类别,规定为以下几种
feat:新功能
fix:修补 bug
docs:修改文档,好比 README, CHANGELOG, CONTRIBUTE 等等
style: 不改变代码逻辑 (仅仅修改了空格、格式缩进、逗号等等)
refactor:重构(既不修复错误也不添加功能)
perf: 优化相关,好比提高性能、体验
test:增长测试,包括单元测试、集成测试等
build: 构建系统或外部依赖项的更改
ci:自动化流程配置或脚本修改
chore: 非 src 和 test 的修改
revert: 恢复先前的提交
复制代码
scope:(可选)用于说明 commit 影响的范围
subject:commit 的简要说明,尽可能简短
Body
Body 部分是对本次 commit 的详细描述,能够分红多行
Footer
Footer 部分只用于两种状况。
若是当前代码与上一个版本不兼容,则 Footer 部分以 BREAKING CHANGE 开头,后面是对变更的描述、以及变更理由和迁移方法。
若是当前 commit 针对某个 issue,那么能够在 Footer 部分关闭这个 issue, 也能够一次关闭多个 issue
? Select the **type** of change that you're committing:
(type) 选择提交更改的类型
? What is the **scope** of this change (e.g. component or file name)? (press enter to skip)
(scope) 这次更改的范围是什么(组件或者文件名)
? Write a **short**, imperative tense description of the change:
(subject) 写一个简短的,命令式的变化描述
? Provide a **longer description** of the change: (press enter to skip)
(Body) 提供更改的长描述
? Are there any **breaking changes**?
(Footer) 有没有突破性的变化
? Does this change affect any open **issues**? (y/N)
(Footer) 这次更改是否有要关闭 issues
复制代码
若是当前 commit 针对某个 issues
? Does this change affect any open issues? (y/N)
选择 Y,输入 Closes #1 (表示关闭第 1 个 issues)
也能够一次关闭多个 issues : Closes #1 #2 #3
CHANGELOG 中 issues 默认的连接地址是根据 package.json 中的 repository 来生成的
若是 repository
没有,则会获取 git 中的远程仓库路径来做为前缀
以后就会进行代码格式化校验,若是代码不符合规范,一样会提交失败,必定要确保项目当前格式没问题,规范后再提交!!!
更多细节能够参考阮一峰老师的博客:Commit message 和 Change log 编写指南
这里我使用 release-it 做为发布版本插件,也能够选择 standard-version
npm install --save-dev release-it
复制代码
"release": "release-it"
复制代码
在项目终端输入 npm run release
就会执行操做
若是出现下图的报错信息,能够经过登陆 npm 解决
在发布版本前,必定要确认是否还有文件没有提交,不然是会报错的,报错信息以下:
ERROR Working dir must be clean.
Please stage and commit your changes.
Alternatively, use `--no-git.requireCleanWorkingDir` to include the changes in the release commit (or save `"git.requireCleanWorkingDir": false` in the configuration).
复制代码
工做目录必须是干净的,请暂存 (add) 并提交 (commit) 你的更改
不推荐经过修改 git 配置来解决,由于发布一个版本就应该是没有任何更改的,稳定的才去发布,git tag 若是没有指定对应的 commitID,默认在最新的 commit 上打标签,注意!!要在主分支(master)上发版本
release-it
会读取本地的 package.json 中的 version,提示你当前版本是多少,不须要开发者使用 git tag -l
来查询当前本地版本是多少,以及这个版本作了哪些改动,它提供了几个默认选项让你选择版本号
若是你以为上面的选项不能知足你的要求,最后一个选项是本身填入版本信息(要符合规范),有关版本规范能够参考语义化版本 2.0.0
确认版本后,会自动修改 package.json
的版本信息,这是前端开发者查看当前项目版本的途径之一。以后就是询问是否要 commit,是否打 tag,是否 push 到远程仓库,能够一路回车。最后一项若是是公司项目,不须要上传到 npm 仓库,选 NO 便可,即便选了 Yes,但只要你在 package.json 中配置 private 为 true,也不会上传。如何查看发布成功? 能够输入 git tag -l
查看本地 tag,也能够 git ls-remote --tags origin
查看远程 tag
可是这只是一个 tag,没有详细信息,更新日志仍是须要开发者手动编写
这个时候就须要用到自动生成 CHANGELOG 插件了
安装
npm i conventional-changelog-cli --save-dev
复制代码
配置 package.json
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
复制代码
上面 changelog 命令不会覆盖之前的 CHANGELOG
,只会在 CHANGELOG.md 的头部加上自从上次发布以来的变更。
npm run changelog
复制代码
生成 CHANGELOG.md 文件
在 CHANGELOG.md 的头部加上自从上次发布版本以来的变更。显示 feat、bug、doc 等类型
生成的 CHANGELOG 不会按 commit 上传的时间顺序排序,有人给官方提交了 issues,等待官方解决。。👉传送门
能够打开 GitHub/GitLub 仓库,将更新日志生成的内容对应的填入 tag 版本中就能够了
这里先展现最终生成的 CHANGELOG 效果图
起源背景以下:
测试:”须要在 CHANGELOG 中生成 commit 对应的提交人,这样问题定位就知道去找谁负责”
我:“😎 这个简单~配置下参数就能够了”
我觉得只要配置一下参数,毕竟 CHANGELOG 插件是支持自定义参数的,当我看到文档懵逼了,没有提供这两个参数,显示提交人和提交人邮箱,咋办,翻 issue。。。这个需求应该有人提 😏,根据 #351 知道了使用自定义配置须要从外部传入自定义配置文件
新建一个配置文件,在命令后面带上 -n <文件路径>
{
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 -n ./changelog-option/index.js"
}
}
复制代码
解决了使用自定义配置问题,如何增长 CHANGELOG 生成更多的提交信息,仍是翻 issue... #349
结合起来大概是这样,试试效果:
format 里面有 authorName 和 authorEmail 字段,运行 npm run changelog
后依旧没有效果 😖 只能翻源码了
配置 launch.json,调试 conventional-changelog-cli 插件下的 cli.js 文件,这里保持和 package 中的 changelog 一致,传入参数 "-p", "angular", "-i", "CHANGELOG.md", "-s", "-r", "0", "-n", "./changelog-option/index.js"
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"cwd": "${workspaceFolder}",
"program": "${workspaceFolder}\\node_modules\\conventional-changelog-cli\\cli.js",
"args": [
"-p",
"angular",
"-i",
"CHANGELOG.md",
"-s",
"-r",
"0",
"-n",
"./changelog-option/index.js"
]
}
]
}
复制代码
全局搜索传入的配置项字段:gitRawCommitsOpts,打个断点调试一下
发现做者是将用户传入的 gitRawCommitsOpts 作个合并,最后传入到 conventionalChangelog 方法中去执行,继续查看该方法
插件由 conventional-changelog-cli
跳转到 conventional-changelog
下
判断用户是否有传入 preset 预设参数,调试的时候使用了 angular 的配置 (-p angular)
这里 return 了一个 conventionalChangelogCore
方法,依旧点击跳转
做为插件的核心库,最核心的地方就是 mergeConfig 这个方法
在 core 中将配置传入 mergeConfig 中进行合并
format 默认只有 hash、gitTags 和 committerDate,没有须要的 authorName 和 authorEmail,fromTag 是咱们最后一次提交的 tag,merges: false 表示在 CHANGELOG 中不会生成 merges 分支的信息
mergeConfig 是一个 Promise,求值后将配置传给了 gitRawCommits,涉及了 pipe 导流来传递数据
将 gitRawCommitsOpts
配置传入 gitRawCommits
方法中,继续点进去看,又会跳转到 git-raw-commits
插件
经过 git-raw-commits
的 GitHub 官网 README,发现这个插件是从本地 git 仓库中获取提交记录,以前传入的 format 就是 git-log 中的参数
hash:哈希值
gitTags:标签
committerDate:提交时间
authorName:提交人
authorEmail:邮箱
复制代码
更多 git-log 细节能够去看 git 官方文档,也能够在 git log 后面带上咱们配置的 format 进行格式化
直接使用 git log 查看 git 提交记录中,也有 Author 的 name 和 email 字段
看到这里,肯定了 git-raw-commits 插件只是从 git 中读取数据并格式化,那么确定有个插件是将这些数据写成 CHANGELOG.md 文件,因而继续翻 conventional-changelog-core
,发现 conventional-changelog-writer
,这个插件先不看,还记得以前使用的是 angular
的预设吗,能够去看 conventional-changelog-angular
插件
好的项目从文件名就知道各个文件是作什么的,将不一样插件的配置单独拆分,这点值得学习
writer-opts.js
就是写入 CHANGELOG 的配置,最后会将配置传给 conventional-changelog-writer
,这里来匹配咱们以前 commit message 的信息
其实在 writer 以前,还有一个 parser 插件,用来解析咱们提交的信息,这个 changelog 里面究竟是依赖了多少插件。。。
在用 commit 规范化插件提交的时候,就须要填写相应的信息,这里打印一下 commit 信息
发现的确有 authorName 和 authorEmail 这两个字段存在,并且 conventional-changelog-writer
这个插件就是将这样的对象生成 CHANGELOG.md,经过插件的 README 能够知道
如今字段也有了,可是为何不会显示呢,继续看源码,这里用到了 templates/commit.hbs
文件
看到这里也就差很少了,template 文件夹下就是生成 CHANGELOG 的模版文件,查了下 hbs(Handlebars) 是一个模版引擎。不过在 commit.hbs 中却并没有发现有用到这两个字段,想一想也是,这两个字段是我配置 gitRawCommitsOpts
传入的
说明 angular
预设一开始就没想过要生成 authorName 和 email。。。这就尴尬了,只能本身加上了,照葫芦画瓢,修改 commit.hbs 文件,在生成 commit 的 hash 值后面加上
成功啦~~!!!🎉🎉🎉
让我激动一下,可是转念一想 🤔,这种直接修改 node_modules 里插件的源码,根本无法分享啊,若是同事要用,不可能也这样去修改 conventional-changelog-angular
的源码吧,并且只要从新 npm install 安装依赖后,以前修改了也会消失
做者已经在 conventional-changelog-cli
中提供了自定义的例子
不过这个地址已经被废弃了,新地址就是咱们以前使用的 angular 预设 conventional-changelog-angular ,官方也有提供其余预设模版,如:atom
、eslint
、jQuery
这种在一个 package 中管理多个项目是用了 lerna,一个用于管理拥有多个包的 JavaScript 项目的工具。是一种比较流行的 monorepo
项目管理模式,React、Vue、Babel 都有用这种模式来管理。
前面也分析了 conventional-changelog-angular ,直接 clone 源码来改,建立 git-raw-commit.js
module.exports = {
format:
'%B%n-hash-%n%H%n-gitTags-%n%d%n-committerDate-%n%ci%n-authorName-%n%an%n-authorEmail-%n%ae'
}
复制代码
在 index.js 中传入并使用
'use strict'
const Q = require(`q`)
const conventionalChangelog = require(`./conventional-changelog`)
const parserOpts = require(`./parser-opts`)
const recommendedBumpOpts = require(`./conventional-recommended-bump`)
const writerOpts = require(`./writer-opts`)
// 格式化 git log 信息
const gitRawCommitsOpts = require('./git-raw-commit')
module.exports = Q.all([
conventionalChangelog,
parserOpts,
recommendedBumpOpts,
writerOpts,
gitRawCommitsOpts
]).spread(
(
conventionalChangelog,
parserOpts,
recommendedBumpOpts,
writerOpts,
gitRawCommitsOpts
) => {
return {
conventionalChangelog,
parserOpts,
recommendedBumpOpts,
writerOpts,
gitRawCommitsOpts // 传入
}
}
)
复制代码
以后修改 commit.hbs,显示 authorName 和 authorEmail
这里有个小坑!!我用 VSCode 修改完直接保存后,若是有屡次提交,不会折行,会挤在同一行,估计是保存的格式不对,也许是我 VSCode 安装了比较多的格式化扩展,建议用 Notepad++ 去修改 commit.hbs 文件
公司使用 redmine 来管理项目,测试人员会在 redmine 中提 issues,这里生成完 CHANGELOG 要批量替换 issues 的地址,将 GitLab 地址前缀替换成 redmine,网上说用 replace 库,可我发现这个库上传 npm 是三年前,而且已经不维护了,使用后也报错。。。因而写了一个简单的字符串替换文件,生成完 CHANGELOG 后运行该文件便可替换,支持传递参数(参考 conventional-changelog
源码,使用了 minimist 插件来获取传递的参数)
{
"scripts": {
"changeissueurl": "node ./changelog-option/replace.js https://gitlba.com/issues/ https://redmine.example.com/issues"
}
}
复制代码
再把这两个脚本集成到一个 version 中,以后要发版本,生成 CHANGELOG 只要运行 npm run version 便可
这样仍是太麻烦,对于使用者来讲不须要了解太多,并且文件存在本地,不方便迁移,🤔 能不能像 angular 同样直接作成预设模版,让 conventional-changelog
直接去用咱们自定义的预设模版就好了,为了验证,仍是得翻源码,以前有调试到,可是没细看
在 conventional-changelog-preset-loader
中
预设只要按照 ${scope}conventional-changelog-${name}
这种命名规范就能够被 require,scope 是由于 npm 仓库不能同名,能够加上本身的用户名做为做用域,例如:@zsh/conventional-changelog-angular
,以后在配置中改成 -p @zsh/angular
就可使用自定义的预设了
感谢 conventional-changelog
!很少说,起一个 npm 项目,将以前的文件都放进去,再次对模版进行优化。
TODO:
由于这里获取的 commit 是字符串格式,能够在 commit.hbs 模版中设置一个值,以后再根据用户的配置来进行替换,这样 authorName 和 authorEmail 就不是必需的,默认禁用,须要手动设置开启
issues 和 emojis 比较简单就不说了,相信你们若是认真的看到这里,彻底能够作你本身的预设~
因为是第一次发布到 npm 上,没什么经验,效果很差还望见谅 🏃♂️,npm 地址:conventional-changelog-custom-config
使用
npm install conventional-changelog-custom-config --save-dev
复制代码
经过在 package.json 中配置参数的形式来定制 CHANGELOG,不填配置则会按照 angular 的预设模版生成 CHANGELOG,具体配置以下:
{
"scripts": {
"changelog": "conventional-changelog -p custom-config -i CHANGELOG.md -s -r 0"
},
"changelog": {
"bugsUrl": "https://redmine.example.com/issues/",
"emojis": true,
"authorName": true,
"authorEmail": true
}
}
复制代码
bugsUrl
Type: string
Default: false
当你须要将 issues URL 替换成其余 URL 时,使用该参数,例如使用 redmine 管理项目, bugsUrl: 'https://redmine.example.com/issues/'
若是不填 bugsUrl
则会根据 package.json 中的 repository
或 repository.url
来做为 issues URL
{
"repository": {
"type": "git",
"url": "https://github.com/example"
}
}
复制代码
若是 repository.url
也没有,则会获取 git 中的远程仓库路径来做为前缀,conventional-changelog-core 源码地址
若是你使用了第三方的协做系统(例如 bitbucket), 推荐你使用这个插件 conventional-changelog-angular-bitbucket
emojis
Type: boolean
Default: false
,emojis types 参考 gitmoji
Commit Type | Title | Description | Emojis |
---|---|---|---|
feat |
Features | A new feature | ✨ |
fix |
Bug Fixes | A bug Fix | 🐛 |
docs |
Documentation | Documentation only changes | 📝 |
style |
Styles | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) | 💄 |
refactor |
Code Refactoring | A code change that neither fixes a bug nor adds a feature | ♻️ |
perf |
Performance Improvements | A code change that improves performance | ⚡️ |
test |
Tests | Adding missing tests or correcting existing tests | ✅ |
build |
Build | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) | 👷 |
ci |
Continuous Integrations | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) | 🔧 |
chore |
Chores | Other changes that don't modify src or test files | 🎫 |
revert |
Reverts | Reverts a previous commit | ⏪ |
authorName
Type: boolean
Default: false
在 CHANGELOG 中生成用户名
authorEmail
Type: boolean
Default: false
在 CHANGELOG 中生成邮箱
更多节能够看 README,码字不易,开源不易,以为不错点给个 ⭐️ 吧~😝 感谢感谢~
总结这一整套折腾过程,代码风格规范 ----> commit 规范 ----> version 规范 ----> 生成 CHANGELOG ---> 自定义 CHANGELOG ---> NPM 发布预设
前四个步骤看看 README 就直接上手,没什么难点,自定义 CHANGELOG 稍微麻烦些,对外开放 conventional-changelog-cli
收集用户配置,如 -p angular -s -r 0 -n config.js,若是有预设模版,好比 angular,就将 conventional-changelog-angular
中的配置传入 conventional-changelog-core
中 merge,以后经过 git-raw-commits
从本地 git 中获取 log 数据,conventional-changelog-parser
来解析用户提交的信息,将两种数据整合成一个对象,传入 conventional-changelog-writer
生成 CHANGELOG.md 文件
刚开始安装插件比较多,一旦配完就是一两个命令的事,感兴趣的也参照我这篇文章,本身写一套模版用, npm 上也有不少预设模版能够用,axetroy 大佬写了个 VSCode 扩展 列入了 conventional-changelog 官方推荐 ,文章位置,人也在掘金 😏
本文篇幅较长,不免会有错误和不足的地方,但愿大佬们留言指正,以避免误人
git commit 、CHANGELOG 和版本发布的标准自动化