2.Git 基础

admin 7720 2026-02-14 02:01:38

至此,你应该已经能够完成大部分日常 Git 任务。但是,若要进行任何 Git 协作,你需要有一个远程 Git 仓库。虽然你可以在技术上向个人仓库推送更改并从中拉取更改,但这样做是不被鼓励的,因为如果你不小心,你很容易混淆他们的工作。此外,你希望你的协作者即使你的计算机离线也能访问仓库——拥有一个更可靠的公共仓库通常很有用。因此,与某人协作的首选方法是设置一个你们都可以访问的中间仓库,并从中进行推送和拉取。

运行 Git 服务器相当简单。首先,你选择服务器要支持的协议。本章的第一部分将介绍可用的协议及其优缺点。接下来的部分将解释使用这些协议的一些典型设置以及如何让你的服务器使用它们运行。最后,我们将介绍一些托管选项,如果你不介意将代码托管在别人的服务器上并且不想经历设置和维护自己服务器的麻烦。

如果你无意运行自己的服务器,可以跳到本章的最后一节,查看一些设置托管帐户的选项,然后转到下一章,我们将讨论在分布式源代码控制环境中工作的各种细节。

远程仓库通常是一个裸仓库——一个没有工作目录的 Git 仓库。由于该仓库仅用作协作点,因此没有理由在磁盘上检出一个快照;它只是 Git 数据。最简单的说,裸仓库是你项目 `.git` 目录的内容,仅此而已。

协议

Git 可以使用四种不同的协议来传输数据:本地(Local)、HTTP、安全外壳(SSH)和 Git。在这里,我们将讨论它们是什么以及在何种基本情况下你想要(或不想要)使用它们。

本地协议

最基本的是本地协议,其中远程仓库位于同一主机上的另一个目录中。如果你的团队中的每个人都可以访问共享文件系统(例如 NFS 挂载),或者在不太可能的情况下,每个人都登录到同一台计算机,则通常会使用此方法。后一种情况并不理想,因为你所有的代码仓库实例都将驻留在同一台计算机上,从而使灾难性损失的可能性大大增加。

如果你有一个共享的挂载文件系统,那么你可以从基于文件的本地仓库克隆、推送和拉取。要克隆这样的仓库,或者将其作为远程添加到现有项目中,请使用仓库的路径作为 URL。例如,要克隆本地仓库,你可以运行如下命令

$ git clone /srv/git/project.git

或者你可以这样做

$ git clone file:///srv/git/project.git

如果你在 URL 开头明确指定 `file://`,Git 的操作会略有不同。如果你只指定路径,Git 会尝试使用硬链接或直接复制它需要的文件。如果你指定 `file://`,Git 会启动它通常用于通过网络传输数据的进程,这通常效率低下得多。指定 `file://` 前缀的主要原因是如果你想要一个干净的仓库副本,其中不包含多余的引用或对象——通常是在从另一个 VCS 导入或类似情况之后(有关维护任务,请参阅Git 内部原理)。我们在这里使用普通路径,因为这样做几乎总是更快。

要将本地仓库添加到现有的 Git 项目中,你可以运行如下命令

$ git remote add local_proj /srv/git/project.git

然后,你可以通过新的远程名称 `local_proj` 向该远程推送和从中拉取,就像通过网络进行一样。

优点

基于文件的仓库的优点是它们简单,并且使用现有的文件权限和网络访问。如果你已经有一个整个团队都可以访问的共享文件系统,那么设置仓库非常容易。你将裸仓库副本放在每个人都可以共享访问的地方,并像设置任何其他共享目录一样设置读/写权限。我们将在在服务器上获取 Git 中讨论如何为此目的导出裸仓库副本。

这也是从别人的工作仓库快速获取工作的好选择。如果你和同事正在处理同一个项目,并且他们希望你检查一些东西,那么运行 `git pull /home/john/project` 这样的命令通常比他们推送到远程服务器然后你从中获取更容易。

缺点

这种方法的缺点是,与基本的网络访问相比,共享访问通常更难以设置和从多个位置访问。如果你在家时想从笔记本电脑推送,你必须挂载远程磁盘,这与基于网络的访问相比可能很困难且缓慢。

值得一提的是,如果你使用某种共享挂载,这不一定是速度最快的选项。只有当你对数据具有快速访问权限时,本地仓库才快。NFS 上的仓库通常比同一服务器上通过 SSH 的仓库慢,因为 Git 允许在每个系统上运行本地磁盘。

最后,此协议不保护仓库免受意外损坏。每个用户对“远程”目录都具有完整的 shell 访问权限,并且没有任何东西可以阻止他们更改或删除内部 Git 文件并损坏仓库。

HTTP 协议

Git 可以通过两种不同的模式通过 HTTP 进行通信。在 Git 1.6.6 之前,只有一种方式可以做到这一点,这种方式非常简单,通常是只读的。在 1.6.6 版本中,引入了一种新的、更智能的协议,它涉及 Git 能够以类似于通过 SSH 的方式智能地协商数据传输。在过去的几年中,这种新的 HTTP 协议变得非常流行,因为它对用户来说更简单,并且在通信方式上更智能。较新的版本通常被称为智能 HTTP 协议,而旧的方式被称为哑 HTTP。我们首先介绍较新的智能 HTTP 协议。

智能 HTTP

智能 HTTP 的操作与 SSH 或 Git 协议非常相似,但它通过标准 HTTPS 端口运行,并且可以使用各种 HTTP 认证机制,这意味着它通常比 SSH 更易于用户使用,因为你可以使用用户名/密码认证等方式,而不必设置 SSH 密钥。

它现在可能已成为使用 Git 最流行的方式,因为它可以配置为像 `git://` 协议一样匿名服务,也可以通过认证和加密像 SSH 协议一样进行推送。你不再需要为这些事情设置不同的 URL,现在可以使用一个 URL 进行两者。如果你尝试推送并且仓库需要认证(通常是这样),服务器可以提示输入用户名和密码。读取访问也是如此。

事实上,对于 GitHub 等服务,你用于在线查看仓库的 URL(例如,https://github.com/schacon/simplegit)与你可以用于克隆的 URL 相同,如果你有权限,也可以通过它进行推送。

哑 HTTP

如果服务器不响应 Git HTTP 智能服务,Git 客户端将尝试回退到更简单的哑 HTTP 协议。哑协议期望裸 Git 仓库像普通文件一样从 Web 服务器提供。哑 HTTP 的优点在于其设置的简单性。基本上,你所要做的就是将一个裸 Git 仓库放在 HTTP 文档根目录下,并设置一个特定的 `post-update` 钩子,然后就完成了(请参阅Git 钩子)。此时,任何能够访问你放置仓库的 Web 服务器的人都可以克隆你的仓库。要允许通过 HTTP 对你的仓库进行读取访问,请执行以下操作

$ cd /var/www/htdocs/

$ git clone --bare /path/to/git_project gitproject.git

$ cd gitproject.git

$ mv hooks/post-update.sample hooks/post-update

$ chmod a+x hooks/post-update

就是这样。Git 默认附带的 `post-update` 钩子会运行适当的命令 (`git update-server-info`),以使 HTTP 获取和克隆正常工作。当你推送到此仓库时(也许通过 SSH);然后,其他人可以通过类似以下的方式进行克隆

$ git clone https://example.com/gitproject.git

在这个特定的例子中,我们使用 Apache 设置中常见的 `/var/www/htdocs` 路径,但你可以使用任何静态 Web 服务器——只需将裸仓库放入其路径即可。Git 数据作为基本静态文件提供(有关其确切提供方式的详细信息,请参阅Git 内部原理一章)。

通常,你会选择运行一个读/写智能 HTTP 服务器,或者只是以哑方式提供只读文件。很少会运行两种服务的混合。

优点

我们将重点关注 HTTP 协议智能版本的优点。

所有类型的访问都只有一个 URL,并且服务器仅在需要身份验证时才提示,这使得最终用户非常容易。能够使用用户名和密码进行身份验证也是相对于 SSH 的一个巨大优势,因为用户不必在本地生成 SSH 密钥并将其公钥上传到服务器,然后才能与之交互。对于不那么熟练的用户,或者在 SSH 较不常见的系统上的用户,这是可用性方面的一个主要优势。它也是一个非常快速和高效的协议,类似于 SSH 协议。

你还可以通过 HTTPS 提供只读仓库,这意味着你可以加密内容传输;或者你可以更进一步,让客户端使用特定的签名 SSL 证书。

另一个好处是 HTTP 和 HTTPS 是如此常用的协议,以至于企业防火墙通常都设置为允许通过其端口的流量。

缺点

在某些服务器上,通过 HTTPS 使用 Git 的设置可能比 SSH 更复杂一些。除此之外,其他协议在提供 Git 内容方面对智能 HTTP 几乎没有优势。

如果你使用 HTTP 进行身份验证推送,提供凭据有时会比通过 SSH 使用密钥更复杂。但是,有几个凭据缓存工具可以使用,包括 macOS 上的 Keychain 访问和 Windows 上的 Credential Manager,这使得它非常方便。请阅读凭据存储以了解如何在系统上设置安全的 HTTP 密码缓存。

SSH 协议

在自托管 Git 时,常用的传输协议是通过 SSH。这是因为大多数地方都已经设置了 SSH 对服务器的访问——如果没有,也很容易做到。SSH 也是一种经过身份验证的网络协议,而且由于它无处不在,通常很容易设置和使用。

要通过 SSH 克隆 Git 仓库,你可以指定一个 `ssh://` URL,如下所示

$ git clone ssh://[user@]server/project.git

或者你可以使用 SSH 协议的较短的类似 scp 的语法

$ git clone [user@]server:project.git

在上述两种情况下,如果你未指定可选的用户名,Git 会假设你当前登录的用户。

优点

使用 SSH 的优点有很多。首先,SSH 相对容易设置——SSH 守护程序很常见,许多网络管理员对它们有经验,并且许多操作系统发行版都已设置好或有工具来管理它们。其次,通过 SSH 的访问是安全的——所有数据传输都经过加密和身份验证。最后,与 HTTPS、Git 和本地协议一样,SSH 效率高,在传输数据之前使其尽可能紧凑。

缺点

SSH 的缺点是它不支持匿名访问你的 Git 仓库。如果你使用 SSH,人们必须对你的机器具有 SSH 访问权限,即使是只读权限,这使得 SSH 不利于开源项目,因为人们可能只是想克隆你的仓库进行检查。如果你只在公司网络内使用它,SSH 可能是你唯一需要处理的协议。如果你想允许对你的项目进行匿名只读访问并也想使用 SSH,你将不得不为自己设置 SSH 以进行推送,但为其他人设置其他方式进行获取。

Git 协议

最后,我们有 Git 协议。这是一个随 Git 附带的特殊守护进程;它监听专用端口(9418),提供类似于 SSH 协议的服务,但完全没有身份验证或加密。为了通过 Git 协议提供仓库服务,你必须创建一个 `git-daemon-export-ok` 文件——如果没有该文件,守护进程将不会提供仓库服务——但除此之外,没有任何安全性。Git 仓库要么可供所有人克隆,要么不可。这意味着通常无法通过此协议进行推送。你可以启用推送访问,但鉴于缺乏身份验证,互联网上任何找到你项目 URL 的人都可以推送到该项目。可以说,这种情况很少见。

优点

Git 协议通常是可用的最快的网络传输协议。如果你为公共项目提供大量流量,或者为不需要用户身份验证即可进行读取访问的非常大的项目提供服务,那么你很可能需要设置一个 Git 守护程序来为你的项目提供服务。它使用与 SSH 协议相同的数据传输机制,但没有加密和身份验证开销。

缺点

由于缺乏 TLS 或其他加密技术,通过 `git://` 进行克隆可能会导致任意代码执行漏洞,因此除非你清楚自己在做什么,否则应避免使用。

如果你运行 `git clone git://example.com/project.git`,控制例如你的路由器的攻击者可以修改你刚刚克隆的仓库,向其中插入恶意代码。如果你随后编译/运行你刚刚克隆的代码,你将执行恶意代码。出于同样的原因,应避免运行 `git clone http://example.com/project.git`。

运行 `git clone https://example.com/project.git` 不会遇到同样的问题(除非攻击者可以为 example.com 提供 TLS 证书)。运行 `git clone git@example.com:project.git` 仅在你接受错误的 SSH 密钥指纹时才会遇到此问题。

它也没有身份验证,也就是说任何人都可以克隆仓库(尽管这通常正是你想要的)。它也可能是最难设置的协议。它必须运行自己的守护程序,这需要 `xinetd` 或 `systemd` 配置或类似的东西,这并非总是轻而易举。它还需要防火墙访问端口 9418,这不是企业防火墙总是允许的标准端口。在大型企业防火墙后面,这个晦涩的端口通常会被阻止。

上一页 | 下一页

上一篇
下一篇
相关文章