当前位置: 首页 > news >正文

【gitlab】通过 `pre-receive` 钩子控制 MR 合并时的分支路径合并方向,阻止未经允许的合并路径

📜 专用钩子脚本

将以下脚本保存为:/gitlab/custom_hooks/pre-receive.d/check-merge-rules,并确保其可执行 (chmod +x)。

#!/usr/bin/env bash# 全局 pre-receive 钩子:仅校验MR合并的分支路径规则# 注意:分支的推送权限(是否允许直接push)应由GitLab界面上的“分支保护”功能控制。# --- 规则配置 ---readonlyMAIN_BRANCH="main"readonlyDEVELOP_BRANCH="develop"# 定义允许合并到 main 的源分支模式readonlyALLOWED_MERGE_TO_MAIN=("develop""hotfix/*")# 定义允许合并到 develop 的源分支模式readonlyALLOWED_MERGE_TO_DEVELOP=("feature/*""bugfix/*""sync-hotfix-*")# --- 函数:拒绝推送并给出提示 ---reject_with_message(){echo"❌ 合并请求路径校验失败"echo"📌 目标分支:$1"echo"📌 源分支:$2"echo"📋 规则:$3"echo"💡 请创建符合上述规则的合并请求。"exit1}# --- 主逻辑 ---whileread-r oldrev newrev refname;do# 提取目标分支名target_branch="${refname#refs/heads/}"# 仅对推送到 main 或 develop 的合并操作进行检查if[["$target_branch"!="$MAIN_BRANCH"&&"$target_branch"!="$DEVELOP_BRANCH"]];thencontinue# 推送到其他分支,不予干涉fi# 判断是否为“快进合并”推送(这是GitLab执行MR合并的典型方式)ifgitmerge-base --is-ancestor"$oldrev""$newrev"2>/dev/null;then# 是快进推送,尝试分析是否为合并提交# 获取本次推送引入的最后一个提交(最可能是合并提交)latest_commit=$(gitrev-list -n1"$oldrev".."$newrev")# 检查这个提交是否是合并提交(有两个或以上父提交)parent_count=$(gitlog --pretty=%P -n1"$latest_commit"|wc-w)if[[$parent_count-lt2]];then# 如果不是合并提交,说明是直接推送,这应由分支保护功能阻止# 此处我们只记录日志并放行,最终应由GitLab的“允许推送”设置来拦截echo"信息: 检测到向${target_branch}的直接推送,分支保护规则将决定是否允许。"continuefi# 是合并提交,提取其第二个父提交(即被合并的源分支的最后提交)source_commit=$(gitlog --pretty=%P -n1"$latest_commit"|cut-d' '-f2)# 查找包含此提交的源分支名(取第一个找到的远程分支)source_branch=$(gitbranch -r --contains"$source_commit"2>/dev/null|head-1|sed's|^origin/||')if[[-z"$source_branch"]];then# 如果通过父提交找不到远程分支,尝试一种备用方案:# 检查本次推送引入的提交信息中,是否包含类似 "Merge branch 'feature/xxx'" 的GitLab默认合并信息merge_message=$(gitlog --format=%B -n1"$latest_commit")if[["$merge_message"=~[Mm]erge\branch\\'([^\']+)]];thensource_branch="${BASH_REMATCH[1]}"echo"信息: 通过提交信息解析出源分支为: '$source_branch'"elif[["$merge_message"=~[Mm]erge\request\\!\d+]];then# 如果提交信息是类似 “Merge request !123” 格式,说明是GitLab MR合并# 这种情况下,我们无法准确获知源分支名,但可以判断这是一个合规的MR合并操作# 出于安全,我们对此类“无法识别源分支的MR合并”进行放行,但记录日志。# 你也可以选择在此处添加更严格的判断,例如要求必须匹配特定模式。echo"警告: 检测到标准的GitLab MR合并提交,但无法解析具体源分支名。予以放行。"continueelse# 如果既找不到分支,提交信息也不是标准合并,则拒绝reject_with_message"$target_branch""(未知)""无法识别合并来源,请确保从有效的远程分支创建MR。"fifi# 根据目标分支应用对应规则进行匹配case"$target_branch"in"$MAIN_BRANCH")allowed=falseforpatternin"${ALLOWED_MERGE_TO_MAIN[@]}";doif[["$source_branch"==$pattern]];then# 注意这里的 $pattern 不加引号,以启用通配符匹配allowed=truebreakfidoneif!$allowed;thenreject_with_message"$MAIN_BRANCH""$source_branch""仅允许从${ALLOWED_MERGE_TO_MAIN[*]}合并。"fi;;"$DEVELOP_BRANCH")allowed=falseforpatternin"${ALLOWED_MERGE_TO_DEVELOP[@]}";doif[["$source_branch"==$pattern]];thenallowed=truebreakfidoneif!$allowed;thenreject_with_message"$DEVELOP_BRANCH""$source_branch""仅允许从${ALLOWED_MERGE_TO_DEVELOP[*]}合并。"fi;;esacecho"信息: 合并路径检查通过 [${source_branch}->${target_branch}]。"else# 非快进推送(如强制推送),拒绝以保护历史echo"❌ 拒绝向${target_branch}的强制推送或非快进推送。"echo"💡 请通过创建合并请求来合入代码。"exit1fidoneexit0

🔧 脚本与GitLab功能的分工

此脚本与GitLab Web界面设置形成了明确分工,如下表所示:

控制维度负责组件具体设置/行为
能否直接推送GitLab 分支保护设置 > 仓库 > 受保护的分支中,将maindevelop“允许推送”设置为“无一人”
谁能合并MRGitLab 分支保护在同上位置,设置“允许合并”为“维护者”或“开发者+维护者”。
MR的源分支是否符合路径规则pre-receive钩子如上脚本,校验feature/* -> develop,hotfix/* -> main等规则。
Hotfix同步回Developpre-receive钩子脚本ALLOWED_MERGE_TO_DEVELOP规则已包含sync-hotfix-*模式,允许以此类分支为源创建到develop的MR。

🚀 部署与验证流程

  1. 保存并配置脚本

    sudovim/gitlab/custom_hooks/pre-receive.d/check-merge-rules# 粘贴脚本内容sudochmod+x /gitlab/custom_hooks/pre-receive.d/check-merge-rulessudochowngit:git /gitlab/custom_hooks/pre-receive.d/check-merge-rules
  2. 在GitLab Web界面完成关键设置

    • 进入项目设置 > 仓库 > 受保护的分支
    • main分支
      • 允许推送无一人
      • 允许合并维护者(根据你的团队权限调整)
    • develop分支
      • 允许推送无一人
      • 允许合并开发者 + 维护者
  3. 测试验证

    • 测试1 (合规MR):从feature/test创建到develop的MR,合并时应成功
    • 测试2 (违规MR):从feature/test创建到main的MR,合并时钩子应拒绝,并显示清晰的规则错误。
    • 测试3 (直接推送):尝试git push origin developGitLab分支保护应直接拒绝(与钩子无关)。
    • 测试4 (Hotfix同步)
      • hotfix/xxx合并到main(应成功)。
      • main新建分支sync-hotfix-xxx
      • 创建sync-hotfix-xxx->develop的MR,合并时应成功

💡 核心要点与建议

  • 钩子专注于规则:脚本只验证“从哪合并到哪”的路径,不管“谁能推”或“谁能合并”,这些交给界面。
  • 清晰的错误提示:脚本拒绝时会明确给出目标分支、违规的源分支和正确规则,便于团队成员自助排查。
  • 同步Hotfix的正确姿势:规则中预设了sync-hotfix-*作为合规源分支,这要求团队在同步时遵循“从main创建同步分支,再向develop提MR”的安全流程。
  • 紧急绕过:若脚本有Bug需紧急合并,管理员可临时重命名钩子文件使其失效,修复后再恢复。

通过以上配置,你将得到一个既严格又清晰的分支合并管控系统。如果需要调整分支命名模式(例如将bugfix/*改为fix/*),只需修改脚本顶部的配置数组即可。

http://www.jsqmd.com/news/144787/

相关文章:

  • 2025年艺术涂料品牌大比拼,谁才是你的装修优选?环保艺术涂料/水性艺术涂料/墙面艺术漆,艺术涂料品牌怎么选择 - 品牌推荐师
  • 基于SpringBoot的蛋糕烘焙方法经验分享平台_huf98rmc
  • 2025年12月山东土工膜厂家推荐榜:HDPE/糙面/单糙面/双糙面/柱点/防渗/聚乙烯/光面/防水/加糙土工膜,山东恒阳凭优质多元化土工膜登榜 - 海棠依旧大
  • 不得了!湖北天玑AIGEO优化系统重磅推广!
  • 存储压缩:不是“挤水分”,而是让数据“轻装上阵
  • 43、【Ubuntu】【Gitlab】拉出内网 Web 服务:静态动态服务 - 详解
  • 提示词工程师(Prompt Engineer) 是一个随着大语言模型(如GPT系列)兴起而快速走红的新兴职业
  • 基于SpringBoot的设计师约稿平台 呢_jye277e8
  • Floorp Browser(基于Firefox火狐浏览器)
  • 微生物美容专利研究:酵母成分抑制致病微生物的作用原理
  • 2025年12月年会创意公司标杆企业最新推荐:GO互动,解锁企业盛典智能互动新体验 - 海棠依旧大
  • 2025年12月矿物铸件厂家推荐榜:矿物铸件直销、矿物铸件生产厂家、矿物铸件制造商、矿物铸件的头部企业,南通盟鼎新材料以高精技术赋能高端装备制造 - 海棠依旧大
  • 小程序心理健康辅导系统(安卓APP)_3vjf7e64
  • 【TVM 教程】处理 TVM 错误
  • Docker 镜像从 1GB 瘦身到 10MB?全网最全 Dockerfile 优化最佳实践 (多阶段构建实战)
  • 行业领先品牌不锈钢旋振筛厂家:设计合理,精细筛分
  • Claude Skills动态工具过滤深度解析:智能代理开发的革命性突破,收藏必备!
  • 【配送路径规划】基于鳄鱼伏击算法CAOA求解带时间窗的骑手外卖配送路径规划问题(目标函数:最优路径成本 含服务客户数量 服务时间 载量 路径长度)附Matlab代码
  • 详细介绍:[论文阅读] AI + 软件工程 | 首测GPT-4.1/Claude Sonnet 4适配能力:LLM多智能体在SE领域的潜力与局限
  • RyTuneX(Win1011系统优化工具)
  • 【Triton 教程】triton_language.store
  • 智能喂食器:云计算赋能宠物科技
  • 机器人自主学习新技巧:强化学习的革命
  • SpringBoot中的SpEL:从入门到实战,这篇就够了
  • linux上面能对pdf注释嘛?推荐Okular,亲测好用
  • 2025年12月商超照明厂家推荐榜:商超照明/品牌/灯具/灯光/灯具制造商/源头厂家/生产厂家/灯具供应商、智能商超照明,上海富明阳照明凭专业实力领跑,赋能商业光环境 - 海棠依旧大
  • LuatOS平台下USB系统可靠性设计:硬件基础与开发进阶!
  • 基于正弦余弦算法-LSSVM的电涡流传感器温度补偿方法附Matlab代码
  • 聊聊 MySQL 那些你曾踩过的“坑”及隐藏的“坑”
  • 【vLLM 学习】Profiling