## 命名

gitnamespaces - Git 命名空间

## 概要

    GIT_NAMESPACE=<namespace> git upload-pack

    GIT_NAMESPACE=<namespace> git receive-pack

## 描述

Git 支持将单个存储库的引用划分为多个名称空间，每个名称空间都有自己的分支，标签和 HEAD 。Git 可以将每个名称空间公开为一个独立的存储库，以便在共享对象存储的同时从其中抽取和推送，并将所有参考文献公开给 git-gc [1] 等操作。

将多个存储库作为单个存储库的名称空间存储可避免存储相同对象的重复副本，例如存储同一个源的多个分支时。alternates 机制提供了类似的支持以避免重复，但是替代方法并不能防止添加到存储库的新对象之间的重复，而无需进行持续维护，而名称空间则可以。

要指定名称空间，请将`GIT_NAMESPACE`环境变量设置为名称空间。对于每个 ref 命名空间，Git 将相应的 ref 存储在一个目录下`refs/namespaces/`。例如，`GIT_NAMESPACE=foo`将存储参考下`refs/namespaces/foo/`。你也可以通过`--namespace` git [1] 选项指定命名空间。

请注意，包含`/`的命名空间将扩展到命名空间的层次结构; 例如，`GIT_NAMESPACE=foo/bar`将存储参考下`refs/namespaces/foo/refs/namespaces/bar/`。这使`GIT_NAMESPACE的`路径的行为具有层次性，因此使用克隆技术可以`GIT_NAMESPACE=foo/bar`产生与`GIT_NAMESPACE=foo`从该回购库克隆和克隆相同的结果`GIT_NAMESPACE=bar`。它还避免了奇怪的命名空间路径的歧义，例如`foo/refs/heads/`可能会在`refs`目录内产生目录/文件冲突。

git-upload-pack [1] 和 git-receive-pack [1] 按照指定的方式重写 refs 的名字`GIT_NAMESPACE`。git-upload-pack 和 git-receive-pack 会忽略指定命名空间之外的所有引用。

智能 HTTP 服务器 git-http-backend [1] 会将 GIT_NAMESPACE 传递给后端程序; 有关示例配置，请参阅 git-http-backend [1] 以将存储库名称空间公开为存储库。

对于简单的本地测试，您可以使用 git-remote-ext [1] ：

    git clone ext::'git --namespace=foo %s /tmp/prefixed.git'

## 安全

获取和推送协议并不旨在防止一方从另一个不想共享的存储库中窃取数据。如果您需要保护私密数据免受恶意对等攻击，则最佳选择是将其存储在另一个存储库中。这适用于客户端和服务器。特别是，服务器上的名称空间对读取访问控制无效; 您应该只向授予读取权限的客户端授予对整个存储库的读取访问权限。

已知的攻击媒介如下：

1. victim 发送 “have” 线广告其具有的对象的 ID，这些对象的 ID 没有明确地意图共享，但是如果对等方也拥有它们，则可用于优化传送。攻击者选择一个对象 ID X 来窃取并向X发送一个 ref，但不需要发送 X 的内容，因为受害者已经拥有了它。现在受害者认为攻击者拥有 X ，并且稍后将X的内容发送回攻击者。（这种攻击对于客户端来说在服务器上执行起来是最直接的，通过在客户端有权访问的命名空间中创建对 X 的引用，然后获取它，服务器在客户端上执行它的最可能方式是“合并“ X 到一个公共分支，并希望用户在这个分支上做额外的工作，并将其推回服务器而不会注意到合并。）

2. 和＃1一样，攻击者选择一个对象 ID X 来窃取。被攻击者发送给攻击者已经拥有的对象 Y，并且攻击者错误地声称具有 X 而不是 Y ，所以被攻击者发送 Y 作为与 X 相对的三角点。该三角点揭示 X 与攻击者类似的 X 的区域。