是否可以使用git push
?部署网站?我有一个预感,它与使用git hooksgit reset --hard
在服务器端执行有关,但我将如何实现这一目标呢?
我在这个网站上找到了这个脚本,它看起来效果很好.
将.git目录复制到Web服务器
在本地副本上,修改.git/config文件并将Web服务器添加为远程:
[remote "production"] url = username@webserver:/path/to/htdocs/.git
在服务器上,将.git/hooks/post-update替换为此文件(在下面的答案中)
添加对文件的执行访问权限(同样,在服务器上):
chmod +x .git/hooks/post-update
现在,只需在本地推送到您的Web服务器,它应该自动更新工作副本:
git push production
使用下面的更新后文件:
将.git目录复制到Web服务器
在本地副本上,修改.git/config文件并将Web服务器添加为远程:
[remote "production"] url = username@webserver:/path/to/htdocs/.git
在服务器上,将.git/hooks/post-update替换为下面的文件
添加对文件的执行访问权限(同样,在服务器上):
chmod +x .git/hooks/post-update
现在,只需在本地推送到您的Web服务器,它应该自动更新工作副本:
git push production
#!/bin/sh
#
# This hook does two things:
#
# 1. update the "info" files that allow the list of references to be
# queries over dumb transports such as http
#
# 2. if this repository looks like it is a non-bare repository, and
# the checked-out branch is pushed to, then update the working copy.
# This makes "push" function somewhat similarly to darcs and bzr.
#
# To enable this hook, make this file executable by "chmod +x post-update".
git-update-server-info
is_bare=$(git-config --get --bool core.bare)
if [ -z "$is_bare" ]
then
# for compatibility's sake, guess
git_dir_full=$(cd $GIT_DIR; pwd)
case $git_dir_full in */.git) is_bare=false;; *) is_bare=true;; esac
fi
update_wc() {
ref=$1
echo "Push to checked out branch $ref" >&2
if [ ! -f $GIT_DIR/logs/HEAD ]
then
echo "E:push to non-bare repository requires a HEAD reflog" >&2
exit 1
fi
if (cd $GIT_WORK_TREE; git-diff-files -q --exit-code >/dev/null)
then
wc_dirty=0
else
echo "W:unstaged changes found in working copy" >&2
wc_dirty=1
desc="working copy"
fi
if git diff-index --cached HEAD@{1} >/dev/null
then
index_dirty=0
else
echo "W:uncommitted, staged changes found" >&2
index_dirty=1
if [ -n "$desc" ]
then
desc="$desc and index"
else
desc="index"
fi
fi
if [ "$wc_dirty" -ne 0 -o "$index_dirty" -ne 0 ]
then
new=$(git rev-parse HEAD)
echo "W:stashing dirty $desc - see git-stash(1)" >&2
( trap 'echo trapped $$; git symbolic-ref HEAD "'"$ref"'"' 2 3 13 15 ERR EXIT
git-update-ref --no-deref HEAD HEAD@{1}
cd $GIT_WORK_TREE
git stash save "dirty $desc before update to $new";
git-symbolic-ref HEAD "$ref"
)
fi
# eye candy - show the WC updates :)
echo "Updating working copy" >&2
(cd $GIT_WORK_TREE
git-diff-index -R --name-status HEAD >&2
git-reset --hard HEAD)
}
if [ "$is_bare" = "false" ]
then
active_branch=`git-symbolic-ref HEAD`
export GIT_DIR=$(cd $GIT_DIR; pwd)
GIT_WORK_TREE=${GIT_WORK_TREE-..}
for ref
do
if [ "$ref" = "$active_branch" ]
then
update_wc $ref
fi
done
fi
经过许多错误的开始和死胡同,由于这篇文章,我终于能够使用"git push remote " 部署网站代码.
作者的更新后脚本只有一行,他的解决方案不需要.htaccess配置来隐藏Git仓库,就像其他人一样.
如果您在Amazon EC2实例上部署此功能,可能会遇到一些绊脚石;
1)如果使用sudo创建裸目标存储库,则必须将repo的所有者更改为ec2-user,否则推送将失败.(尝试"chown ec2-user:ec2-user repo.")
2)如果您没有预先配置amazon-private-key .pem的位置,在/ etc/ssh/ssh_config中作为IdentityFile参数或在〜/ .ssh/config中使用"[..."主机] - HostName - IdentityFile - 用户" 这里描述的布局......
...但是,如果在〜/ .ssh/config中配置Host并且与HostName不同,则Git push将失败.(这可能是一个Git bug)
不要在服务器上安装git或在那里复制.git文件夹.要从git clone更新服务器,您可以使用以下命令:
git ls-files -z | rsync --files-from - --copy-links -av0 . user@server.com:/var/www/project
您可能必须删除从项目中删除的文件.
这会复制所有已签入的文件.rsync使用安装在服务器上的ssh.
您在服务器上安装的软件越少,他就越安全,管理配置和记录就越容易.也没有必要在服务器上保留完整的git克隆.它只会使正确保护所有内容变得更加复杂.
实质上,您需要做的是以下内容:
server = $1 branch = $2 git push $server $branch ssh@$server "cd /path/to/www; git pull"
我在我的应用程序中将这些行作为可执行文件调用deploy
.
所以,当我想进行部署时,我输入./deploy myserver mybranch
.
我这样做的方式是我在部署服务器上有一个裸Git存储库,我推送更改.然后我登录到部署服务器,切换到实际的Web服务器docs目录,并执行git pull.我没有使用任何钩子来尝试自动执行此操作,这似乎比它的价值更麻烦.
receive.denyCurrentBranch updateInstead在Git 2.3中添加是可能的.
将其设置在服务器存储库中,如果工作树是干净的,它还会更新工作树.
2.4中有push-to-checkout
未来分支的钩子和处理方面有进一步的改进.
样品用法:
git init server cd server touch a git add . git commit -m 0 git config --local receive.denyCurrentBranch updateInstead cd .. git clone server local cd local touch b git add . git commit -m 1 git push origin master:master cd ../server ls
输出:
a b
这确实在GitHub公告中提到了以下缺点:
您的服务器将包含一个.git目录,其中包含项目的整个历史记录.您可能想要确保它无法提供给用户!
在部署期间,用户可能会暂时遇到处于不一致状态的站点,旧版本的某些文件和新版本的其他文件,甚至是半写文件.如果这对您的项目来说是个问题,那么推送部署可能不适合您.
如果你的项目需要一个"构建"步骤,那么你必须明确地设置它,也许是通过githooks.
但所有这些都超出了Git的范围,必须由外部代码处理.所以从这个意义上说,这与Git钩子一起,是最终的解决方案.
更新:我现在正在使用Lloyd Moore解决方案和密钥代理ssh -A ...
.推送到主仓库然后从所有机器并行地从中取出它会更快,并且在这些机器上需要更少的设置.
这里没有看到这个解决方案 如果服务器上安装了git,只需通过ssh推送即可.
您需要在本地.git/config中输入以下条目
[remote "amazon"] url = amazon:/path/to/project.git fetch = +refs/heads/*:refs/remotes/amazon/*
但是,嘿,那是amazon:
什么?在你的本地〜/ .ssh/config中,你需要添加以下条目:
Host amazon HostnameUser IdentityFile ~/.ssh/amazon-private-key
现在你可以打电话了
git push amazon master ssh@ 'cd /path/to/project && git pull'
(BTW:/path/to/project.git与实际工作目录/ path/to/project不同)
在我们的场景中,我们将代码存储在github / bitbucket上,并希望部署到实时服务器上。在这种情况下,以下组合对我们有效(这是此处高度支持的答案的重新组合):
将.git
目录复制到Web服务器
在本地副本上 git remote add live ssh://user@host:port/folder
在远程: git config receive.denyCurrentBranch ignore
远程:nano .git/hooks/post-receive
并添加以下内容:
#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f
在远程: chmod +x .git/hooks/post-receive
现在您可以用 git push live
此解决方案适用于较旧的git版本(已通过1.7和1.9测试)
您需要确保先推送到github / bitbucket,这样您才能实时获得一致的仓库
如果您的.git
文件夹位于文档根目录中,请确保通过添加到.htaccess
(source)将其隐藏在外部:
RedirectMatch 404 /\..*$