git hook 异常合并检测
git hook 异常合并检测
vi project_name/hooks/pre-receive
加入以下脚本
# 我用的 git 软件是 gitea
PUSHER_NAME=${GITEA_PUSHER_NAME}
DINGDING_ACCESS_TOKEN="xxx"
GIT_MANAGER=(
"http://lukachen.com"
)
# 钉钉报警
funNotify(){
curl 'https://oapi.dingtalk.com/robot/send?access_token='"${DINGDING_ACCESS_TOKEN}"'' -s -H 'Content-Type: application/json' -d '{"msgtype":"text","text":{"content":"'"$1"'"},"at":{"isAtAll":true}}' > /dev/null 2>&1
}
# 判断字符串是否在数组中,是返回1,否返回0
funInArray(){
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 1; done
return 0
}
while read oldrev newrev refname; do
# echo ${oldrev} ${newrev} ${refname}; exit 1;
if [[ $refname == "refs/heads/master" || $refname == "refs/heads/develop" ]]; then
# 稳定分支上的 commit list
span=$(git rev-list $oldrev..$newrev $EXCLUDE_EXISTING)
for commit in $span; do
# develop、master 分支上最后一个 merge 点
last_merge_commit=$commit
break;
done
# 检查稳定分支上的节点,需为 merge|revert 节点
for commit in $span; do
msg=$(git log --format=%s -n 1 $commit);
is_ignore=$(echo $msg | grep -v grep | grep -Ei 'revert|merge' | wc -l);
if [[ $is_ignore -gt 0 ]]; then
continue
fi
is_merge=$(git show --no-patch --format="%P" $commit | awk '{print NF}');
if [[ $is_merge -lt 2 ]]; then
funNotify "repo: $REPO_NAME\nsha1: $commit\ncommit remark: $msg\nerror: 不允许直接在 $refname 提交代码\nhook: verify_merge\ncmd: git rev-list $oldrev..$newrev $EXCLUDE_EXISTING\npush user: $PUSHER_NAME\n"
echo "=========================提示========================="
echo "hook: ${BASH_SOURCE[0]}"
echo "sha1: $commit"
echo "commit message: $msg"
echo "不允许直接在 $refname 提交代码, 请使用 git merge --no-ff origin/feature/storyNUM 合并代码"
echo "======================================================"
exit 1
fi
done
# story 分支上的最后一个 commit, merge 节点 Parent2 是 story 分支
last_commit=$(git show --no-patch --format=%P $newrev | awk '{print $2}')
if [[ $last_commit == "" ]]; then
# is revert commit
continue
fi
last_commit_msg=$(git log --format=%s -n 1 $last_commit)
# 检查要上线的 last_commit 是否上过外测了
if [[ $refname == "refs/heads/master" ]]; then
in_develop=$(git branch -a --contains $last_commit | grep -v grep | grep develop | wc -l)
last_commit_is_revert=$(echo $last_commit_msg | grep -v grep | grep -Ei 'revert' | wc -l)
if [[ $last_commit_is_revert -eq 0 && $in_develop -eq 0 ]]; then
funNotify "repo: $REPO_NAME\nhook: verify_merge\nsha1: $last_commit\ncommit msg: $last_commit_msg\nerror: 节点未通过 develop(外测) 验收\npush user: $PUSHER_NAME\n"
echo "=========================提示========================="
echo "hook: ${BASH_SOURCE[0]}"
echo "sha1: $last_commit"
echo "commit msg: $last_commit_msg"
echo "error: 节点未经过 develop(外测) 验收"
echo "======================================================"
exit 1
fi
fi
# 检查要上 develop 的代码的 story 分支代码,是否有异常合并
## step1.获取最后一个 commit 所在的 story 分支 (如果存在分支间的合并,这个可能会获取失误。这里放行管理员操作)
## step2.获取 story 分支的 fork point:
## 2.1 first_point=$(git log --reverse --format=format:%H master..feature/story51805 | head -1)
## 2.2 fork_point=$(git show --no-patch --pretty=format:%H ${first_point}^)
## step3.获取 story 分支的所有普通 commit 节点的文件列表
## 3.1 获取仅在 story 分支的 非merge commits
## 3.2 获取 3.1 节点的修改文件
## step4.获取 git diff --name-only $last_merge_commit..${last_merge_parent1_commit}, 循环列表中的文件判断是不是在 3 的列表中(这些文件是要上 develop 时的修改文件)
if [[ $refname == "refs/heads/develop" ]]; then
# step1
story_branch_num=$(git branch -a --contains $last_commit | grep -v grep | grep -Ei 'feature' | wc -l)
funInArray "${PUSHER_NAME}" "${GIT_MANAGER[@]}"
is_git_manager=$?
if [[ $story_branch_num -gt 1 && $is_git_manager == 0 ]]; then
# 最后一个节点如果在多个分支,就没办法判断当前是在合并的哪个分支的需求了,所以只能限制一下
funNotify "repo: $REPO_NAME\nhook: verify_merge\nsha1: $last_commit\ncommit msg: $last_commit_msg\nerror: 存在 story 分支间合并,请联系管理员处理,谢谢\ncmd: git branch -a --contains $last_commit\npush user: $PUSHER_NAME\n"
echo "=========================提示========================="
echo "hook: ${BASH_SOURCE[0]}"
echo "sha1: $last_commit"
echo "commit msg: $last_commit_msg"
echo "error: 存在 story 分支间合并,请联系管理员处理,谢谢"
echo "======================================================"
exit 1
fi
if [[ $story_branch_num -eq 1 ]]; then
# step2
story_branch=$(git branch -a --contains $last_commit | grep -v grep | grep -Ei 'feature')
first_point=$(git log --reverse --format=format:%H master..$story_branch | head -1)
fork_point=$(git show --no-patch --pretty=format:%H ${first_point}^)
# step3
# 3.1
fork_to_last_commits=$(git log --format=%H --no-merges $fork_point..$last_commit)
fork_to_master_commits=$(git log --format=%H --no-merges $fork_point..master)
fork_to_master_commits_array=()
if [[ $fork_to_master_commits != "" ]]; then
for one_commit in $fork_to_master_commits; do
fork_to_master_commits_array+=($one_commit)
done
fi
story_commits=""
for one_commit in $fork_to_last_commits; do
if [[ ${#fork_to_master_commits_array[@]} -eq 0 ]]; then
story_commits="$story_commits $one_commit"
continue
fi
funInArray "$one_commit" "${fork_to_master_commits_array[@]}"
commit_in_master=$?
if [[ $commit_in_master == 0 ]]; then
story_commits="$story_commits $one_commit"
continue
fi
done
if [[ $story_commits == "" ]]; then
# 没有开发分支节点,可能是 merge master into develop
continue
fi
# debug
# echo $last_commit
# echo $story_commits
# 3.2
story_files=$(git show --pretty="" --name-only $story_commits)
story_files_array=()
for tmp in $story_files; do
funInArray "$tmp" "${story_files_array[@]}"
in_story_files_array=$?
if [[ $in_story_files_array == 0 ]]; then
story_files_array+=($tmp)
fi
done
# step4
merge_files=$(git diff --name-only $last_merge_commit..${last_merge_commit}^)
is_error_merge=0
error_files_array=()
for one_file in $merge_files; do
funInArray "$one_file" "${story_files_array[@]}"
in_story_files=$?
if [[ $in_story_files == 0 ]]; then
is_error_merge=1
error_files_array+=($one_file)
fi
done
if [[ $is_error_merge == 1 ]]; then
echo "=========================提示========================="
echo "hook: ${BASH_SOURCE[0]}"
echo "error: $story_branch 分支可能存在异常合并, 请 fgit develop $REPO_NAME 重新尝试合并或联系管理员处理,谢谢"
echo "error_files: ${error_files_array[@]}"
echo "======================================================"
# 阻止普通人员的提交
if [[ $is_git_manager == 0 ]]; then
funNotify "repo: $REPO_NAME\nhook: verify_merge\nerror: $story_branch 分支可能存在异常合并\nerror_files: ${error_files_array[@]}\npush user: $PUSHER_NAME\n"
exit 1
fi
# 放行管理员操作
fi
fi
fi
fi
done
exit 0
文章目录
打赏: 微信
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。