前言
在公司的一次上线后,测试突然说某个功能不是还没测试完成吗,怎么到线上了。我大吃一惊赶忙去排查问题,后面发现是有同学把dev
开发分支合并到功能分支里面了,上线时master
分支合并了功能分支,导致dev
分支里面未测试完成的功能跟着一起上到了master
。 会出问题的原先是在原先小公司时,对分支划分没有那么清晰,多人多版本开发情况比较少,一般dev
上只有当前迭代的需求,所以会出现master
直接合并dev
的情况。但当团队规模大或者需求多的时候就不能这样做了,需要有合理的分支管理,git工作流,上线代码审核等步骤。
Git 分支管理的挑战
在平时团队开发中,通常会有不同的 Git 分支,每个分支用于不同的目的。以下是一些常见的分支和其用途:
master
:用于正式环境,包含已发布的稳定版本。dev
:用于开发或测试环境,包含正在进行的开发工作,但可能包含未完成或未经测试的代码。pre
:用于预发布环境,用于在正式发布之前进行最后的测试和验证。feature/xx
:用于不同功能或特性的开发,通常从master
分支分出,用于独立开发功能。
问题出现在dev
和pre
分支上,因为它们可能包含未完成的工作或未经过充分测试的代码。如果这些分支的代码被错误地合并到master
或feature/xx
分支,将会导致线上代码出现问题。
尽管团队内部可能有规范和流程来避免这种情况,但有时人为因素仍可能导致问题的发生。这时,工程化解决方案就显得尤为重要,我们更需要采用工程化的方式,结合工具如 husky,来确保代码的安全性和质量。
husky:Git 钩子的好帮手
Husky 是一个强大的工具,它允许我们在 Git 操作中添加 githooks 钩子,以便在特定的时机执行自定义脚本。这些脚本可以用于执行各种任务,包括在 Git 合并分支时进行检查,以确保代码合并的安全性。
要开始使用 husky,在项目根目录中运行以下命令:
shell
npm install husky --D
安装完成后,需要将 husky
和项目的 git
建立连接,才会监听 git
的事件,在根目录执行:
shell
npx husky install
同时也要在 package.json
里面添加一下,确保每次安装依赖后都能自动建立连接:
json
// package.json
"script": {
"prepare": "husky install",
}
prepare: 会在安装依赖完成后自动执行,这样在其他同学的电脑上打开项目,安装依赖后就可以自动建立连接啦。
配置 Git 合并分支的 Hook
在上面 husky
安装完成后,就该添加监听合并分支的钩子了,在git
提供的一系列的githooks 中,post-merge
会在git merge
之后执行,并获取到当前分支和合并分支的名称,可以通过这个钩子来验证被合并分支是否为 dev
或 pre
,来判断是否需要取消合并。
添加合并分支 hook
监听:
shell
npx husky add .husky/post-merge
会在根目录.husky文件夹中新增post-merge
文件,添加了 git
的 post-merge
钩子后,会劫持 git
的分支合并事件,在触发事件后执行 post-merge
文件,这个就我们最核心的检测合并分支是不是dev
和pre
的脚本文件了,在 post-merge
文件添加代码
sh
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# 当前分支的名称
CURRENT_BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
# 合并分支的名称
MERGE_BRANCH_NAME="${GIT_REFLOG_ACTION//merge /}"
echo "------$MERGE_BRANCH_NAME"
# 禁止合并的公共分支
forbidden_branches=("pre" "dev")
# 判断当前合并的分支是否属于禁止合并的分支
if [[ " ${forbidden_branches[*]} " = *" $MERGE_BRANCH_NAME "* ]]; then
echo "检测到非法合并: $CURRENT_BRANCH_NAME merge $MERGE_BRANCH_NAME"
echo "撤销合并中..."
git reset --merge HEAD@{1} # 撤回合并
echo "已撤销合并"
exit 1
fi
这段脚本会检查当前合并操作的分支是否是dev
或pre
分支。如果是的话,将会撤销合并操作并显示错误信息,并以异常 1 退出,这样不符合规定的合并操作就会被自动撤回,有效确保了代码的安全性。
进行测试
在 dev
分支上进行一些修改,然后 add/commit
提交,再回到 master
分支,执行合并 dev
操作:
sql
git merge dev
会看到出现下图,git
钩子监听到了合并分支事件,获取到分支是 dev
,在我们不能合并的分支之内,执行了合并回退操作。
结论
Git
分支管理是现代软件开发的重要组成部分。通过合理的分支策略和 husky
工具,我们可以有效地保障代码的质量和安全性。避免不合规的分支合并到主分支中,减少异常情况发生,但有条件的话也要进行代码上线审查,master权限管控等,从多方面来确保线上代码安全。本文也只是提供一个思路,具体判断和实现也根据公司现有的情况来实施。