【问题标题】:Git: Set up a fetch-only remote?Git:设置一个仅获取的遥控器?
【发布时间】:2011-11-25 05:59:58
【问题描述】:

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

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

对于指向同行开发人员的远程,无需推送,Git 无论如何都会拒绝推送到非裸存储库。有没有办法将这些遥控器配置为“仅获取”而没有推送地址或功能?

【问题讨论】:

  • @sehe,不,你不能。如果未指定推送 URL,则推送将使用获取 URL。

标签: git workflow


【解决方案1】:

我认为你不能删除推送 URL,你只能覆盖它是拉 URL 以外的东西。所以我认为你会得到最接近的是这样的:

$ 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 remote set-url --delete --push .*”可以解决问题,但如果你删除推送 url,那么它会默认返回获取 url。
  • 我个人更喜欢使用像“DISALLOWED”这样的东西,更明显。但这只是口味问题。
  • @Pierre-OlivierVares 'DONTPUSH' 怎么样?! :)
  • 仅供参考,执行此操作后,您的 git 配置文件应如下所示:(注意新的 pushurl 选项)[remote "origin"] fetch = +refs/heads/* :refs/remotes/origin/* url = ssh://host/path/to/repo pushurl = ssh://host/no-pushing/repo
  • 与@Pierre-OlivierVares 类似,我选择了git remote set-url --push origin -- --read-only--——注意额外的-- 允许名称带有前导破折号。这对我来说更具可读性。
【解决方案2】:

除了将推送 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 打印一条消息,说明推送已被禁用。

【讨论】:

  • 好主意!如果没有更复杂的脚本,您将禁用所有遥控器的推送。
  • @v01pe 是的。我已更新答案以包含示例脚本。过滤推送到单个分支并不需要太多。一个 shell oneliner 就可以了。
  • 更好更优雅的方式
【解决方案3】:

“Git 将拒绝推送到非裸存储库”的一般说法是不正确的。如果您尝试推送与远程存储库的签出工作目录位于同一分支上的更改,Git 只会拒绝推送到非裸远程存储库。

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

(我将其添加为答案,因为我还没有足够的声誉来添加 cmets)

【讨论】:

  • 根据定义,裸存储库没有签出的工作目录。你可以推送到它上面的特定分支。,
【解决方案4】:

如果您已经设置了远程,并且只是想防止自己执行诸如意外直接推送到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

【讨论】:

    【解决方案5】:

    如果您可以控制存储库,则可以通过使用权限来实现。获取存储库的用户不应拥有主存储库的写入权限。

    【讨论】:

    • 如果您无法修改文件,也无法获取新的更改。
    猜你喜欢
    • 1970-01-01
    • 2014-10-28
    • 2014-12-09
    • 2017-08-18
    • 2012-10-14
    • 1970-01-01
    • 2016-11-08
    • 2012-08-01
    • 2014-08-11
    相关资源
    最近更新 更多