您的问题面向 Git Pro 书籍的讨论,从技术上讲,这实际上主要涉及我认为应该称为 transsports 而不是协议的内容。 Git Pro 书没有涉及这种区别(至少在我写这个答案的时候);当前的 Git 文档也没有。但是Git 2.18 has introduced a new wire protocol(启用代码首先出现在Git 2.16),所以我认为这需要另一个答案来解决这个问题。
特别是,Git 有一个坏习惯,将 authentication、permissions、transsports(在“传输层”的意义上网络堆栈)和 protocol(Git 用于 Git 到 Web 服务器或点对点通信的协议)。到目前为止,这一直适用于 Git,因为:
- 本地(
file:// 或原始路径名)说明符导致使用本地方法,这些方法不进行身份验证并依赖于操作系统权限。1 由于您的 Git 只是在自言自语,因此它只是必须同意自己对自己说的话。
-
http:// 和 https:// 说明符使用 libcurl 和外部身份验证器进行身份验证(如果他们这样做的话)。2 之后,它们依赖于操作系统权限。因为 Git 与 Web 服务器通信,它必须通过服务器的 REST 接口走私自己的协议。同时网络服务器本身提供传输协议。
-
ssh:// 说明符使用 ssh(通常来自操作系统提供的库)进行身份验证和传输。3 另一端的操作系统在正常情况下提供任何权限检查。 (Gitolite 和 GitHub-ssh-access 等特殊情况在幕后使用了其他技巧,所有这些都超出了 Git 的权限。)
-
git:// 说明符使用 TCP 上的轻量级协议作为传输协议。它不进行身份验证,也没有权限检查。它是纯只读的:它不需要任何东西来控制谁可以推送,因为没有人可以推送。4
在 Git 2.16 之前,实际上只有一个 Git 有线协议。 (所谓的“哑协议”是特定于使用 Web 服务器的,即使那样,也只有当它们无法运行真正的协议时。哑协议实际上相当于能够从 Web 服务器下载单个文件——仅此而已!)然而,在 Git 2.16 中,Git 学会了请求特定协议版本的能力。
因此,现有的智能协议成为 Git 协议版本零。 Git 协议版本 1 立即被定义为做同样的事情,因此可以在不添加任何其他内容的情况下测试协议版本选择代码。
然而,在 Git 2.18 中,现在有一个协议版本 2。协议 2 仍在定义中,但它具有的第一个可能也是最有用的(至少对某些人来说)技巧是能够列出更少的引用。例如,连接到具有许多标签的大型旧 Git 存储库会产生大量带宽浪费。 the Google blog page here有很多好的细节。
目前,这种协议编号仍主要针对 Git 开发人员,但很可能很快就会变得重要。
1值得一提的是,POSIX 系统(Linux、各种 BSD 等)上的操作系统权限允许 user、group 和其他权限。这里的“user”表示运行各种命令的人的数字用户ID,“group”表示数字组ID,“other”表示不首先匹配“user”或“group”的任何人。也就是说,实际的权限取决于这三个中的哪一个首先匹配当前用户的ID。
虽然不像完整的 ACL 那样花哨,但 Git 利用这些权限让操作系统同时处理本地(同一主机)和远程(任何网络传输)权限检查。具体来说,您可以将core.sharedRepository 配置为group 或all 或连接到特定的POSIX umask 值。详情请见the git config documentation。
2注意https:// 可以使用 SSL/TLS 并进行加密数据交换。也就是说,REST 操作,以及一旦 Git 通过 Git 将使用的任何协议连接后发送的所有数据,都对中间站点保密,假设没有人破坏加密。 Git 中有许多配置旋钮提供给 libcurl(尽管由 libcurl 来使用它们)。查看git config 中的所有http.* 设置。 SSL 安全性很复杂;请参阅脚注 3 中的链接。
3SSH 传输采用 SSL/TLS 加密,但细节有所不同。更多信息,请参阅Difference between SSH and SSL, especially in terms of "SFTP" vs. "FTP over SSL"。
4作为kostix noted in a comment,您可以启用推送git:// 传输。这对我来说似乎是一个非常糟糕的主意,正是因为没有身份验证和权限检查。请注意,操作系统级别的权限检查实际上是短路的,因为服务 git:// 请求的 Git 守护进程作为一个特定的用户 ID 运行,通常是 git-daemon 的用户 ID。