构建一个最简化的 Git 环境
如何从 GitHub 迁移仓库,配置软件,并开始在您自己的 Linux 服务器上托管 Git 仓库。
随着最近微软收购 GitHub 的新闻,许多人选择研究其他的代码托管选项。像 GitLab 这样的自托管解决方案提供了一个完善的 UI,功能上类似于 GitHub,但它需要配置性能良好的硬件,并提供了许多非 Git 常用用户不一定觉得有用的功能。
对于那些想要更简单解决方案的人来说,可以在 Linux 服务器上本地托管 Git 仓库,只需使用一些基本的软件,这些软件只需要最少的系统资源,并提供基本的 Git 功能,包括 Web 访问和 HTTP/SSH 克隆。
在本文中,我将展示如何从 GitHub 迁移仓库,配置必要的软件,并执行一些基本操作。
迁移仓库从 GitHub 迁移出来的第一步是将您的仓库重新定位到它们将被托管的服务器上。由于 Git 是一个分布式版本控制系统,仓库的克隆副本包含运行整个仓库所需的所有信息。因此,仓库可以从 GitHub 克隆到您的服务器,并且包括提交日志在内的所有仓库数据都将被保留。如果您有大量的仓库,这可能是一个耗时的过程。为了简化这个过程,这里有一个 bash 函数,用于返回特定 GitHub 用户托管的所有仓库的 URL
genrepos() {
if [ -z "$1" ]; then
echo "usage: genrepos <github username>"
else
repourl="https://github.com/$1?tab=repositories"
while [ -n "$repourl" ]; do
curl -s "$repourl" | awk '/href.*codeRepository/
↪{print gensub(/^.*href="\/(.*)\/(.*)".*$/,
↪"https://github.com/\\1/\\2.git","g",$0); }'
export repourl=$(curl -s "$repourl" | grep'>Previous<.
↪*href.*>Next<' | grep -v 'disabled">Next' | sed
↪'s/^.*href="//g;s/".*$//g;s/^/https:\/\/github.com/g')
done
fi
}
此函数接受 GitHub 用户名的单个参数。如果此命令的输出通过管道输入到 while
循环以读取每一行,则每一行都可以被馈送到 git clone
语句中。仓库将被克隆到 /opt/repos 目录中
genrepos <GITHUB-USERNAME> | while read repourl; do
git clone $repourl /opt/repos/$(basename $repourl |
↪sed 's/\.git$//g')
pushd .
cd /opt/repos/$(basename $repourl | sed 's/\.git$//g')
git config --bool core.bare true
popd
done
让我们运行一下这个 while
循环在做什么。 while
循环的第一行只是将 GitHub 仓库克隆到 /opt/repos/REPONAME,其中 REPONAME
是仓库的名称。接下来的四行在仓库配置中设置 core.base
属性,这允许将远程提交推送到服务器(pushd
和 popd
用于在运行脚本时保留工作目录)。此时,所有仓库都将被克隆。
测试仓库完整性的一种方法是从本地文件系统将其克隆到本地文件系统上的新位置。这里名为 scripts
的仓库将被克隆到用户主目录中的 scripts 目录中
git clone /opt/repos/scripts ~/scripts
~/scripts 目录的内容将包含与 /opt/repos/scripts 目录相同的文件。验证两个仓库之间的提交日志应返回相同的日志数据(从仓库目录运行 git log
)。此时,GitHub 仓库已全部就位并准备好使用。
在专用服务器上拥有仓库是很好,但如果它们无法远程访问,那么 Git 仓库的分布式特性就变得毫无用处。为了实现基本级别的功能,您需要在服务器上安装一些应用程序:git、openssh-server、apache2 和 cgit(软件包名称可能因发行版而异)。
在流程中达到这一点时,应该已经安装了 git 软件。SSH 服务器将提供使用 SSH 协议推送/拉取仓库数据的能力。SSH 的开箱即用配置将正常工作,因此无需自定义。另一方面,Apache 和 cgit 将需要一些自定义。
首先,让我们配置 cgit 应用程序。cgit 软件包包含一个名为 cgit.conf 的配置文件,它将放置在 Apache 配置目录中(配置目录的位置因发行版而异)。为了提高 Apache 安装的灵活性,请对 cgit.conf 文件进行以下修改
- 将以下文本添加为文件的第一行:
<Macro CgitPage $url>
。 - 将以下文本添加为文件的最后一行:
</Macro>
。 - 将所有出现的
/cgit
替换为$url
(请注意,/cgit/
将被替换为$url/
)。
生成的配置文件将如下所示(请注意,此宏中的某些路径可能因 Linux 发行版而异)
<Macro CgitPage $url>
ScriptAlias $url/ "/usr/lib/cgit/cgit.cgi/"
RedirectMatch ^$url$ $url/
Alias /cgit-css "/usr/share/cgit/"
<Directory "/usr/lib/cgit/">
AllowOverride None
Options ExecCGI FollowSymlinks
Require all granted
</Directory>
</Macro>
此宏将通过允许在 Apache 配置中的任何 VirtualHost
上启用 cgit 来简化实现。要启用 cgit,请将以下指令放在默认 <VirtualHost>
定义的底部。如果您找不到默认的 VirtualHost
,则可以创建一个新的 VirtualHost
,并且可以将此指令添加到新的 VirtualHost
中。
在本例中,您使用 /git 作为访问 cgit 的 URL。安装后,cgit 没有安装默认配置文件。首次访问应用程序时会生成这样一个配置文件。新配置文件将位于 /etc 目录中,并将命名为 cgitrc。您可以通过以下 URL 访问 cgit 应用程序:http://HOSTNAME/git。
一旦 URL 被访问,配置文件将出现在文件系统中。您现在可以配置 cgit 以查找将要存储仓库的特定目录。假设本地仓库路径为 /opt/repos,则以下行将被添加到 /etc/cgitrc 文件中
scan-path=/opt/repos
scan-path
变量设置 Git 仓库所在的目录。(请注意,cgit 还有其他自定义选项,我在这里没有介绍。)在对 cgitrc 文件进行此更改后,仓库列表将显示在该页面上。您可以通过单击仓库,然后单击页面顶部的“Tree”链接来访问仓库的内容。

图 1. cgit 树
与仓库交互现在环境已完全设置好,仓库也已就位,您需要执行一些基本操作,例如从服务器克隆、推送和拉取仓库。如前所述,您将使用两种主要协议来执行这些基本的 git 操作:HTTP 和 SSH。
在此环境中,这些协议将服务于两个不同的目的。HTTP 将提供对仓库的只读访问权限,这对于公共访问仓库非常有用。您可以从 cgit 仓库列表页面获取 HTTP 克隆 URL,它们将具有以下形式
http://<HOSTNAME>/git/<REPOSITORY>/.git/.
对于读写访问,您可以使用有效的本地用户通过 SSH 克隆仓库。一个好的做法可能是向一个组提供读写访问权限,并向该组授予对 /opt/repos 目录的递归访问权限。
SSH 克隆地址的格式为
ssh://USER@HOSTNAME:PORT/opt/repos/<REPOSITORY>/
如果 SSH 使用的端口保留为默认端口 22,则可以从克隆地址中省略 PORT
。请注意,您可能需要打开防火墙端口才能实现远程 SSH 和 HTTP 连接。
您的自托管极简 Git 环境现已完成。虽然它可能缺少其他解决方案提供的一些高级功能,但它提供了管理分布式代码的基本功能。值得注意的是,您可以将此环境的功能扩展到远远超出我在此处描述的范围,而对性能和整体复杂性的影响很小。
资源