情况如下:
我在github.com上有我的开源应用程序的公共存储库。但是,现在我想编写一些不公开的特定代码(我可能会在我的应用程序的商业版本中使用它)。
我想我可以使用相同的存储库,并且我会在我的git存储库中创建一个“私有”分支,我不会推送它。
但是,错误发生了。有没有办法禁止git将分支推送到远程服务器?
如果有更好的方法来处理这种情况,我当然欢迎任何建议。
答案 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"例如,分支出现在当前分支上。
再次看一下这个问题,我认为在这种情况下更好的解决方案是:
git remote rm origin
)。git pull https://github.com/myproj/mypublicrepo
这样,私人仓库工作目录永远不会有任何可以推送的目录。你基本上有私人的公共信息单向阀,但不能回来。
答案 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)
有多种解决方案:
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'