Git钩子配置教程:实现自动部署的实战指南

作者:技术拾光

时间:2026-05-25

浏览:164

结论:使用post-receive钩子实现自动部署 直接说结论:用 post-receive 钩子配合 GIT_WORK_TREE 环境变量,是目前最稳妥的自动部署方案。至于 post-update 或者试图在裸仓库里直接执行 checkout 的操作,建议你碰都别碰——它们不仅会失败,而且常常不给

文章目录

结论:使用post-receive钩子实现自动部署

直接说结论:用 post-receive 钩子配合 GIT_WORK_TREE 环境变量,是目前最稳妥的自动部署方案。至于 post-update 或者试图在裸仓库里直接执行 checkout 的操作,建议你碰都别碰——它们不仅会失败,而且常常不给你明确的错误提示,排查起来才叫一个头疼。

Git钩子配置教程:实现自动部署的实战指南

为什么必须用post-receive而不是post-update

核心原因在于裸仓库(bare repo)的特性:它没有工作目录。当你使用 post-update 钩子时,Git 命令默认的执行环境仍然在 .git 目录内部,此时如果执行 git checkout,就会立刻收到一个经典的错误:fatal: this operation must be run in a work tree。

而 post-receive 钩子则不同,它是唯一一个在服务器接收完推送数据后、能够安全地通过 --work-tree 和 --git-dir 参数来指定路径的钩子。这为后续的检出操作铺平了道路。

  • 信息获取方式:post-receive 通过读取标准输入(stdin)来获取 ref 的更新信息(例如 refs/heads/main),这种方式非常适合用来做分支判断,实现按分支部署。
  • 执行时机:post-update 虽然也能接收到参数,但此时 Git 的内部对象写入已经完成,一些关键的环境变量可能并不可靠。
  • 一个常见的坑:网上很多互相抄来抄去的教程还在推荐 post-update,但实际上,尤其是在 Git 2.30 及以后的版本中,这套方案大概率会静默失败,让你查无可查。

post-receive钩子脚本的正确写法

写钩子脚本的关键,从来不是“能不能跑起来”,而是“权限对不对、路径存不存在、分支认不认”。下面是一个经过验证的最小可用模板,你可以基于它来修改:

#!/bin/sh
# 必须 unset GIT_DIR,否则后续 git 命令会误以为还在裸仓库目录下
unset GIT_DIR

# 指定部署目录(必须提前创建,且属主为运行 git 的用户,例如 git:git)
DEPLOY_PATH="/var/www/myapp"
BRANCH="main"

# 检查部署目录是否存在,避免静默失败
if [ ! -d "$DEPLOY_PATH" ]; then
    echo "ERROR: $DEPLOY_PATH does not exist"
    exit 1
fi

# 切换到部署目录并强制检出指定分支
cd "$DEPLOY_PATH" || exit 1
git --git-dir="/repo/myapp.git" --work-tree="$DEPLOY_PATH" checkout -f "$BRANCH" 2>&1

# 修复权限(尤其当 web 服务用户不是 git 时)
chown -R www-data:www-data "$DEPLOY_PATH"

使用这个模板时,有几个细节必须注意:

  • --git-dir 参数必须指向裸仓库的绝对路径(比如 /repo/myapp.git),使用相对路径大概率会出错。
  • checkout -f 是强制检出,它会丢弃部署目录里所有未提交的改动,包括用户上传的文件。如果生产环境有这类文件,务必在部署前将其迁移走。
  • 如果使用 Nginx 或 Apache 作为 Web 服务器,最后的 chown 步骤不能省略,否则等待你的很可能是 502 或 403 错误。

Git自动部署常见报错与解决方案

post-receive 钩子默认不输出日志,错误信息很容易被“吞掉”。在脚本里加上简单的日志输出,能帮你快速定位问题。下面是一些典型的错误场景:

  • 推送失败,提示 remote: fatal: not a git repository:首先检查 --git-dir 的路径是否拼写错误,然后确认该路径下是否存在 objects/ 等 Git 仓库目录。
  • 推送成功,但网站页面没有更新:可以登录服务器,执行 ls -l /var/www/myapp 查看文件时间戳是否变化。更直接的方法是,手动在服务器上运行一遍钩子脚本里的 git checkout 命令,观察是否有报错。
  • 本地推送失败,提示 Permission denied (publickey):这不是钩子脚本的问题,而是 SSH 密钥配置有误。检查服务器上 ~git/.ssh/authorized_keys 文件是否包含了你的公钥。
  • 部署后网站 CSS/JS 文件 404:这通常意味着前端构建产物(如 dist 目录)没有提交到 Git 仓库,或者钩子脚本里缺少了触发构建的命令(如 npm install && npm run build),需要你根据项目情况自行添加。

说到底,配置自动部署真正的麻烦,从来不是写那几行脚本。而是每次部署前,你都得在心里默念确认三件事:裸仓库的权限对不对、部署目录的权限对不对、Web 服务用户能不能读到那些文件。这三者漏掉任何一个,都足够让你卡上大半天。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章