防止在GitHub上推送到主分支(master)?

267

GitHub允许您配置您的存储库,以便用户无法强制推送到主分支,但是否有一种方法可以完全防止向主分支推送?我希望使其仅通过GitHub拉取请求UI添加提交到主分支。


2
仓库设置 -> 分支限制。但您需要支付团队账户费用。 - Ben Racicot
8个回答

210

自从最初的提问/回答后,Github已经为受限分支UI添加了一个新选项,允许您设置这个功能。

要求在合并之前进行拉取请求审查启用后,所有提交必须在非受保护分支上完成,并通过具有所需数量的批准审查和不需要更改的拉取请求提交,然后才能合并到符合此规则的分支中。

要找到它,请转到“设置”>“分支”>“分支保护规则”,然后单击“添加规则”。 Github UI after following instructions 然后,输入您想要保护的分支名称,并单击复选框以要求在合并之前进行拉取请求审查。 Github UI with the button to click 默认情况下,这仅会阻止非管理员的人。稍后还有另一个复选框,用于确保即使管理员也无法合并。 Github UI with the other button to click


147
这会在合并时强制进行审查,但不会阻止直接提交和推送到主分支。至少对于我的仓库是这样。 - Damien
29
@Damien,你是否设置了“包括管理员”标志?如果没有,你应该仍然能够直接推送到主分支。或者,你可以尝试以非管理员权限的不同用户身份进行推送测试。 - Cerno
17
如果我不想要求评审,我只想要合并拉取请求到主分支。我不关心拉取请求的状态。 - Michał Pietraszko
4
受保护的分支仅适用于私有存储库的专业版、团队版和企业版用户,而非免费用户。 - Movahhedi
15
看起来现在的选项被称为“不允许绕过上述设置”。 - l0b0
显示剩余4条评论

144
当前被接受的答案实际上是正确的,但如果您是组织所有者或具有管理权限,即如果您创建了存储库,则仍然可以推送到受保护的分支。根据Github文档:https://help.github.com/en/articles/about-branch-restrictions

组织所有者和拥有存储库管理权限的人始终可以推送到受保护的分支。

对于任何其他类型的协作者,“git push”将失败。
如果您真的想完全禁用推送,则必须在本地进行设置,方法是配置分支的无效pushRemote,如上所述: git config branch.master.pushRemote no_push 或者创建一个pre-push挂钩,如此处所示:https://gist.github.com/vlucas/8009a5edadf8d0ff7430

另一个预推钩子的原理相同:https://github.com/219-design/git_templatedir/blob/master/hooks/pre-push - pestophagous
3
必须提到的是,pushRemote 的方式仅适用于在终端使用 git 命令推送时,如果像我一样使用 IntelliJ 进行推送,则仍然有效。 - ZhengguanLi

21

当启用状态检查时,直接推送到远程主分支会被拒绝,这意味着将提交添加到远程主分支的唯一方法是在 GitHub 上合并通过状态检查的拉取请求。

以下是我进行的需要状态检查的主分支实验结果:

  1. 在我的PC上创建了一个提交。
  2. 将其推送到远程主分支。
  3. 出现拒绝消息。最终未将提交推送到远程。
C:\GitRepo\GitHub\TomoyukiAota\photo-location-map [master ↑1]> git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote: error: GH006: Protected branch update failed for refs/heads/master.
remote: error: 3 of 3 required status checks are expected.
To https://github.com/TomoyukiAota/photo-location-map.git
 ! [remote rejected] master -> master (protected branch hook declined)
error: failed to push some refs to 'https://github.com/TomoyukiAota/photo-location-map.git'
C:\GitRepo\GitHub\TomoyukiAota\photo-location-map [master ↑1]>

5
启用“包括管理员”功能后,我作为仓库管理员可以正常运作。 - Robert K. Bell

13
如果您在Github的私有仓库中使用免费计划,则可能无法使用受保护的分支功能。因此,您需要阻止从本地进行任何推送/提交。 这是我为了使其在本地工作并分发到所有仓库成员所做的事情。 首先,您需要安装husky来控制pre-commit和pre-push挂钩。 然后,我创建了一个pre-push bash脚本并将其提交到仓库中。然后使用husky参数从husky pre-push钩子调用此脚本。 这是我的husky配置在`package.json`内部(如果需要,您可以设置单独的配置)。
"husky": {
    "hooks": {
        "pre-commit": "./commands/pre-commit",
        "pre-push": "./commands/pre-push $HUSKY_GIT_STDIN"
    }
},

正如您所看到的,我有两个脚本,一个用于 pre-push ,另一个用于 pre-commit。

这是我的 commands/pre-push bash 脚本。

#!/bin/bash

echo -e "===\n>> Talenavi Pre-push Hook: Checking branch name / Mengecek nama branch..."

BRANCH=`git rev-parse --abbrev-ref HEAD`
PROTECTED_BRANCHES="^(master|develop)"

if [[ $1 != *"$BRANCH"* ]]
then
  echo -e "\n You must use (git push origin $BRANCH) / Anda harus menggunakan (git push origin $BRANCH).\n" && exit 1
fi

if [[ "$BRANCH" =~ $PROTECTED_BRANCHES ]]
then
  echo -e "\n Cannot push to remote $BRANCH branch, please create your own branch and use PR."
  echo -e " Tidak bisa push ke remote branch $BRANCH, silahkan buat branch kamu sendiri dan gunakan pull request.\n" && exit 1
fi

echo -e ">> Finish checking branch name / Selesai mengecek nama branch.\n==="

exit 0
这个脚本基本上会做两件事情:
  • 阻止任何人(包括我自己)直接向masterdevelop分支推送,他们需要在自己的分支上工作,然后创建拉取请求。
  • 阻止任何试图推送到与其当前活动分支不同的分支的人。例如,您在fix/someissue分支中,但是您错误地键入git push origin master
更详细的说明,请参考此文章:https://github.com/talenavi/husky-precommit-prepush-githooks

11

我希望能够让在GitHub拉取请求界面中添加提交成为将改动推送到主分支的唯一方式。

我有一个解决方案,可以防止将更改推送到主分支,而不需要批准或通过拉取请求中的长状态检查。

关键是创建一个立即通过的状态检查。

.github/workflows/requirePullRequest.yml中创建以下GitHub操作。

name: require pull request

on:
  pull_request:
    branches:
      - master

jobs:
  job:
    name: require pull request
    runs-on: ubuntu-latest
    steps:
      - run: echo hello

接下来,更新存储库设置以要求要求拉取请求状态检查通过。

如果你希望管理员遵循相同的规则,那么你必须勾选包括管理员规则。

这样,GitHub将拒绝所有对主分支的直接推送,并且拉取请求不会被任何事情延迟。


2
非付费用户请注意:这是Github的高级功能,位于“设置>分支”下。如果您没有付费版的Github,则可能不是您想要的解决方案。 - acenturyandabit

10

我需要避免意外推送到主分支的任何提交。 这是一个类似@christian-chandra的解决方案,但更简单。

进入您的本地工作副本并

$ cd .git/hooks
echo '' > pre-commit
$ chmod +x pre-commit

将这个内容添加到文件(pre-commit)中。
#!/bin/sh

branch="$(git rev-parse --abbrev-ref HEAD)"

if [ "$branch" = "master" ]; then
  echo "Master Branch commit is blocked"
  exit 1
fi

完成!


2
这对于意外推送很有用,但是可以通过从.git目录中删除钩子来轻松绕过它。 - htafoya

10
你可以启用分支限制并决定允许哪些用户和组织团队进行推送。

https://help.github.com/articles/about-branch-restrictions/

注意:如果选中了“包括管理员”,并且您已在分支上启用了所需的状态检查,并且它们失败,则无论用户或团队的权限状态如何,任何尝试将更改推送到基本分支的尝试都将失败。


21
在Github界面上,是否可能防止本地推送到远程,并仅接受通过Pull-Request进行合并? - MarvHock
13
为了防止在本地推送到主分支,你可以将以下内容添加到你的git配置文件中:git config branch.master.pushRemote no_push - Nikhita Raghunath
@marvhock,现在已经可以实现了(刚刚添加了一个答案)。 - Cory

2
如果您正在使用Node,可以使用husky创建一个预推送验证,以防止直接推送到主分支。这样,您仍然可以使用管理员权限合并PR。我想其他语言也有类似的解决方案。
  1. npm install husky --save-dev
  2. /.huskyrc.js 文件中:
const preventPushToMaster = `branch=\`git symbolic-ref HEAD\`
if [ "$branch" = "refs/heads/master" ]; then
    echo "\\033[31mDirect push to master is not allowed.\\033[0m"
    exit 1
fi`;

module.exports = {
  hooks: {
    'pre-push': preventPushToMaster,
  },
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接