Git版本管理工具使用知识汇总
版本管理在软件开发中是非常重要的,版本管理可以有效的降低代码版本丢失风险,极大的方便了软件开发中不同版本代码的管理。
本文内容包括:
- 如何使用git工具
- 规范化commit信息的格式
- 使用commitlint验证commit信息的格式是否符合规范
- 使用husky强制执行commit格式的规范化验证
- 如何在代码提交前对代码格式验证
- 最后封装成一键脚本自动化配置 commitizen
版本管理工具有很多:
- svn :中心化在线版本管理控制工具,老旧的版本管理工具。
- git :分布式版本控制工具,支持离线版本管理,目前主流的版本管理工具。
安装Git
这里有不同平台的所有安装包,安装后你可以通过git命令或者GUI窗口进行版本管理。
了解Git命令
初学者对git版本管理有点迷糊,没关系,这里有个Git CheatSheet 帮你快速理解Git的工作原理及命令的作用。
访问 Git Cheat Sheet 学习一下Git命令用法。
规范化commit信息格式
由于commit 提交信息的作用是描述本次提交的改动信息及原因,可往往开发者处于懒惰而省略了很多描述信息,这将导致我们对git项目提交信息的管理变得困难,因此就产生了 commitizen 工具,帮我们规范化 代码提交信息。
提交信息可以告诉阅读这当前提交做了些什么变更,是代码修改了或者文档变更等等。这样,阅读这可以选择性的审阅代码内容。可以让提交信息更加有价值和实际的意义。
常规的commit的message格式规范化(主流Angular规范)如下:
<header>
<空行>
<body>
<空行>
<footer>
-
目前很少用到,本用于更详细的说明每一个改动点,但对于每次只提交一小部分改动的变更,只需要填写subject概述信息就足够了。
-
-
<header>
包含提交信息的概述,必填字段,此部分信息的常用Angular规范格式如下:
<type>(<scope>?): <subject>
│ │ │
│ │ └─⫸变更内容概述信息,英文不区分大小写,行末不能有句点(.)结束.
│ │
│ └─⫸ 提交范围,可选字段.
│
└─⫸ 提交类型(变更分类): build|ci|docs|feat|fix|perf|refactor|test
Type 字段取值含义:
- feat : 新增加功能特性
- fix : 修复bug
- refactor: 一些代码结构上的优化,没有新特性和bug修复.
- perf : 性能优化的代码改动
- release: release版本提交
- chore: 一些与主要业务无关的构建/工程依赖/工具等功能改动
- ci : CI持续集成提交变更
- docs: 文档更新
- style: 码的样式美化,不涉及到功能修改等
- test: 测试代码相关新增或变更
Scope字段为影响范围,很少用到,想了解可以去阅读Angular Commit Message Guidelines 详细相关说明。
Subject内容通常为提交内容的概述文本,用于说明本次提交做了哪些改动,以及改动原因或目标等。
到这里,我们基本了解了commit常用的规范化格式信息,当然Angular规范化格式只是比较流行的其中一种,还有些其他类似的格式,这里不再介绍。
开始安装commitizen规范化工具
每次都按照上面格式人工拼写难免会有出错的可能,所以下面就来介绍如何通过工具来辅助我们实现 规范化的commit文本提交。
- comitizen工具源码Github地址 : 这是项目源码地址,想了解源码的可以看看。
- comitizen使用文档网站 : 这里介绍了如何使用此工具实现规范化提交,当然是英文文档。
安装 commitizen工具
npm安装方式有两种,本地安装和全局安装,个人比较推荐全局安装,养成一个好的版本提交规范化习惯很重要。
前提依赖:
全局安装方法:
npm install -g commitizen
或者
npm install --location=global commitizen
npm install -g cz-conventional-changelog
echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
本地安装方法:
npm install --save-dev commitizen
安装完毕后,使用conventional-changelog
初始化项目,命令如下:
commitizen init cz-conventional-changelog --save-dev --save-exact
如果遇到错误,提示已经初始化过,可以使用--force
参数强制重新初始化一次。
执行成功后,我们看到当前项目多了如下几个文件和目录:
node_modules package.json package-lock.json
其中 package.json
文件内容多了如下部分:
{
"devDependencies": {
"cz-conventional-changelog": "^3.3.0"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}
到这里,我们就可以使用 git cz
命令提交规范化文本信息了:
对于英文不好的朋友,还可以使用
git-cz
替代commitizen
, 应为git-cz
支持配置定制,我们可以配置后实现中文提示,效果如下:这样是不是很人性化呢? 具体使用可以直接访问Github项目地址 ,安装后,在项目根目录下添加如下文件即可达到效果:
// 文件名: changelog.config.js // 作用: commit 规范化配置 // 参考文档:https://github.com/streamich/git-cz module.exports = { disableEmoji: true, // format: '{type}{scope}: {emoji}{subject}', list: ['test', 'feat', 'fix', 'chore', 'docs', 'refactor', 'style', 'ci', 'perf', 'build'], maxMessageLength: 72, minMessageLength: 3, questions: ['type', 'scope', 'subject', 'body', 'breaking', 'issues', 'lerna'], scopes: [], types: { chore: { description: '一些与主要业务无关的构建/工程依赖/工具等功能改动', emoji: '🤖', value: 'chore' }, ci: { description: 'CI持续集成相关变更', emoji: '🎡', value: 'ci' }, docs: { description: '文档更新(如:README)', emoji: '✏️', value: 'docs' }, feat: { description: '新的特性', emoji: '🎸', value: 'feat' }, fix: { description: 'BUG修复', emoji: '🐛', value: 'fix' }, perf: { description: '优化了性能的代码改动', emoji: '⚡️', value: 'perf' }, refactor: { description: '一些代码结构上优化,既不是新特性也不是修 Bug', emoji: '💡', value: 'refactor' }, release: { description: '发布Release版本提交', emoji: '🏹', value: 'release' }, style: { description: '代码的样式美化,不涉及到功能修改等', emoji: '💄', value: 'style' }, test: { description: '新增或修改已有的测试代码', emoji: '💍', value: 'test' }, build: { description: '影响构建系统或外部依赖项的更改(示例范围:gulp、broccoli、npm)', emoji: '💍', value: 'build' } } };
安装commitlint验证commit信息是否规范化
规范化的commit格式只是防君子不防小人的约定,总会有人不遵守约定而胡乱提交信息,所以就出现了 commitlint工具来验证提交信息的格式是否合格。
首先说明的是,commitlint 是用于检验 git工具的commit 提交信息是否符合 规范的commit格式的工具。
全局安装命令如下:
npm install -g @commitlint/cli @commitlint/config-conventional
仅在当前项目安装方法如下:
npm install --save-dev @commitlint/config-conventional @commitlint/cli
安装后,我们需要新增加一个配置文件commitlint.config.js
设置 commit规范格式,在项目的根目录下新建一个 commitlint.config.js 文件,内容如下:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// level[0..2]: 0表示禁用规则,1为警告,2为错误
// Appliable : always 适用此规则, never反转规则
// Value 用于此规则的值
'body-leading-blank': [2, 'always'], // body 开始于空白行
'header-max-length': [2, 'always', 72], // header 字符最大长度为 72
'subject-full-stop': [0, 'never'], // subject 结尾不加 '.'
'type-empty': [2, 'never'], // type字段不可以为空
'type-enum': [2, 'always', [
'feat', // 新特性、需求
'fix', // bug 修复
'docs', // 文档内容改动
'style', // 不影响代码含义的改动,例如去掉空格、改变缩进、增删分号
'refactor', // 代码重构
'test', // 添加或修改测试
'chore', // 不修改 src 或者 test 的其余修改,例如构建过程或辅助工具的变动
'revert', // 执行 git revert 打印的 message
'build', // 影响构建系统或外部依赖项的更改(示例范围:gulp、broccoli、npm)
]],
}
};
想了解更多commitlint配置规则请阅读 commitlint-规则参考, 这里有更全面的介绍 配置规则。
重点说明: 此时还无法自动化使用 commitlint 进行验证,还需要husky
添加一个 commit-msg
的钩子,让git提交信息时自动触发 commitlint
验证功能。接下来,我们就来了解一下如何配置 husky
。
使用husky
强制使用规范提交
husky工具 可用于git的commit或push时对commit信息格式化验证、自动测试以及代码格式化等等任何工作,
husky
支持git所有钩子。
- 安装husky命令:
npm install --save-dev husky
- 激活钩子:
npx husky install
- 添加commitlint钩子:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
验证commit信息是否符合规范化要求
首先,检验上次提交信息是否合格的命令:
$ npx commitlint --from HEAD~1 --to HEAD --verbose
⧗ input: docs: 文档变更
✔ found 0 problems, 0 warnings
接下来,我们来验证一下husky添加的钩子是否生效:
$ git commit -m "foo: this is a test"
⧗ input: foo: this is a test
✖ type must be one of [feat, fix, docs, style, refactor, test, chore, revert, build] [type-enum]
✖ found 1 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky - commit-msg hook exited with code 1 (error)
可以看到,钩子生效了,随便提交的文本信息就这样被拒绝了。
$ git cz
? Select the type of change that you're committing: chore: 一些与主要业务无关的构建/工程依赖/工具等功能改动
? Write a short, imperative mood description of the change:
[---------------------------------------------------------------------] 62 chars left
chore: 更新了changelog.config.js与commitlint.config.js文件
? Provide a longer description of the change:
? List any breaking changes
BREAKING CHANGE:
? Issues this commit closes, e.g #123:
[daily 12024a1] chore: 更新了changelog.config.js与commitlint.config.js文件
2 files changed, 36 insertions(+), 27 deletions(-)
rewrite commitlint.config.js (97%)
$
验证完毕,到这儿我们就完成了版本管理中commit信息规范化的配置工作。
最后
总结一下上面所用到的命令,为了方便以后新建项目可以自动执行命令完成配置工作,将上面命令封装为一个自动化配置脚本,脚本内容如下:
#!/usr/bin/env bash
#########################################################
# 功能: 自动化配置 git 规范化commit 脚本
# 作者: Awkee
# 日期: 2022-08-12
# 邮箱: xiaoyu0720@gmail.com
#########################################################
pre_check() {
#安装前检测是否已经安装了npm
npm -v > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "npm is not installed, please install npm first"
echo "install nodejs: https://nodejs.org/en/download/"
exit 1
fi
ver=$(npm -v | cut -d. -f1)
if [ $ver -lt 7 ]; then
echo "npm version is less than 7, please upgrade npm first"
echo "upgrade npm: npm install -g npm"
exit 1
fi
git --version > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "git is not installed, please install git first"
echo "install git: https://git-scm.com/downloads"
exit 1
fi
user_name=$(git config --global user.name)
if [ -z "$user_name" ]; then
echo "git user.name is not set, please set it first"
exit 1
fi
user_email=$(git config --global user.email)
if [ -z "$user_email" ]; then
echo "git user.email is not set, please set it first"
exit 1
fi
}
gen_changelog_config_file() {
echo -n "Ly8g5paH5Lu25ZCNOiBjaGFuZ2Vsb2cuY29uZmlnLmpzIAovLyDkvZznlKg6IGNvbW1pdCDop4TojIPljJbphY3nva4KLy8g5Y+C6ICD5paH5qGj77yaaHR0cHM6Ly9naXRodWIuY29tL3N0cmVhbWljaC9naXQtY3oKCm1vZHVsZS5leHBvcnRzID0gewogIGRpc2FibGVFbW9qaTogdHJ1ZSwKICAvLyBmb3JtYXQ6ICd7dHlwZX17c2NvcGV9OiB7ZW1vaml9e3N1YmplY3R9JywKICBsaXN0OiBbJ3Rlc3QnLCAnZmVhdCcsICdmaXgnLCAnY2hvcmUnLCAnZG9jcycsICdyZWZhY3RvcicsICdzdHlsZScsICdjaScsICdwZXJmJywgJ2J1aWxkJ10sCiAgbWF4TWVzc2FnZUxlbmd0aDogNzIsCiAgbWluTWVzc2FnZUxlbmd0aDogMywKICBxdWVzdGlvbnM6IFsndHlwZScsICdzY29wZScsICdzdWJqZWN0JywgJ2JvZHknLCAnYnJlYWtpbmcnLCAnaXNzdWVzJywgJ2xlcm5hJ10sCiAgc2NvcGVzOiBbXSwKICB0eXBlczogewogICAgY2hvcmU6IHsKICAgICAgZGVzY3JpcHRpb246ICfkuIDkupvkuI7kuLvopoHkuJrliqHml6DlhbPnmoTmnoTlu7ov5bel56iL5L6d6LWWL+W3peWFt+etieWKn+iDveaUueWKqCcsCiAgICAgIGVtb2ppOiAn8J+klicsCiAgICAgIHZhbHVlOiAnY2hvcmUnCiAgICB9LAogICAgY2k6IHsKICAgICAgZGVzY3JpcHRpb246ICdDSeaMgee7rembhuaIkOebuOWFs+WPmOabtCcsCiAgICAgIGVtb2ppOiAn8J+OoScsCiAgICAgIHZhbHVlOiAnY2knCiAgICB9LAogICAgZG9jczogewogICAgICBkZXNjcmlwdGlvbjogJ+aWh+aho+abtOaWsCjlpoLvvJpSRUFETUUpJywKICAgICAgZW1vamk6ICfinI/vuI8nLAogICAgICB2YWx1ZTogJ2RvY3MnCiAgICB9LAogICAgZmVhdDogewogICAgICBkZXNjcmlwdGlvbjogJ+aWsOeahOeJueaApycsCiAgICAgIGVtb2ppOiAn8J+OuCcsCiAgICAgIHZhbHVlOiAnZmVhdCcKICAgIH0sCiAgICBmaXg6IHsKICAgICAgZGVzY3JpcHRpb246ICdCVUfkv67lpI0nLAogICAgICBlbW9qaTogJ/CfkJsnLAogICAgICB2YWx1ZTogJ2ZpeCcKICAgIH0sCiAgICBwZXJmOiB7CiAgICAgIGRlc2NyaXB0aW9uOiAn5LyY5YyW5LqG5oCn6IO955qE5Luj56CB5pS55YqoJywKICAgICAgZW1vamk6ICfimqHvuI8nLAogICAgICB2YWx1ZTogJ3BlcmYnCiAgICB9LAogICAgcmVmYWN0b3I6IHsKICAgICAgZGVzY3JpcHRpb246ICfkuIDkupvku6PnoIHnu5PmnoTkuIrkvJjljJbvvIzml6LkuI3mmK/mlrDnibnmgKfkuZ/kuI3mmK/kv64gQnVnJywKICAgICAgZW1vamk6ICfwn5KhJywKICAgICAgdmFsdWU6ICdyZWZhY3RvcicKICAgIH0sCiAgICByZWxlYXNlOiB7CiAgICAgIGRlc2NyaXB0aW9uOiAn5Y+R5biDUmVsZWFzZeeJiOacrOaPkOS6pCcsCiAgICAgIGVtb2ppOiAn8J+PuScsCiAgICAgIHZhbHVlOiAncmVsZWFzZScKICAgIH0sCiAgICBzdHlsZTogewogICAgICBkZXNjcmlwdGlvbjogJ+S7o+eggeeahOagt+W8j+e+juWMlu+8jOS4jea2ieWPiuWIsOWKn+iDveS/ruaUueetiScsCiAgICAgIGVtb2ppOiAn8J+ShCcsCiAgICAgIHZhbHVlOiAnc3R5bGUnCiAgICB9LAogICAgdGVzdDogewogICAgICBkZXNjcmlwdGlvbjogJ+aWsOWinuaIluS/ruaUueW3suacieeahOa1i+ivleS7o+eggScsCiAgICAgIGVtb2ppOiAn8J+SjScsCiAgICAgIHZhbHVlOiAndGVzdCcKICAgIH0sCiAgICBidWlsZDogewogICAgICBkZXNjcmlwdGlvbjogJ+W9seWTjeaehOW7uuezu+e7n+aIluWklumDqOS+nei1lumhueeahOabtOaUue+8iOekuuS+i+iMg+WbtO+8mmd1bHDjgIFicm9jY29saeOAgW5wbe+8iScsCiAgICAgIGVtb2ppOiAn8J+SjScsCiAgICAgIHZhbHVlOiAnYnVpbGQnCiAgICB9CiAgfQp9Owo=" | base64 -d
}
gen_commitlint_config_file() {
echo -n "bW9kdWxlLmV4cG9ydHMgPSB7CiAgICBleHRlbmRzOiBbJ0Bjb21taXRsaW50L2NvbmZpZy1jb252ZW50aW9uYWwnXSwKICAgIHJ1bGVzOiB7CiAgICAgICAgLy8gbGV2ZWxbMC4uMl06IDDooajnpLrnpoHnlKjop4TliJnvvIwx5Li66K2m5ZGK77yMMuS4uumUmeivrwogICAgICAgIC8vIEFwcGxpYWJsZSA6IGFsd2F5cyDpgILnlKjmraTop4TliJnvvIwgbmV2ZXLlj43ovazop4TliJkKICAgICAgICAvLyBWYWx1ZSDnlKjkuo7mraTop4TliJnnmoTlgLwKICAgICAgICAnYm9keS1sZWFkaW5nLWJsYW5rJzogWzIsICdhbHdheXMnXSwgLy8gYm9keSDlvIDlp4vkuo7nqbrnmb3ooYwKICAgICAgICAnaGVhZGVyLW1heC1sZW5ndGgnOiBbMiwgJ2Fsd2F5cycsIDcyXSwgLy8gaGVhZGVyIOWtl+espuacgOWkp+mVv+W6puS4uiA3MgogICAgICAgICdzdWJqZWN0LWZ1bGwtc3RvcCc6IFswLCAnbmV2ZXInXSwgLy8gc3ViamVjdCDnu5PlsL7kuI3liqAgJy4nCiAgICAgICAgJ3R5cGUtZW1wdHknOiBbMiwgJ25ldmVyJ10sIC8vIHR5cGXlrZfmrrXkuI3lj6/ku6XkuLrnqboKICAgICAgICAndHlwZS1lbnVtJzogWzIsICdhbHdheXMnLCBbCiAgICAgICAgICAgICdmZWF0JywgLy8g5paw54m55oCn44CB6ZyA5rGCCiAgICAgICAgICAgICdmaXgnLCAvLyBidWcg5L+u5aSNCiAgICAgICAgICAgICdkb2NzJywgLy8g5paH5qGj5YaF5a655pS55YqoCiAgICAgICAgICAgICdzdHlsZScsIC8vIOS4jeW9seWTjeS7o+eggeWQq+S5ieeahOaUueWKqO+8jOS+i+WmguWOu+aOieepuuagvOOAgeaUueWPmOe8qei/m+OAgeWinuWIoOWIhuWPtwogICAgICAgICAgICAncmVmYWN0b3InLCAvLyDku6PnoIHph43mnoQKICAgICAgICAgICAgJ3Rlc3QnLCAvLyDmt7vliqDmiJbkv67mlLnmtYvor5UKICAgICAgICAgICAgJ2Nob3JlJywgLy8g5LiN5L+u5pS5IHNyYyDmiJbogIUgdGVzdCDnmoTlhbbkvZnkv67mlLnvvIzkvovlpoLmnoTlu7rov4fnqIvmiJbovoXliqnlt6XlhbfnmoTlj5jliqgKICAgICAgICAgICAgJ3JldmVydCcsIC8vIOaJp+ihjCBnaXQgcmV2ZXJ0IOaJk+WNsOeahCBtZXNzYWdlCiAgICAgICAgICAgICdidWlsZCcsIC8vIOW9seWTjeaehOW7uuezu+e7n+aIluWklumDqOS+nei1lumhueeahOabtOaUue+8iOekuuS+i+iMg+WbtO+8mmd1bHDjgIFicm9jY29saeOAgW5wbe+8iQogICAgICAgIF1dLAogICAgfQp9Owo=" | base64 -d
}
install_commitizen() {
if which cz > /dev/null; then
echo "commitizen 已经安装!"
return 0
fi
echo "安装 commitizen ..."
npm install -g commitizen
echo "安装 commitizen 成功!"
}
install_cz_changelog() {
if grep "cz-conventional-changelog" "$HOME/.czrc" > /dev/null 2>&1 ; then
echo "cz-conventional-changelog 已经安装!"
else
echo "安装 cz-conventional-changelog ..."
npm install -g cz-conventional-changelog
echo "安装 cz-conventional-changelog 成功!"
echo "添加 cz-conventional-changelog 到 .czrc"
mv $HOME/.czrc $HOME/.czrc.bak
echo '{ "path": "cz-conventional-changelog" }' > "$HOME/.czrc"
echo "添加 cz-conventional-changelog 到 .czrc 成功!"
fi
}
install_commitlint() {
if which commitlint > /dev/null 2>&1; then
echo "commitlint 已经安装!"
else
echo "安装 commitlint ..."
npm install -g @commitlint/{cli,config-conventional}
echo "安装 commitlint 成功!"
fi
}
config_cz() {
install_commitizen
install_cz_changelog
install_commitlint
echo "初始化 commitizen:"
commitizen init cz-conventional-changelog --save-dev --save-exact --force
echo "检测 .gitignore 中是否过滤掉了 node_modules目录"
if grep "node_modules" "./.gitignore" > /dev/null 2>&1 ; then
echo "node_modules is already in .gitignore"
else
echo "添加 node_modules 到 .gitignore"
echo "node_modules" >> "./.gitignore"
fi
if [ -f "changelog.config.js" ] ; then
echo "changelog.config.js 已存在"
else
echo "生成 changelog.config.js"
gen_changelog_config_file > changelog.config.js
fi
if [ -f "./commitlint.config.js" ] ; then
echo "commitlint.config.js 已存在"
else
echo "生成 commitlint.config.js"
gen_commitlint_config_file > commitlint.config.js
fi
if grep commitlint "./.husky/commit-msg" >/dev/null 2>&1 ; then
echo "husky已经安装,commitlint已经配置"
else
echo "安装 husky:"
npm install --save-dev husky
echo "激活钩子:"
npx husky install
echo "添加 commitlint 钩子:"
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
fi
echo "配置完毕!"
echo "请修改内容后执行 git cz 提交命令验证配置是否正确"
}
usage() {
cat <<END
Usage:
自动化配置 git commitlint 和 commitizen
`basename $0` config
END
}
pre_check
case $1 in
config)
config_cz
;;
*)
usage
;;
esac
所有关于git的内容到此结束!