在自建代码托管平台时,不少团队希望复用已有的 Apache 服务来暴露 Git 仓库,而不是单独部署 SSH 或专用 Git 服务。Git 自带的 Smart HTTP 协议恰好能满足这种需求:它借助标准 HTTP 请求完成 clone、push 与 pull,且比早期的 dumb 协议高效得多。要在 Apache 中真正跑通这套机制,需要理解后端程序如何接管 URL、授权信息如何透传,以及仓库本身的配置开关。

Smart HTTP 与 dumb 协议的核心差异
早期的 Git HTTP 访问被称为 dumb 协议,它假设 Web 服务器只是静态文件服务者。客户端需要列举远程仓库的 objects 与 packs 目录,把每一个文件都尝试下载,再通过本地计算找出所需对象。这种方式在仓库体积小的时候尚可接受,一旦仓库包含大量历史提交或二进制资源,网络往返次数会急剧上升,克隆一次可能要请求上千个文件。
Smart HTTP 协议则引入了动态协商过程。服务器端的 git-http-backend 作为一个 CGI 程序运行,当收到 info/refs?service=git-upload-pack 这类请求时,它会直接调用本地的 git 命令,生成一份仅包含双方协商后差异的包流。客户端不再盲目遍历静态目录,而是像使用 SSH 协议一样获取精简数据。从用户视角看,URL 仍是 http 开头,但底层已经由哑管道升级为智能管道。
值得注意的是,Smart HTTP 是按需降级而非永远可用。如果 Apache 没有正确指向后端程序,或后端无权读取仓库,Git 客户端会自动回退到 dumb 协议并报出警告。很多运维误以为配置失败是权限问题,其实只是 ScriptAlias 写错导致后端根本没启动。理解这一差异有助于快速定位部署故障。
Apache 中 git-http-backend 的基础配置
要让 Apache 识别 Git 请求,第一步是通过 ScriptAlias 把特定路径映射到后端可执行文件。通常我们将所有 /git/ 开头的请求交给 git-http-backend,并设置环境变量 GIT_PROJECT_ROOT 指明仓库根目录。这样 /git/myrepo.git 就会对应到磁盘上的真实裸仓库。
下面给出一个最小可用的 Apache 配置片段,假设后端程序位于 /usr/lib/git-core/git-http-backend,仓库放在 /srv/git 下:
<VirtualHost *:80>
ServerName git.ippipp.com
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
<Directory "/usr/lib/git-core">
Require all granted
</Directory>
<Directory "/srv/git">
Require all granted
</Directory>
</VirtualHost>
配置中 GIT_HTTP_EXPORT_ALL 表示允许列出所有仓库,若省略则仅在仓库内存在 git-daemon-export-ok 文件时才对外可见。生产环境建议结合具体目录权限做精细化控制,例如对写操作单独要求认证。另外,Apache 的 mod_cgi 或 mod_cgid 必须启用,否则 ScriptAlias 无法执行外部程序。
当配置完成后,可以用 curl 直接请求 http://git.ippipp.com/git/myrepo.git/info/refs?service=git-upload-pack 来验证。若返回内容以 001e# service=git-upload-pack 开头,说明 Smart HTTP 后端已正常接管;若返回的是 HTML 目录列表,则明显回退到了静态服务。
鉴权、写权限与常见故障排查
只读克隆通常不需要登录,但 push 操作必须确认客户端身份。Apache 可通过 AuthType Basic 配合 htpasswd 文件来拦截写请求。关键在于使用 Require 指令区分动作:利用 LimitExcept 让 GET 类请求公开,而 POST 类请求强制认证,这样既不影响克隆又不放开推送。
除 Web 层鉴权外,Git 自身也有开关。每个裸仓库内的 config 文件需要设置 http.receivepack 为 true,否则即使 Apache 放行了 POST,后端也会拒绝接收包。这一项默认关闭,是新手部署时最容易忽略的点。对应配置如下:
[http]
receivepack = true
实际排错时,建议先开启 Apache 的 LogLevel debug 观察 CGI 环境变量是否传递正确,再检查 SELinux 或 AppArmor 是否阻止了 httpd 进程访问 /srv/git 目录。如果出现 403,多半是目录权限或 Require 规则过严;如果出现 404,优先确认 ScriptAlias 路径末尾的斜杠是否遗漏。通过分层验证,基本可以在十分钟内定位绝大多数 Smart HTTP 部署问题。
从架构角度看,Smart HTTP 把传输协议的选择成本降到了最低:开发者不需要配置 SSH 密钥,企业也能借助现有反向代理做审计与限流。只要 Apache 配置严谨、仓库开关明确,它完全可以作为中型团队内部代码分发的稳定方案。
ApacheGit_Smart_HTTPrepository修改时间:2026-08-18 19:26:33