如何限制将特定分支合并到 Gitlab 中的其他分支?

Posted

技术标签:

【中文标题】如何限制将特定分支合并到 Gitlab 中的其他分支?【英文标题】:How to restrict merging specific branch into other branches in Gitlab? 【发布时间】:2019-04-06 11:45:12 【问题描述】:

有没有办法限制特定分支合并到其他分支?请允许我解释一下:

我在 Gitlab 中有一个“测试”分支和一个“主”分支。团队创建功能分支,将它们合并到“测试”以供批准,然后将功能分支合并到“主”(一旦获得批准)。

有时,某些功能可能需要几个月的时间才能获得批准,因此代码会在“测试”分支中停留一段时间。同时,另一个功能分支可能会尝试合并到“测试”中,并且会出现冲突。这是意料之中的,然而,我们只是人类,偶尔有人可能会在处理冲突时不小心将“测试”合并到他们的特性分支中,这显然是错误的。相反,我们应该切换到“测试”并将我们的功能分支合并到“测试”中,从而管理测试分支内的冲突。

感谢任何建议。

【问题讨论】:

【参考方案1】:

首先,请确保您的需求非常正常和传统。 答案是……是的。

如何防止从一个分支合并到另一个,设置服务器 Git Hook

这些是一些有用的链接:

Git Hook explanations 在 Git 官方手册中 GitLab server-side Hook explanations An example 使用 Ruby 编写的 Git Hook,以防止将“暂存”分支合并到“主”分支

为了帮助您(并且为了好玩 ^^),我在 Python 中编写了一个专门的钩子来满足您的特定需求(如果您想使用其他一些分支,您只需要调整 FORBIDDEN_SOURCE_BRANCH 和 FORBIDDEN_IF_NOT_DEST_BRANCH)。

#!/bin/python
##
## Author: Bertrand Benoit <mailto:contact@bertrand-benoit.net>
## Description: Git Hook (server-side) allowing to prevent merge from some branches to anothers
## Version: 0.9

import sys, subprocess, re

FORBIDDEN_SOURCE_BRANCH='testing'
FORBIDDEN_IF_NOT_DEST_BRANCH='master'

# Considers only merge commit.
if not (len(sys.argv) >=2 and sys.argv[2] == 'merge'):
    sys.exit(0)

# Defines which is the source branch.
with open(sys.argv[1], 'r') as f:
    mergeMessage=f.readline()
mergeBranchExtract=re.compile("Merge branch '([^']*)'.*$").search(mergeMessage)
if not mergeBranchExtract:
    print('Unable to extract branch to merge from message: ', mergeMessage)
    sys.exit(0) # Ensures normal merge as failback

# Checks if the merge (source) branch is one of those to check.
mergeBranch=mergeBranchExtract.group(1)
if mergeBranch != FORBIDDEN_SOURCE_BRANCH:
  sys.exit(0) # It is NOT the forbidden source branch, so keeps on normal merge

# Defines which is the current branch.
currentBranchFullName=subprocess.check_output(['git', 'symbolic-ref', 'HEAD'])
currentBranchExtract=re.compile("^.*/([^/]*)\n$").search(currentBranchFullName)
if not currentBranchExtract:
  print('Unable to extract current branch from: ', currentBranchFullName)
  sys.exit(1) # Ensures normal merge as failback

# Checks if the current (destination) branch is one of those to check.
currentBranch=currentBranchExtract.group(1)
if currentBranch != FORBIDDEN_IF_NOT_DEST_BRANCH:
  print("FORBIDDEN: Merging from '" + mergeBranch + "' to '" + currentBranch + "' is NOT allowed. Contact your administrator. Now, you should use git merge --abort and keep on your work.")
  sys.exit(1) # This is exactly the situation which is forbidden

# All is OK, so keeps on normal merge
sys.exit(0)

为了分享所有这些工作,我创建了一个新的Gitlab repository,我会在需要时添加更多的钩子:)

有关信息,您还可以设置受保护的分支以保护它们免受某些用户的影响

这是关于那个的complete documentation。

如果您需要进一步的帮助,请告诉我。

【讨论】:

但是我的印象是 OP 想要一种方法来防止合并 来自 一个特定的分支,而不是 to 一个特定的分支...... @RomainValeri 没错,我想阻止从特定分支合并。 我因此更新了我的答案以满足您的需求。 为了帮助你(也为了好玩^^),我用 Python 写了一个专门的钩子来满足你的特定需求。因此,我更新了我的答案。【参考方案2】:

所以,你希望你的 pre-receive 钩子拒绝的是任何包含当前 testing 提示的分支推送(如果有的话),除非推送到 testing 本身或 master。做起来几乎和说出来一样容易:

testtip=`git rev-parse testing`
[[ `git merge-base testing master` = $testtip ]] && exit 0    # okay if testing's merged

while read old new ref; do
        [[ $ref = refs/heads/* ]] || continue      # only care about branches
        [[ $new = *[^0]* ]] || continue            # not checking branch deletions
        [[ $ref = */master ]] && continue          # not checking pushes to master
        [[ $ref = */testing ]] && continue         # nor testing


        range=$new; [[ $old = *[^0]* ]] && range=$old..$new

        [[ `git rev-list --first-parent $range` != *$testtip* ]] \
        && [[ `git rev-list $range` = *$testtip* ]] \
        && 
                echo push to $ref merges from unmerged testing commits, rejecting push
                exit 1
        
done

编辑:哎呀,它拒绝任何基于测试的东西,而不仅仅是任何合并它的东西。固定。

【讨论】:

你能解释一下你的代码应该在哪里运行吗?对不起,我不认识这种语言,也不认识它的用法。看起来像 bash? @JulienRousé 这是一个预接收挂钩,是的,它是 bash。说git help hooks 谢谢,我会查一下

以上是关于如何限制将特定分支合并到 Gitlab 中的其他分支?的主要内容,如果未能解决你的问题,请参考以下文章

Python 操作Gitlab-API 实现批量的合并分支

Gitlab 无法将恢复的分支与另一个分支合并

如何将 gitlab 合并请求用作 npm 模块

如何防止 Gitlab 在分支合并上创建额外的合并提交

如何从 master 创建发布分支,不包括已经合并到 master 中的特定分支

将 GitLab 合并请求中的所有提交添加到 Upsource 审查