在多人协作时,我们会把各自的分支开发的功能合并入test分支。有的分支可能有当前版本不能上的代码。这时如果有人将test分支合到自己当前需要发的分支中,会将自己分支给污染,一不注意就会影响整个系统当前版本上线;我们一般会约定test分支只可合入代码,而不能将其合入其它分支。约定的有时一不注意就会出错,因此这里我们将通过自动化检测防止分支误合并,通过硬性机制控制
基本原理
-
githooks
的prepare-commit-msg
与post-commit
、post-merge
钩子 -
child_process
node子进程执行shell -
git tag
标记合并前代码便于回退 -
git reset --hard
回退代码 -
git symbolic-ref --short -q HEAD
获取当前分支名 -
git log --grep=
过滤commit提交记录
基本流程
- 合并前触发
prepare-commit-msg
钩子 判断是否为测试分支(不可合并入其它分支),不是开发分支则打标签 - 合并后触发
post-merge
钩子 非不可合并分支时查询提交记录里是否有不可合并分支名称记录,命中则根据标签还原 - 只是
commit
提交后,为防止推送是和远程tag
冲突 需触发post-commit
删除tag
源码(基于node)
- 工具库
const childprocess = require('child_process');
// 检查提交记录是否包含name
function checkMerge(name){
return new Promise(function (resolve,reject){
childprocess.exec(`git log --grep="Merge branch '${name}'"`,(err,stdout,stderr)=>{
if (err !== null) {
return reject(err)
}
return resolve(!!stdout)
})
})
}
// 检查当前分支是否为name
function checkBranch(name){
return new Promise(function(resolve,reject){
childprocess.exec(`git symbolic-ref --short -q HEAD`,(err,stdout,stderr)=>{
if (err !== null) {
return reject(err)
}
return resolve(stdout.search(name)===0)
})
})
}
module.exports={checkMerge,checkBranch}
prepare-commit-msg
执行脚本
const {checkBranch} =require('./mergelint.util.js')
async function main(){
// 检查是否为测试分支或者开发分支
const res = await checkBranch(/operate_test|operate_dev/)
// 不为开发分支
if(!res){
// 打标签
const childprocess = require('child_process');
childprocess.exec(`git tag -d m0.1.0`,function(){
childprocess.exec(`git tag -a m0.1.0 -m "合并分支暂存"`,function (error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
}
console.log('打标签成功')
});
})
}
}
main()
post-merge
执行脚本
const {checkBranch,checkMerge} =require('./mergelint.util.js')
async function main(){
const res = await checkBranch(/operate_test|operate_dev/)
if(res){
childprocess.exec(`git tag -d m0.1.0`,function(){})
return true
}
// 检查是否含测试分支
const resM = await checkMerge('operate_test')
const resM2 = await checkMerge('operate_dev')
// 为开发分支
if(resM||resM2){
// 还原
const childprocess = require('child_process');
childprocess.exec(`git reset --hard m0.1.0`,function (error, stdout, stderr) {
if (error !== null) {
console.log('当前分支被污染,请手动处理!')
return
}
console.log('请不要合并test和dev分支到当前分支!')
childprocess.exec(`git tag -d m0.1.0`,function(){})
});
}else{
childprocess.exec(`git tag -d m0.1.0`,function(){})
}
}
main()