案前独忆灯明灭

怕他什么整理无穷, 进一寸有一寸的欢喜

利用git自动部署网站

本周早就想写点服务器上使用 Git 的东西, 但是没有时间, 一直拖到现在才写.

在服务器上建立的 Git 仓库一般都是裸仓库, 即没有文档树的仓库. 所以单纯的push是无法自动部署网站的. 为了让 Git 自动展开文档树, 我们需要使用到一个叫 钩子(hooks) 的东西, 官方文档在这里, 简单理解这就是在执行某些 Git 操作后会自动触发的脚本.

钩子存放在在 Git 工作目录的 /hooks 目录下, 各个钩子的触发时间如其名字所示, .sample 的后缀表示其未被激活.

这是我这个博客的 Git 仓库下的钩子, 其中 post-update 是激活的, 它会在每次仓库被推送的时候运行, 也就是用来展开文档树, 自动部署网站的.

使用vi或者下载下来编辑 post-update.sample 文件, 将其内容改为:

并将文件重命名为 post-update 后上传. 注意 exit 0 不能省略, 否则 Git 收不到退出信号会报错. work-tree 就是要展开到的位置, 文件夹要提前建立好, Git 如果没有找到文件夹则不会展开文档, 也不会报错. git-dir 即仓库所在的路径.


BTW

有些人可能会问: > 既然裸仓库是没有文档树的, 那么不在服务器上建裸仓库, 那干嘛不直接建立正常的仓库? →_→

答案当然是不行啦, 当服务器上的仓库是正常的仓库是, push 操作会收到一个很长错误

[remote rejected] master -> master (branch is currently checked out)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To git@120.78.xx.xx:/home/blog/blog.git
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git@120.78.xx.xx:/home/blog/blog.git'

其大概的意思是, master是服务器上的当前分支, 无法对其进行推送. 这是因为 Git 认为不是裸仓库就是有人在编辑的仓库, 对其采取的一种保护机制(好好的写着东西, 突然被人推送了一下, 整个世界都变了, 你会不会想拿个程序员祭天). 当然, 这种保护是可以关闭的. 错误中已经说了 You can set 'receive.denyCurrentBranch' configuration variable to 'ignore' or 'warn' in the remote 所以可以修改 Git 的配置, 来忽略这个警告.

通过命令

git config --help

可以查看配置文件的帮助. receive.denyCurrentBranch 部分有详细写到:

receive.denyCurrentBranch

If set to true or "refuse", git-receive-pack will deny a ref update to the currently checked out branch of a non-bare repository. Such a push is potentially dangerous because it brings the HEAD out of sync with the index and working tree. If set to "warn", print a warning of such a push to stderr, but allow the push to proceed. If set to false or "ignore", allow such pushes with no message. Defaults to "refuse".

Another option is "updateInstead" which will update the working tree if pushing into the current branch. This option is intended for synchronizing working directories when one side is not easily accessible via interactive ssh (e.g. a live web site, hence the requirement that the working directory be clean). This mode also comes in handy when developing inside a VM to test and fix code on different Operating Systems.

By default, "updateInstead" will refuse the push if the working tree or the index have any difference from the HEAD, but the push-to-checkout hook can be used to customize this. See githooks(5).

如果仍然坚持不使用裸仓库, 则通过:

git config 'receive.denyCurrentBranch' ignore

receive.denyCurrentBranch 设为 ignore, 再进行推送, 不在报错, 推送成功.

可是

文档树仍然没有展开. 还是老老实实的用钩子吧, 嘿嘿.

⬅️ Go back