WP DEVELOP

EP118. “裸仓库与 post-receive Hook 实现 git push 部署”

首页 WordPress 开发课程 网站上线部署 · EP118
约 8 分钟· #EP118#网站上线部署
🔒 登录后可标记已读

把线上服务器配置成一个可以被 git push 的目标:在公开可访问的网站目录之外新建一个文件夹,初始化成「裸仓库(bare repo)」——裸仓库没有工作目录,只用来接收推送,不能直接在里面改代码。再写一个 post-receive 钩子脚本,让服务器每次收完推送的最后一个字节后,自动把仓库内容检出(checkout)到真正对外公开的 wp-content 目录。最后在本地把这个远程仓库加为 Git 的 remote,处理本地分支名(main)和 DreamHost 默认分支名(master)不一致的问题,第一次成功推送。


涉及文件

  • ~/我的仓库文件夹/hooks/post-receive (线上服务器新建,Shell 脚本)

代码实现

在线上服务器(SSH 会话里)创建裸仓库

# 在公开网站目录之外新建一个文件夹(名字随意,这里叫 our-repo)
mkdir our-repo
cd our-repo

# 确认当前路径
pwd

# 初始化为裸仓库——没有工作目录,只用来接收 push
git init --bare

hooks/post-receive(裸仓库自带的 hooks 文件夹里新建这个文件,无扩展名)

#!/bin/bash
git --work-tree=/home/你的SSH用户名/你的域名/wp-content --git-dir=/home/你的SSH用户名/our-repo checkout -f

创建 + 编辑 + 赋可执行权限的命令:

cd hooks
touch post-receive
nano post-receive
# 粘贴/输入上面的脚本内容,Ctrl+X → Y → Enter 保存
chmod +x post-receive

本地(VS Code 终端,在 wp-content 仓库里)添加远程仓库、处理分支名、首次推送

# 添加远程仓库,取个昵称叫 live,指向刚创建的裸仓库
git remote add live ssh://你的SSH用户名@你的域名/home/你的SSH用户名/our-repo

# 如果地址填错了,用 set-url 更正(不用重新 add)
git remote set-url live ssh://你的SSH用户名@你的域名/home/你的SSH用户名/our-repo

# 查看当前本地分支名
git status

# DreamHost 默认认的分支名是 master,不是新版 Git/Apple 自带 Git 默认的 main
# 如果本地分支是 main,创建并切换到一个叫 master 的新分支(从 main 派生)
git checkout -b master

# 改动文件后,照常提交
git add -A
git commit -m "changed home page title"

# 推送到线上(第一次会要求输入 SSH 密码;因为是第一次推送,会传送仓库里的全部文件)
git push live master

关键改动点:

  • 裸仓库故意建在网站公开目录之外(比如跟 logsmaildir 平级的位置),因为 push 的过程本身是「服务器管理层面」的操作,不应该发生在对外公开的目录里;等推送完全接收完毕,post-receive 钩子再负责把文件复制/检出到真正公开可访问的位置
  • post-receive 是 Git 内置的钩子机制之一(还有 pre-commitpost-merge 等,都是裸仓库 hooks 文件夹里自动生成的示例文件),文件名必须精确匹配 post-receive,才会在「服务器完整接收完一次 push」之后自动执行
  • 钩子脚本的核心是一行 git --work-tree=... --git-dir=... checkout -f--git-dir 指向裸仓库自己的位置(存版本历史的地方),--work-tree 指向真正要把文件铺开的公开目录(这里specifically 是网站域名文件夹下的 wp-content),checkout -f 强制检出,确保这一步不管什么情况都会执行
  • 脚本第一行 #!/bin/bash 用来指定这个脚本要用哪个 shell 解释器执行,是 Linux shell 脚本的标准写法
  • chmod +x 给脚本文件加上可执行权限——新建的文件默认没有执行权限,钩子脚本不可执行的话,post-receive 事件触发了也不会真正跑起来
  • DreamHost 服务器端默认认的分支名固定是 master;较新版本的 Git(尤其是 macOS 自带版本)新建仓库默认分支名是 main——作者尝试过多种方法把服务器端改成认 main,都没有稳定生效,所以最终采用「反过来让本地分支改名去匹配服务器」这个更省心的折中方案:git checkout -b master 会基于当前分支创建一个新分支 master 并自动切换过去

常见坑

  • 裸仓库建在网站公开目录里面——推送过程本身不应该发生在公开可访问的路径下,必须建在外面,靠 post-receive 钩子间接把内容同步到公开目录
  • post-receive 文件名拼错(比如少个字母)——钩子文件名必须完全精确匹配 Git 认的固定名称,拼错的话 Git 根本不会去执行它,不会有任何报错提示,只会表现成「push 成功了但网站没更新」
  • 忘记给 post-receive 加可执行权限(chmod +x)——脚本内容写对了但没有执行权限,一样不会生效
  • 本地分支名(main)和服务器认的分支名(master)不一致——推送时容易搞不清到底该 push 到哪个分支,统一改成跟服务器一致最省心
  • git remote add 时手滑打错用户名/域名——作者在录制时真实遇到过这个问题,报错是「fatal: 这看起来不是一个 git 仓库」,遇到这种情况不用重新 add,用 git remote set-url 直接改正 URL 即可

延伸 / 后续讲座会用到

现在 git push 已经能把改动送上线,但每次推送都要输入密码。下一讲会配置 SSH Key 实现免密登录/推送,是这套自动化工作流的最后一块拼图。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 21, EP118