阻止 git 分支被推送

发布于 2024-11-19 08:50:54 字数 231 浏览 3 评论 0原文

情况是这样的:

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

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

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

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

Here's the situation:

I have a public repository for my open-source app on github.com. However, now I'd like to write some specific code that will not be public (I might use it in a commercial version of my application).

I figured I could use the same repository, and I'd create a "private" branch in my git repository that I wouldn't push.

But, mistakes happen. Is there some way to forbid git from ever pushing a branch to remote servers?

If there's a better way to handle this situation, I would of course welcome any suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

那一片橙海, 2024-11-26 08:50:54

以下是 pre-push 挂钩方法的工作原理,其中有一个名为 dontpushthis 的分支。

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

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

这是有效的,因为正在推送的引用列表是通过标准输入传递的。所以这也会捕获 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

这样,私有存储库工作目录就永远没有可以推送到的任何地方。从本质上讲,你有一个将公共信息转为私人信息的单向阀,但不能返回。

Here's how the pre-push hook approach works, with a branch called dontpushthis.

Create this file as .git/hooks/pre-push:

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

This works because the list of refs being pushed is passed on standard input. So this will also catch git push --all.

Make it executable.

Do this in every local repository.

When you try to push to that branch, you'll see:

$ 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'

Obviously this is as simple as it looks, and only prevents pushing the branch named "dontpushthis". So it's useful if you're trying to avoid directly pushing to an important branch, such as master.

If you're trying to solve the problem of preventing confidential information leaking, it might not be sufficient. For example, if you created a sub-branch from dontpushthis, that branch would not be detected. You'd need more sophisticated detection - you could look to see whether any of the commits on the "dontpushthis" branch were present on the current branch, for instance.

A safer solution

Looking at the question again, I think a better solution in this case would be:

  1. Have one repo which is public
  2. Clone that to a new working directory which is private
  3. Remove the remote (git remote rm origin) from that working directory.
  4. To merge public changes, just do git pull https://github.com/myproj/mypublicrepo

This way, the private repo working directory never has anywhere it could push to. You essentially have a one-way valve of public information to private, but not back.

梦幻之岛 2024-11-26 08:50:54

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

这是一个例子。

$ git clone [email protected]: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 [email protected]:user/repo.git
! [rejected]        secret -> secret (non-fast forward)
error: failed to push some refs to ‘[email protected]:user/repo.git’

A slightly hackish solution: Make a dummy branch on GitHub with the same name as your real branch, and make sure it would not be a fast forward merge. That way, the push operation will fail.

Here's an example.

$ git clone [email protected]: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

Now that the dummy branch is set up, we can recreate it locally to diverge from the one on 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"

Now if we accidentally try to push, it will fail with a non-fast forward merge error:

$ git push origin secret
To [email protected]:user/repo.git
! [rejected]        secret -> secret (non-fast forward)
error: failed to push some refs to ‘[email protected]:user/repo.git’
乱世争霸 2024-11-26 08:50:54

来自 @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

A touch up of the .git/hooks/pre-push script from @steve-bennett

#!/usr/bin/bash

branch_blocked=mine

if grep -q "$branch_blocked"; then
    echo "Branch '$branch_blocked' is blocked by yourself." >&2
    exit 1
fi
软糯酥胸 2024-11-26 08:50:54

为什么不简单地使用当前 git 版本提供的预推送示例呢?

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

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

步骤如下:

  • .git/hooks/pre-push 中创建一个文件,
  • 赋予其执行权限
  • 在其中添加以下脚本

    <前><代码>#!/bin/sh

    远程=“$1”
    网址=“$2”

    z40=0000000000000000000000000000000000000000

    IFS=''
    当读取 local_ref local_sha 远程_ref 远程_sha

    如果[“$local_sha”=$z40]
    然后
    # 处理删除

    别的
    如果[“$remote_sha”=$z40]
    然后
    # 新分支,检查所有提交
    范围=“$local_sha”
    别的
    # 更新现有分支,检查新提交
    范围=“$remote_sha..$local_sha”

    # 检查 WIP 提交
    commit=`git rev-list -n 1 --grep '^PRIVATE:' "$range"`
    if [ -n "$commit" ]
    然后
    echo“错误:在 $local_ref 中找到私人提交。”
    echo "提交在 $range 范围内。"
    echo“不要推!”
    1号出口


    完毕

    出口0

    远程=“$1”
    网址=“$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 将此脚本修改为仅考虑一个禁止的遥控器。但在这种情况下,不要忘记在允许接收此分支的所有存储库中复制此挂钩。

Why not simply use the example of pre-push provided with current git version?

The idea is to begin the commit message of the first commit of your private branch with the word PRIVATE:.

After setting the pre-push script, for every push it checks the commit messages of all the log of pushed refs. If they start with PRIVATE:, the push will be blocked.

Here are the steps:

  • Create a file in .git/hooks/pre-push
  • Give it execution rights
  • Past the following script in it

    #!/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"
    

Example of failure

$ 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'

To make the branch pushable again, you can either remove the hook or, better, modify the commit message to remove the forbidden word.

This script can be modified to only consider one forbidden remote by checking remote_ref. But in that case, do not forget to copy this hook in all the repos allowed to receive this branch.

瀟灑尐姊 2024-11-26 08:50:54

如果您使用 GitHub,则可以在 GitHub 上创建一个与您的分支同名的分支。不需要向它推送任何提交,只需在 master 或其他任何地方创建一个空分支(您可以在 GitHub 界面中通过在“branch”弹出窗口中输入分支并单击 createbranch)。

然后,转到存储库的分支设置(例如,https://github.com///settings/branches/)并为您的分支启用分支保护。请务必选中所有复选框,特别是需要评论或状态复选框,这不允许直接推送分支(必须从拉取请求推送),并且还要确保选中包含的复选框管理员。

那么GitHub将不允许你推送到分支,即使你使用-f。您会收到类似这样的消息

$ 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 '[email protected]:<user>/<repo>.git'

If you use GitHub, you can create a branch on GitHub with the same name as your branch. There is no need to push any commits to it, just make an empty branch off master or whatever (you can do it in the GitHub interface by typing the branch in the "branch" popdown and clicking create branch <branch-name>).

Then, go to the branch settings for the repository (e.g., https://github.com/<user>/<repo>/settings/branches/<branch-name>) and enable branch protection for your branch. Be sure to check all the boxes, particularly, the require reviews or status checks boxes, which disallows the branch from being pushed to directly (it would have to be pushed from a pull request), and also be sure to check the box to include administrators.

Then GitHub will not allow you to push to the branch, even if you use -f. You'll get a message like

$ 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 '[email protected]:<user>/<repo>.git'
终难遇 2024-11-26 08:50:54

有多种解决方案:

  1. 非技术性的,只需将您的分支的许可证调整为商业许可证
  2. 在 github 上创建一个包含您的 fork 的私有存储库
  3. 在服务器上创建一个 git-hook (据我所知,github 上不可能)
  4. git-push 防止使用 git Push 进行推送

There are multiple solutions:

  1. Non technical, just adjust the license to a commercial one for your branch
  2. Make a private repository on github which contains your fork
  3. Make a git-hook on the server (afaik not possible with github)
  4. Write an wrapper for git-push to prevent the push with git push
一梦等七年七年为一梦 2024-11-26 08:50:54

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

这样,如果您这样做:

git push origin

它将仅推送远程存储库上存在的分支。

创建分支后还要查看 .git/config(在本地存储库目录中)文件 - 您将看到每个本地分支都可以分配不同的远程存储库。您可以通过将此分支分配给单独的(私有)存储库来利用这一点,但这不是通用解决方案(如果明确订购,或通过命令 git push origin<,分支仍然可以推送到原始远程) /代码>)。

You can create a branch that does not exist in your remote repository.

That way if you just do:

git push origin

it will push only branches that exist on the remote repository.

Also look into .git/config (within the local repository directory) file after creating the branch - you will see that every local branch can have different remote repository assigned. You can take advantage of that by assigning this branch to separate (private) repository, but the is not the universal solution (the branch still can be pushed to origin remote, if explicitly ordered to, or by command git push origin).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文