使用Git推送部署项目
是否可以使用 git push 部署网站? 我有预感这与使用 git hooks 有关 在服务器端执行 git reset --hard ,但是我将如何实现这一点呢?
Is it possible to deploy a website using git push
? I have a hunch it has something to do with using git hooks to perform a git reset --hard
on the server side, but how would I go about accomplishing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
我在这个脚本上找到了这个网站 看起来效果很好。
在本地副本上,修改 .git/config 文件并将 Web 服务器添加为远程服务器:
在服务器上,将 .git/hooks/post-update 替换为 此文件(在下面的答案中)
添加对文件的执行访问权限(同样在服务器上):
现在,只需在本地推送到您的 Web 服务器,它就会自动更新工作副本:
I found this script on this site and it seems to work quite well.
On your local copy, modify your .git/config file and add your web server as a remote:
On the server, replace .git/hooks/post-update with this file (in the answer below)
Add execute access to the file (again, on the server):
Now, just locally push to your web server and it should automatically update the working copy:
使用下面的更新后文件:
在本地副本上,修改 .git/config 文件并将 Web 服务器添加为远程服务器:< /p>
在服务器上,将 .git/hooks/post-update 替换为以下文件
添加对该文件的执行访问权限(同样,在服务器上):
现在,只需在本地推送到您的 Web 服务器,它就会自动更新工作副本:
Using the post-update file below:
On your local copy, modify your .git/config file and add your web server as a remote:
On the server, replace .git/hooks/post-update with file below
Add execute access to the file (again, on the server):
Now, just locally push to your web server and it should automatically update the working copy:
经过多次错误的开始和死胡同后,我终于能够仅使用“git push remote”来部署网站代码,这要归功于 这篇文章。
作者的更新后脚本只有一行长,他的解决方案不需要像其他人那样通过 .htaccess 配置来隐藏 Git 存储库。
如果您在 Amazon EC2 实例上部署此功能,则会遇到一些障碍;
1) 如果使用 sudo 创建裸目标存储库,则必须将存储库的所有者更改为 ec2-user,否则推送将失败。 (尝试“chown ec2-user:ec2-user repo。”)
2) 如果您没有预先配置 amazon-private-key 的位置,推送将会失败em>.pem,在 /etc/ssh/ssh_config 中作为 IdentityFile 参数,或者在 ~/.ssh/config 中使用描述的“[Host] - HostName - IdentityFile - User”布局 此处...
...但是,如果在 ~/.ssh/config 中配置了主机与 HostName 不同,Git 推送将会失败。 (这可能是一个 Git 错误)
After many false starts and dead ends, I'm finally able to deploy website code with just "git push remote" thanks to this article.
The author's post-update script is only one line long and his solution doesn't require .htaccess configuration to hide the Git repo as some others do.
A couple of stumbling blocks if you're deploying this on an Amazon EC2 instance;
1) If you use sudo to create the bare destination repository, you have to change the owner of the repo to ec2-user or the push will fail. (Try "chown ec2-user:ec2-user repo.")
2) The push will fail if you don't pre-configure the location of your amazon-private-key.pem, either in /etc/ssh/ssh_config as an IdentityFile parameter or in ~/.ssh/config using the "[Host] - HostName - IdentityFile - User" layout described here...
...HOWEVER if Host is configured in ~/.ssh/config and different than HostName the Git push will fail. (That's probably a Git bug)
不要在服务器上安装 git 或将 .git 文件夹复制到那里。 要从 git 克隆更新服务器,您可以使用以下命令:
您可能必须删除从项目中删除的文件。
这将复制所有签入的文件。 rsync 使用安装在服务器上的 ssh。
服务器上安装的软件越少,服务器就越安全,管理其配置和记录它也就越容易。 也无需在服务器上保留完整的 git 克隆。 这只会使正确保护一切变得更加复杂。
dont install git on a server or copy the .git folder there. to update a server from a git clone you can use following command:
you might have to delete files which got removed from the project.
this copies all the checked in files. rsync uses ssh which is installed on a server anyways.
the less software you have installed on a server the more secure he is and the easier it is to manage it's configuration and document it. there is also no need to keep a complete git clone on the server. it only makes it more complex to secure everything properly.
git config --local receive.denyCurrentBranch updateInstead
在 Git 2.3 中添加,这可能是一个很好的可能性:https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155
您将其设置在服务器存储库上,如果工作树是干净的,它还会更新工作树。
2.4 中通过
push-to-checkout
挂钩和未出生分支的处理。示例用法:
输出:
这确实具有 上提到的以下缺点GitHub 公告:
但所有这些点都超出了 Git 的范围,必须由外部代码处理。 所以从这个意义上说,这与 Git hooks 一起是最终的解决方案。
git config --local receive.denyCurrentBranch updateInstead
Added in Git 2.3, this could be a good possibility: https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155
You set it on the server repository, and it also updates the working tree if it is clean.
There have been further improvements in 2.4 with the
push-to-checkout
hook and handling of unborn branches.Sample usage:
Output:
This does have the following shortcomings mentioned on the GitHub announcement:
But all of those points are out of the scope of Git and must be taken care of by external code. So in that sense, this, together with Git hooks, are the ultimate solution.
本质上,您需要做的就是以下内容:
我将这些行作为名为
deploy
的可执行文件存在于我的应用程序中。因此,当我想要进行部署时,我输入
./deploy myserver mybranch
。In essence all you need to do are the following:
I have those lines in my application as an executable called
deploy
.so when I want to do a deploy I type
./deploy myserver mybranch
.我的做法是在我的部署服务器上有一个裸露的 Git 存储库,我可以在其中推送更改。 然后我登录到部署服务器,更改到实际的 Web 服务器文档目录,并执行 git pull。 我没有使用任何钩子来尝试自动执行此操作,这似乎比其价值更麻烦。
The way I do it is I have a bare Git repository on my deployment server where I push changes. Then I log in to the deployment server, change to the actual web server docs directory, and do a git pull. I don't use any hooks to try to do this automatically, that seems like more trouble than it's worth.
更新:我现在使用 Lloyd Moore 解决方案和密钥代理
ssh -A ...
。 推送到主存储库,然后从所有机器上并行地从主存储库中拉取速度要快一些,并且在这些机器上需要的设置更少。在这里没有看到这个解决方案。 如果服务器上安装了 git,只需通过 ssh 推送即可。
您需要在本地 .git/config 中添加以下条目
但是,嘿,
amazon:
是什么? 在本地 ~/.ssh/config 中,您需要添加以下条目:现在您可以调用
(顺便说一句:/path/to/project.git 与实际工作目录 /path/to/project 不同)
Update: I'm now using Lloyd Moore solution with the key agent
ssh -A ...
. Pushing to a main repo and then pulling from it in parallel from all your machines is a bit faster and requires less setup on those machines.Not seeing this solution here. just push via ssh if git is installed on the server.
You'll need the following entry in your local .git/config
But hey, whats that with
amazon:
? In your local ~/.ssh/config you'll need to add the following entry:now you can call
(BTW: /path/to/project.git is different to the actual working directory /path/to/project)
我们使用 capistrano 来管理部署。
我们构建 capistrano 来部署在临时服务器上,然后与我们所有的服务器运行 rsync。
使用 Capistrano,我们可以在出现错误时轻松回滚
We use capistrano for managing deploy.
We build capistrano to deploy on a staging server, and then running a rsync with all of ours server.
With capistrano, we can made easy rollback in case of bug
对于部署场景
在我们的场景中,我们将代码存储在 github/bitbucket 上,并希望部署到实时服务器。
在这种情况下,以下组合对我们有效(这是此处高度赞成的答案的重新组合):
.git
目录复制到您的网络服务器上git Remote add live ssh://user@host:port/folder
git config receive.denyCurrentBranchignore
在远程:
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
文件夹位于文档根目录中,请确保通过以下方式将其从外部隐藏添加到.htaccess
(源):RedirectMatch 404 /\..*$
For Deployment Scenario
In our scenario we're storing the code on github/bitbucket and want to deploy to live servers.
In this case the following combination works for us (that is a remix of the highly upvoted answers here):
.git
directory to your web servergit remote add live ssh://user@host:port/folder
git config receive.denyCurrentBranch ignore
On remote:
nano .git/hooks/post-receive
and add this content:#!/bin/sh
GIT_WORK_TREE=/var/www/vhosts/example.org git checkout -f
On remote:
chmod +x .git/hooks/post-receive
git push live
Notes
If your
.git
folder is within document root make sure you hide it from the outside by adding to.htaccess
(source):RedirectMatch 404 /\..*$
Giddyup 是与语言无关的just-add-water git hooks,通过以下方式自动部署git 推送。 它还允许您使用自定义启动/停止挂钩来重新启动 Web 服务器、预热缓存等。
https://github。 com/mpalmer/giddyup
查看示例。
Giddyup are language-agnostic just-add-water git hooks to automate deployment via git push. It also allows you to have custom start/stop hooks for restarting web server, warming up cache etc.
https://github.com/mpalmer/giddyup
Check out examples.
听起来您的服务器上应该有两个副本。 一个裸副本,您可以从中推送/拉取,完成后您将推送更改,然后您可以将其克隆到您的 Web 目录中并设置一个 cronjob 每天从您的 Web 目录更新 git pull 或所以。
Sounds like you should have two copies on your server. A bare copy, that you can push/pull from, which your would push your changes when you're done, and then you would clone this into you web directory and set up a cronjob to update git pull from your web directory every day or so.
您可以想象设置一个 git 钩子,当提交一个“稳定”分支时,它将提取更改并将其应用到 PHP 站点。 最大的缺点是,如果出现问题,您将无法进行太多控制,并且会增加测试时间 - 但您可以了解当您将主干分支合并到稳定分支时会涉及多少工作,以了解您可能遇到多少冲突。 密切关注特定于站点的任何文件(例如配置文件)非常重要,除非您只想运行一个站点。
或者您是否考虑过将更改推送到网站?
有关 git hooks 的信息,请参阅 githooks 文档。
You could conceivably set up a git hook that when say a commit is made to say the "stable" branch it will pull the changes and apply them to the PHP site. The big downside is you won't have much control if something goes wrong and it will add time to your testing - but you can get an idea of how much work will be involved when you merge say your trunk branch into the stable branch to know how many conflicts you may run into. It will be important to keep an eye on any files that are site specific (eg. configuration files) unless you solely intend to only run the one site.
Alternatively have you looked into pushing the change to the site instead?
For information on git hooks see the githooks documentation.
我对基督徒解决方案的看法。
My take on Christians solution.
我正在使用 toroid.org 提供的以下解决方案,它具有更简单的挂钩脚本。
在服务器上:
并在服务器上安装挂钩:
在您的客户端上:
然后要发布,只需键入
网站上有完整的说明:http://toroid.org/ams/git-website-howto
I am using the following solution by toroid.org, which has a simpler hook script.
on the server:
and install the hook on the server:
on your client:
then to publish, just type
There is a full description on the website: http://toroid.org/ams/git-website-howto
作为补充答案,我想提供一个替代方案。 我正在使用 git-ftp 并且工作正常。
https://github.com/git-ftp/git-ftp
易于使用,只需输入:
git 就会自动上传项目文件。
问候
As complementary answer I would like to offer an alternative. I'm using git-ftp and it works fine.
https://github.com/git-ftp/git-ftp
Easy to use, only type:
and git will automatically upload project files.
Regards
在有多个开发人员访问同一存储库的环境中,以下准则可能会有所帮助。
确保您有一个所有开发人员都属于的 unix 组,并将 .git 存储库的所有权授予该组。
在服务器存储库的.git/config 中设置sharedrepository = true。 (这告诉 git 允许提交和部署所需的多个用户。
将每个用户在 bashrc 文件中的 umask 设置为相同 - 002 是一个好的开始
Given an environment where you have multiple developers accessing the same repository the following guidelines may help.
Ensure that you have a unix group that all devs belong to and give ownership of the .git repository to that group.
In the .git/config of the server repository set sharedrepository = true. (This tells git to allow multiple users which is needed for commits and deployment.
set the umask of each user in their bashrc files to be the same - 002 is a good start
我最终创建了自己的基本部署工具,该工具会自动从存储库中提取新更新 - https://github.com /jesalg/SlimJim - 基本上它监听 github post-receive-hook 并使用代理来触发更新脚本。
I ended up creating my own rudimentary deployment tool which would automatically pull down new updates from the repo - https://github.com/jesalg/SlimJim - Basically it listens to the github post-receive-hook and uses a proxy to trigger an update script.
我对接收后挂钩使用两种解决方案:
部署解决方案 1
部署解决方案 2
这两种解决方案都基于此线程中提供的早期解决方案。
注意,
BRANCH_REGEX='^${GIT_BRANCH1}.$'
过滤与“master”或“dev*”字符串匹配的分支名称,如果推送的分支匹配,则部署工作树。
这使得将开发版本和主版本部署到不同的地方成为可能。
部署解决方案 1 仅删除属于存储库一部分并通过提交删除的文件。 它比部署解决方案 2 更快。
部署解决方案 2 的优点是,它会从生产目录中删除在服务器端添加的所有新文件,无论它是否添加到存储库中。 它将始终是回购协议的干净副本。 它比部署解决方案 1 慢。
if [[ $branch =~ $BRANCH_REGEX ]] ; then export GIT_WORK_TREE=$GIT_TARGET2/. echo "Checking out branch: $branch"; echo "Checking out to workdir: $GIT_WORK_TREE"; # DEPLOY SOLUTION 2: cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2; export GIT_WORK_TREE=$GIT_TEMP_DIR2/. git checkout -f $branch export GIT_WORK_TREE=$GIT_TARGET2/. rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/. rm -rf $GIT_TEMP_DIR2 fi done这两种解决方案都基于此线程中提供的早期解决方案。
注意,
BRANCH_REGEX='^${GIT_BRANCH1}.$'
过滤与“master”或“dev*”字符串匹配的分支名称,如果推送的分支匹配,则部署工作树。
这使得将开发版本和主版本部署到不同的地方成为可能。
部署解决方案 1 仅删除属于存储库一部分并通过提交删除的文件。 它比部署解决方案 2 更快。
部署解决方案 2 的优点是,它会从生产目录中删除在服务器端添加的所有新文件,无论它是否添加到存储库中。 它将始终是回购协议的干净副本。 它比部署解决方案 1 慢。
if [[ $branch =~ $BRANCH_REGEX ]] ; then export GIT_WORK_TREE=$GIT_TARGET1/. echo "Checking out branch: $branch"; echo "Checking out to workdir: $GIT_WORK_TREE"; git checkout -f $branch fi BRANCH_REGEX='^${GIT_BRANCH2}.*部署解决方案 2
这两种解决方案都基于此线程中提供的早期解决方案。
注意,
BRANCH_REGEX='^${GIT_BRANCH1}.$'
过滤与“master”或“dev*”字符串匹配的分支名称,如果推送的分支匹配,则部署工作树。
这使得将开发版本和主版本部署到不同的地方成为可能。
部署解决方案 1 仅删除属于存储库一部分并通过提交删除的文件。 它比部署解决方案 2 更快。
部署解决方案 2 的优点是,它会从生产目录中删除在服务器端添加的所有新文件,无论它是否添加到存储库中。 它将始终是回购协议的干净副本。 它比部署解决方案 1 慢。
if [[ $branch =~ $BRANCH_REGEX ]] ; then export GIT_WORK_TREE=$GIT_TARGET2/. echo "Checking out branch: $branch"; echo "Checking out to workdir: $GIT_WORK_TREE"; git checkout -f $branch fi done部署解决方案 2
这两种解决方案都基于此线程中提供的早期解决方案。
注意,
BRANCH_REGEX='^${GIT_BRANCH1}.$'
过滤与“master”或“dev*”字符串匹配的分支名称,如果推送的分支匹配,则部署工作树。
这使得将开发版本和主版本部署到不同的地方成为可能。
部署解决方案 1 仅删除属于存储库一部分并通过提交删除的文件。 它比部署解决方案 2 更快。
部署解决方案 2 的优点是,它会从生产目录中删除在服务器端添加的所有新文件,无论它是否添加到存储库中。 它将始终是回购协议的干净副本。 它比部署解决方案 1 慢。
I use two solutions for post-receive hook:
DEPLOY SOLUTION 1
DEPLOY SOLUTION 2
Both solutions are based on earlier solutions available in this thread.
Note, the
BRANCH_REGEX='^${GIT_BRANCH1}.$'
filters for the branch names matching "master" or "dev*" string, and deploys the work tree, if the pushed branch matches.
This makes possible to deploy a dev version and master version to different places.
DEPLOY SOLUTION 1 removes only files, which are part of the repo, and was removed by a commit. It is faster than Deployment Solution 2.
DEPLOY SOLUTION 2 has the advantage, that it will remove any new files from the production directory, which was added on server side, no matter if it was added to the repo or not. It will be always clean dupe of the repo. It is slower than Deployment Solution 1.
if [[ $branch =~ $BRANCH_REGEX ]] ; then export GIT_WORK_TREE=$GIT_TARGET2/. echo "Checking out branch: $branch"; echo "Checking out to workdir: $GIT_WORK_TREE"; # DEPLOY SOLUTION 2: cd $GIT_DIR/; mkdir -p $GIT_TEMP_DIR2; export GIT_WORK_TREE=$GIT_TEMP_DIR2/. git checkout -f $branch export GIT_WORK_TREE=$GIT_TARGET2/. rsync $GIT_TEMP_DIR2/. -v -q --delete --delete-after -av $GIT_TARGET2/. rm -rf $GIT_TEMP_DIR2 fi doneBoth solutions are based on earlier solutions available in this thread.
Note, the
BRANCH_REGEX='^${GIT_BRANCH1}.$'
filters for the branch names matching "master" or "dev*" string, and deploys the work tree, if the pushed branch matches.
This makes possible to deploy a dev version and master version to different places.
DEPLOY SOLUTION 1 removes only files, which are part of the repo, and was removed by a commit. It is faster than Deployment Solution 2.
DEPLOY SOLUTION 2 has the advantage, that it will remove any new files from the production directory, which was added on server side, no matter if it was added to the repo or not. It will be always clean dupe of the repo. It is slower than Deployment Solution 1.
if [[ $branch =~ $BRANCH_REGEX ]] ; then export GIT_WORK_TREE=$GIT_TARGET1/. echo "Checking out branch: $branch"; echo "Checking out to workdir: $GIT_WORK_TREE"; git checkout -f $branch fi BRANCH_REGEX='^${GIT_BRANCH2}.*DEPLOY SOLUTION 2
Both solutions are based on earlier solutions available in this thread.
Note, the
BRANCH_REGEX='^${GIT_BRANCH1}.$'
filters for the branch names matching "master" or "dev*" string, and deploys the work tree, if the pushed branch matches.
This makes possible to deploy a dev version and master version to different places.
DEPLOY SOLUTION 1 removes only files, which are part of the repo, and was removed by a commit. It is faster than Deployment Solution 2.
DEPLOY SOLUTION 2 has the advantage, that it will remove any new files from the production directory, which was added on server side, no matter if it was added to the repo or not. It will be always clean dupe of the repo. It is slower than Deployment Solution 1.
if [[ $branch =~ $BRANCH_REGEX ]] ; then export GIT_WORK_TREE=$GIT_TARGET2/. echo "Checking out branch: $branch"; echo "Checking out to workdir: $GIT_WORK_TREE"; git checkout -f $branch fi doneDEPLOY SOLUTION 2
Both solutions are based on earlier solutions available in this thread.
Note, the
BRANCH_REGEX='^${GIT_BRANCH1}.$'
filters for the branch names matching "master" or "dev*" string, and deploys the work tree, if the pushed branch matches.
This makes possible to deploy a dev version and master version to different places.
DEPLOY SOLUTION 1 removes only files, which are part of the repo, and was removed by a commit. It is faster than Deployment Solution 2.
DEPLOY SOLUTION 2 has the advantage, that it will remove any new files from the production directory, which was added on server side, no matter if it was added to the repo or not. It will be always clean dupe of the repo. It is slower than Deployment Solution 1.