Git: 设置一个只能 fetch 的远程仓库?

当我在一个配置了远程的 Git 存储库中运行 git remote -v时,我发现每个远程都有提取和推送规范:

$ git remote -v
 ssh://host/path/to/repo (fetch)
 ssh://host/path/to/repo (push)

对于指向同类开发人员的远程服务器,不需要推送,而且 Git 无论如何都会拒绝推送到非空的代码仓库。有没有办法将这些远程配置为没有推送地址或者“只能 fetch”?

37664 次浏览

我不认为你可以 移除推送的远端地址,你只能用其他的拉取地址来 覆盖它。所以我认为最接近的方法是这样的:

$ git remote set-url --push origin no-pushing
$ git push
fatal: 'no-pushing' does not appear to be a git repository
fatal: The remote end hung up unexpectedly

你正在将推送 URL 设置为 no-pushing,只要你的工作目录中没有相同名称的文件夹,git 就无法找到它。您实际上是强制 git 使用一个不存在的位置。

“ Git 将拒绝推送到非空仓库”的说法是不正确的。只有当您试图将与远程存储库的 check out 工作目录位于同一个分支上的更改推送到非空的远程存储库时,Git 才会拒绝推送。

这个答案给出了一个简单的解释: https://stackoverflow.com/a/2933656/1866402

(我添加这个作为一个答案,因为我还没有足够的声誉添加评论)

如果您对存储库有控制权,那么可以通过使用权限来实现这一点。获取存储库的用户不应该拥有对主存储库的写权限。

除了将推送 URL 更改为无效(例如,git remote set-url --push origin DISABLED)之外,还可以使用 pre-push挂钩。

阻止 git push的一个快速方法是将 /usr/bin/false符号链接为钩子:

$ ln -s /usr/bin/false .git/hooks/pre-push
$ git push
error: failed to push some refs to '...'

如果需要的话,使用钩子可以对推力进行更细粒度的控制。有关如何防止推动正在进行的提交的示例,请参见 .git/hooks/pre-push.sample

为了防止向某个特定的树枝推进,或者限制向单个树枝推进,在一个例子中,钩子是这样的:

$ cat .git/hooks/pre-push
#!/usr/bin/sh


# An example hook script to limit pushing to a single remote.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If this script exits with a non-zero status nothing will be pushed.


remote="$1"
url="$2"


[[ "$remote" == "origin" ]]

带有多个遥控器的测试回收:

$ git remote -v
origin  ../gitorigin (fetch)
origin  ../gitorigin (push)
upstream        ../gitupstream (fetch)
upstream        ../gitupstream (push)

允许推到 origin:

$ git push origin
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 222 bytes | 222.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../gitorigin
* [new branch]      master -> master

不允许推到任何其他远程:

$ git push upstream
error: failed to push some refs to '../gitupstream'

请注意,可以修改 pre-push钩子脚本,以便在其他方面向 stderr 打印一条消息,说明推送已被禁用。

如果您已经有一个远程设置,只是想防止自己做一些事情,如意外推直接到 masterrelease/production,您可以防止这一点使用 git config

# prevent pushing to branch: master
$ git config branch.master.pushRemote no_push


# prevent pushing to branch: release/production
$ git config branch.release/production.pushRemote no_push

郑重声明,no_push不是一个特殊的名称。只是一个不存在的分支机构的名字。所以你可以使用 $ git config branch.master.pushRemote create_a_pr_and_do_not_push_directly_to_master,它会工作得很好。

更多信息: Git-config pushRemote