阻止git分支被推送

时间:2011-07-10 23:06:09

标签: git branch private

情况如下:

我在github.com上有我的开源应用程序的公共存储库。但是,现在我想编写一些不公开的特定代码(我可能会在我的应用程序的商业版本中使用它)。

我想我可以使用相同的存储库,并且我会在我的git存储库中创建一个“私有”分支,我不会推送它。

但是,错误发生了。有没有办法禁止git将分支推送到远程服务器?

如果有更好的方法来处理这种情况,我当然欢迎任何建议。

7 个答案:

答案 0 :(得分:30)

以下是pre-push挂钩方法的工作方式,以及名为dontpushthis的分支。

将此文件创建为.git/hooks/pre-push

if [[ `grep 'dontpushthis'` ]]; then 
  echo "You really don't want to push this branch. Aborting."
  exit 1
fi

这是有效的,因为推送的ref列表是在标准输入上传递的。所以这也会抓住git push --all

让它可执行。

在每个本地存储库中执行此操作。

当你试图推进那个分支时,你会看到:

$ git checkout dontpushthis
$ git push
You really don't want to push this branch. Aborting.
error: failed to push some refs to 'https://github.com/stevage/test.git'

显然,这看起来很简单,只能阻止推动名为" dontpushthis"的分支。因此,如果您试图避免直接推送到重要分支,例如master,那么它很有用。

如果您正在尝试解决防止机密信息泄露的问题,则可能还不够。例如,如果您从dontpushthis创建了一个子分支,则不会检测到该分支。您需要更复杂的检测 - 您可以查看是否有任何提交在" dontpushthis"例如,分支出现在当前分支上。

更安全的解决方案

再次看一下这个问题,我认为在这种情况下更好的解决方案是:

  1. 有一个公开的回购
  2. 将其克隆到私有的新工作目录
  3. 从该工作目录中删除远程(git remote rm origin)。
  4. 要合并公开更改,只需执行git pull https://github.com/myproj/mypublicrepo
  5. 即可

    这样,私人仓库工作目录永远不会有任何可以推送的目录。你基本上有私人的公共信息单向阀,但不能回来。

答案 1 :(得分:27)

一个稍微破解的解决方案:在GitHub上创建一个与真实分支同名的虚拟分支,并确保它不是快进合并。这样,推送操作就会失败。

这是一个例子。

$ git clone git@github.com:user/repo.git
$ cd repo
$ git checkout -b secret
$ echo "This is just a dummy to prevent fast-forward merges" > dummy.txt
$ git add .
$ git commit -m "Dummy"
$ git push origin secret

现在已经设置了虚拟分支,我们可以在本地重新创建它以与GitHub上的那个分开。

$ git checkout master
$ git branch -D secret
$ git checkout -b secret
$ echo "This diverges from the GitHub branch" > new-stuff.txt
$ git add .
$ git commit -m "New stuff"

现在,如果我们不小心尝试推送,它将因非快速合并错误而失败:

$ git push origin secret
To git@github.com:user/repo.git
! [rejected]        secret -> secret (non-fast forward)
error: failed to push some refs to ‘git@github.com:user/repo.git’

答案 2 :(得分:4)

点击@ steve-bennett的.git / hooks / pre-push脚本

    #!/usr/bin/bash

    branch_blocked=mine

    if grep -q "$branch_blocked"; then
        echo "Branch '$branch_blocked' is blocked by yourself." >&2
        exit 1
    fi

答案 3 :(得分:3)

为什么不简单地使用当前git版本提供的pre-push示例?

我们的想法是使用单词PRIVATE:开始私有分支的第一次提交的提交消息。

设置推送前脚本后,每次推送都会检查推送引用的所有日志的提交消息。如果他们以PRIVATE:开头,则推送将被阻止。

以下是步骤:

  • .git/hooks/pre-push
  • 中创建文件
  • 授予执行权
  • 通过以下脚本

    #!/bin/sh
    
    remote="$1"
    url="$2"
    
    z40=0000000000000000000000000000000000000000
    
    IFS=' '
    while read local_ref local_sha remote_ref remote_sha
    do
            if [ "$local_sha" = $z40 ]
            then
                    # Handle delete
                    :
            else
                    if [ "$remote_sha" = $z40 ]
                    then
                            # New branch, examine all commits
                            range="$local_sha"
                    else
                            # Update to existing branch, examine new commits
                            range="$remote_sha..$local_sha"
                    fi
    
                    # Check for WIP commit
                    commit=`git rev-list -n 1 --grep '^PRIVATE:' "$range"`
                    if [ -n "$commit" ]
                    then
                            echo "Error: Found PRIVATE commit in $local_ref."
                            echo "The commit is in the range $range."
                            echo "NOT pushing!"
                            exit 1
                    fi
            fi
    done
    
    exit 0
    
    remote="$1"
    url="$2"
    

失败的例子

$ git push origin private/old-kalman-filter 
Found PRIVATE commit in refs/heads/myforbiddenbranch, the commit is in the range 
a15c7948676af80c95b96430e4240d53ff783455. NOT PUSHING!
error: failed to push some refs to 'remote:/path/to/remote/repo'

要使分支再次推送,您可以删除钩子,或者更好地修改提交消息以删除禁用词。

通过选中remote_ref,可以修改此脚本以仅考虑一个禁用的远程。但在这种情况下,不要忘记在允许接收此分支的所有存储库中复制此挂钩。

答案 4 :(得分:2)

有多种解决方案:

  1. 非技术性,只需将许可证调整为您的分支机构的商业许可证
  2. 在github上创建一个包含fork
  3. 的私有存储库
  4. 在服务器上创建一个git-hook(github无法实现)
  5. git-push编写一个包装,以防止使用git push推送

答案 5 :(得分:2)

您可以创建远程存储库中不存在的分支。

如果你这样做的话:

git push origin

它只会推送远程存储库中存在的分支。

在创建分支后,还要查看.git/config(在本地存储库目录中)文件 - 您将看到每个本地分支可以分配不同的远程存储库。您可以通过将此分支分配给单独的(私有)存储库来利用它,但这不是通用解决方案(分支仍然可以推送到源远程,如果显式地命令,或者通过命令git push origin)。

答案 6 :(得分:0)

如果使用GitHub,则可以在GitHub上创建与分支同名的分支。无需向其提交任何提交,只需在master或其他任何东西上创建一个空分支(您可以在GitHub界面中,通过在“分支”弹出框中键入分支并单击create branch <branch-name>来完成此操作)。

然后,转到存储库的分支设置(例如https://github.com/<user>/<repo>/settings/branches/<branch-name>)并为分支启用分支保护。确保选中所有复选框,尤其是“要求审阅”或“状态”复选框,这不允许将分支直接推入(必须从拉取请求中将其推入),还请确保选中该复选框以包括管理员。

然后,即使您使用-f,GitHub也不允许您推送到分支。您会收到类似

的消息
$ git push -f origin private
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 981 bytes | 981.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/private.
remote: error: At least 1 approving review is required by reviewers with write access.
To github.com:<user>/<repo>.git
 ! [remote rejected] private -> private (protected branch hook declined)
error: failed to push some refs to 'git@github.com:<user>/<repo>.git'