git commit规范及自动生成CHANGELOG.md
本文以Ubuntu为例。
1.卸载旧版本Node.js并安装最新版本
sudo apt remove nodejs npm
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs
检查版本:
node --version
npm --version
2.安装相关Package
首先安装淘宝的cnpm代替npm:
sudo npm install -g cnpm -registry=https://registry.npmmirror.com
查看版本:
cnpm --version
sudo cnpm install -g husky cz-customizable commit-and-tag-version conventional-changelog-cli
echo '{ "path": "cz-customizable" }' > ~/.czrc
3.本地创建git仓库
解决Git显示中文文件名为乱码:
git config --global core.quotepath false
忽略文件权限变化:
git config --global core.filemode false
设置默认编辑器为vim
:
git config --global core.editor vim
mkdir test-git-commit && cd test-git-commit
git init
4.远程创建git仓库
初始化仓库:
5.创建本地配置文件
code .
新建.gitignore
、.cz-config.js
、test.txt
和README.md
,内容如下:
.gitignore
:
.cz-config.js
.cz-config.js
:
module.exports = {
types: [
{
value: '✨ feat',
name: '✨ feat:\tA new feature | 新功能'
},
{
value: '🚧 wip',
name: '🚧 wip:\tWork in progress | 正在开发中'
},
{
value: '🐛 fix',
name: '🐛 fix:\tA bug fix | Bug 修复'
},
{
value: '🔥 remove',
name: '🔥 remove:\tRemove code or files | 移除代码或文件'
},
{
value: '⚰️ bury',
name: '⚰️ bury:\tBury dead code | 埋葬无用代码'
},
{
value: '💩 poop',
name: '💩 poop:\tPoop | 写了一些屎一样待优化的代码'
},
{
value: '💄 ui',
name: '💄 ui:\tUpdated UI and style files | 更新UI'
},
{
value: '🎨 style',
name: '🎨 style:\tMarkup, white-space, formatting, missing semi-colons... | 风格'
},
{
value: '🔨 script',
name: '🔨 script:\tAdd or update the build system | 脚本'
},
{
value: '💡 comment',
name: '💡 comment:\tComment | 注释'
},
{
value: '🍱 asset',
name: '🍱 asset:\tAdd or update assets | 资源'
},
{
value: '📸 image',
name: '📸 image:\tAdd or update images | 图像'
},
{
value: '🔧 config',
name: '🔧 config:\tAdd or update configuration files | 配置文件'
},
{
value: '🚚 path',
name: '🚚 path:\tMove or rename resources (e.g.: files, paths, routes) | 移动'
},
{
value: '🧱 chore',
name: '🧱 chore:\tBuild process or auxiliary tool changes | 构建/工程依赖/工具'
},
{
value: '🚨 lint',
name: '🚨 lint:\tFix compiler or linter warnings | 编译/代码检查工具警告'
},
{
value: '🚑️ hotfix',
name: '🚑️ hotfix:\tCritical hotfix | 紧急修复'
},
{
value: '✏️ typo',
name: '✏️ typo:\tFix typos | 错别字'
},
{
value: '🏷️ type',
name: '🏷️ type:\tAdd or update types | 增加或更新类型'
},
{
value: '🛂 passport',
name: '🛂 passport:\tWork on code related to authorization, roles and permissions | 授权、身份和权限相关'
},
{
value: '🦺 val',
name: '🦺 val:\tAdd or update code related to validation | 验证相关'
},
{
value: '⚓ hook',
name: '⚓ hook:\tGit hook | 钩子'
},
{
value: '🐳 docker',
name: '🐳 docker:\tDocker container | Docker容器相关'
},
{
value: '☸️ k8s',
name: '☸️ k8s:\tKubernetes | Kubernetes相关'
},
{
value: '💫 anim',
name: '💫 anim:\tAdd or update animations and transitions | 动画和过渡'
},
{
value: '👔 logic',
name: '👔 logic:\tAdd or update business logic | 业务逻辑'
},
{
value: '💬 text',
name: '💬 text:\tAdd or update text and literals | 文本和文字'
},
{
value: '⚡️ perf',
name: '⚡️ perf:\tA code change that improves performance | 性能优化'
},
{
value: '🗃️ db',
name: '🗃️ db:\tPerform database related changes | 数据库相关'
},
{
value: '🧵 thread',
name: '🧵 thread:\tAdd or update code related to multithreading or concurrency | 线程'
},
{
value: '👽️ api',
name: '👽️ api:\tUpdate code due to external API changes | API相关'
},
{
value: '🔐 secert',
name: '🔐 secert:\tSecert | 秘钥'
},
{
value: '💸 fund',
name: '💸 fund:\tAdd sponsorships or money related infrastructure | 资金相关'
},
{
value: '🚀 deploy',
name: '🚀 deploy:\tDeploy stuff | 部署'
},
{
value: '🚸 usability',
name: '🚸 usability:\tImprove user experience or usability | 增强用户体验/可用性'
},
{
value: '🌐 i18n',
name: '🌐 i18n:\tInternationalization | 国际化'
},
{
value: '🌐 l10n',
name: '🌐 l10n:\tLocalization | 本地化'
},
{
value: '🔀 merge',
name: '🔀 merge:\tMerge branch | 合并'
},
{
value: '⏪ revert',
name: '⏪ revert:\tRevert | 回退'
},
{
value: '🔖 release',
name: '🔖 release:\tCreate a release commit | 发行版'
},
{
value: '📦 build',
name: '📦 build:\tBuild System | 打包构建'
},
{
value: '🥅 catch',
name: '🥅 catch:\tCatch errors | 捕捉错误'
},
{
value: '🔊 add_log',
name: '🔊 add_log:\tAdd or update logs | 添加日志'
},
{
value: '🔇 rm_log',
name: '🔇 rm_log:\tRemove logs | 移除日志'
},
{
value: '➕ add_dep',
name: '➕ add_dep:\tAdd dep | 添加依赖'
},
{
value: '➖ rm_dep',
name: '➖ rm_dep:\tRemove dep | 移除依赖'
},
{
value: '⬆️ up_dep',
name: '⬆️ up_dep:\tUpgrade dep | 升级依赖'
},
{
value: '⬇️ down_dep',
name: '⬇️ down_dep:\tDowngrade dep | 降级依赖'
},
{
value: '📌 pin_dep',
name: '📌 pin_dep:\tPin dependencies to specific versions | 固定依赖版本'
},
{
value: '💚 fix_ci',
name: '💚 fix_ci:\tFix CI Build | CI 修复'
},
{
value: '👷 ci',
name: '👷 ci:\tCI related changes | CI 配置'
},
{
value: '📈 monitor',
name: '📈 monitor:\tAdd or update analytics or track code | 分析或跟踪'
},
{
value: '♻️ refactor',
name: '♻️ refactor:\tA code change that neither fixes a bug or adds a feature | 代码重构'
},
{
value: '✅ test',
name: '✅ test:\tAdding tests | 测试'
},
{
value: '⚗️ exp',
name: '⚗️ exp:\tPerform experiments | 实验'
},
{
value: '🎉 init',
name: '🎉 init:\tBegin a project | 初始化'
},
{
value: '🙈 ignore',
name: '🙈 ignore:\tAdd or update a .gitignore file | 忽略'
},
{
value: '📄 license',
name: '📄 license:\tAdd or update license | 证书'
},
{
value: '📝 doc',
name: '📝 doc:\tDocumentation only changes | 文档'
},
],
messages: {
type: '请选择提交类型(必填):',
customScope: '请输入文件修改范围(可选):',
subject: '请简要描述提交(必填):',
body: '请输入详细描述(可选):',
breaking: '列出任何\x1b[1;31mBREAKING CHANGES\x1b[0m(可选):',
footer: '请输入要关闭的\x1b[1;38;5;129missue\x1b[0m(可选):',
confirmCommit: '确定提交此说明吗?:'
},
allowCustomScopes: true,
allowBreakingChanges: ['✨ feat', '🐛 fix', '🚧 wip', '🔥 remove', '🚚 path', '💩 poop', '⏪ revert', '➖ rm_dep', '➕ add_dep', '⬆️ up_dep', '⬇️ down_dep', '📌 pin_dep'],
subjectLimit: 100
};
test.txt
:
1
README.md
:
# FIRST COMMIT
之后进行npm init
:
npm init
依次填写即可(注意git远程仓库url不能填错):
生成.husky
文件夹:
husky
6.修改配置文件
修改.husky/_/pre_push
:
原先:
#!/usr/bin/env sh
. "${0%/*}/h"
修改后:
#!/usr/bin/env sh
git pull --rebase || {
echo "\e[1;31m代码拉取失败\e[0m"
exit 1
}
echo "\e[1;32m\e[1m代码拉取成功\e[0m"
commit-and-tag-version
# 获取仓库根目录
repo_root_dir=$(git rev-parse --show-toplevel)
# 获取最新的标签
latest_tag_global=$(git describe --tags "$(git rev-list --tags --max-count=1)")
git tag -d "${latest_tag_global}"
updateVersionTag() {
latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)" 2>/dev/null)
# 使用正则表达式从标签中提取主版本号、次版本号和修订号
major_version=$(echo "${latest_tag}" | cut -d '.' -f 1 | sed 's/v//')
minor_version=$(echo "${latest_tag}" | cut -d '.' -f 2)
patch_version=$(echo "${latest_tag}" | cut -d '.' -f 3)
# 如果是第一次提交,即没有标签
if [ -z "${latest_tag}" ]; then
new_tag="v1.0.0"
echo "${new_tag}"
return
fi
# 更新版本号
if [ "${patch_version}" -eq 9 ]; then
# 如果修订号为 9
patch_version=0 # 将修订号重置为 0
# 接下来检查次版本号
if [ "${minor_version}" -eq 9 ]; then
# 如果次版本号也为 9
minor_version=0 # 将次版本号重置为 0
major_version=$((major_version + 1)) # 将主版本号加 1
else
# 如果次版本号不是 9
minor_version=$((minor_version + 1)) # 将次版本号加 1
fi
else
# 如果修订号不是 9
patch_version=$((patch_version + 1)) # 将修订号加 1
fi
new_tag="v${major_version}.${minor_version}.${patch_version}"
# 返回
echo "${new_tag}"
}
updateVersionInPackageJson() {
new_version="$1"
sed -i "s/\"version\": \".*\"/\"version\": \"${new_version}\"/" "${repo_root_dir}/package.json"
}
new_tag=$(updateVersionTag)
updateVersionInPackageJson "${new_tag}"
git add "${repo_root_dir}/package.json"
git commit --amend -m "🔖 tag(package.json): ${new_tag}"
rm "${repo_root_dir}/CHANGELOG.md"
conventional-changelog -i "${repo_root_dir}/CHANGELOG.md" -s -r 0
# 获取当前仓库的远程URL
remote_url=$(git remote -v | grep origin | grep '(fetch)' | awk '{print $2}')
# 处理commit URL
case "${remote_url}" in
*github.com*)
echo "\e[1;32mRemote URL is from GitHub.\e[0m"
;;
*gitee.com*)
echo "\e[1;32mRemote URL is from Gitee.\e[0m"
sed -i 's/commits\//commit\//g' "${repo_root_dir}/CHANGELOG.md"
;;
*gitcode.com*)
echo "\e[1;32mRemote URL is from GitCode.\e[0m"
sed -i 's/commits\//commits\/detail\//g' "${repo_root_dir}/CHANGELOG.md"
;;
*)
echo "\e[1;31mRemote URL is from an unknown source.\e[0m"
;;
esac
git add "${repo_root_dir}/CHANGELOG.md"
git commit -m "📝 doc(CHANGELOG.md): automatic update"
git tag -a "${new_tag}" -m "🔖 tag: ${new_tag}"
echo "\e[1;32m更新后的标签为: ${new_tag}\e[0m"
7.测试
git add .
使用cz-cust
代替git commit -m
:
cz-cust
选择init
:
或者起一个别名:
sudo vi /etc/profile # 为了使多用户和多Shell解释器同时生效
在最后加上:
alias cz='cz-cust'
保存退出:
source /etc/profile
git log
git push origin --set-upstream --follow-tags -u master
可以看到已经自动生成了CHANGELOG.md
:
此时远程仓库已经更新:
8.Tips
之后推送代码可使用以下命令:
git push --follow-tags && sed -i 's/^/# /' $(git rev-parse --show-toplevel)/.husky/_/pre-push && git push --follow-tags && sed -i 's/^# //' $(git rev-parse --show-toplevel)/.husky/_/pre-push