git 对同一服务器上的部署、暂存和生产、现有代码进行完整性检查
sanity check for git deployment, staging and production on same server, existing code
假设我有一台服务器,它有一个现有的生产站点及其暂存站点。
现在我在 ~/
创建了一个裸仓库,它有一个 hook/post-receive
#!/bin/bash
# post-receive
# deploy production and staging to vhost dirs
# Directory we are deploying to. Should be the directory where the repo's root .gitignore would exist in.
PRODDEST="/path/to/destination/of/production"
STAGDEST="/path/to/destination/of/staging"
while read oldrev newrev refname; do
# Grab the name of the branch that was pushed.
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "master" = "$branch" ]; then
echo "Master push, deploy production..."
GIT_WORK_TREE=$PRODDEST git checkout -f master
GIT_WORK_TREE=$PRODDEST git clean -fd
elif [ "develop" = "$branch" ]; then
echo "Develop push, deploy staging..."
GIT_WORK_TREE=$STAGDEST git checkout -f develop
GIT_WORK_TREE=$STAGDEST git clean -fd
fi
done
通过从本地推送到任一远程分支,相应文件夹中的代码会在服务器上得到更新。这行得通,但我太谨慎了,因为我只在虚拟生产和暂存文件夹上这样做过。
现在如果我想在我现有的生产站点上使用它而不移动它的位置怎么办? (更改 PRODDEST
和 STAGDEST
位置后)
我进入所有现有代码所在的生产根文件夹,运行 git init
、git add .
、git commit -m "initial commit"
、git add remote hub ~/hub.git
和 git push hub master
。 (同时添加一个 bitbucket origin 并推送到那个)。
我将为 .htaccess
中的 .git
文件夹添加重写
测试时,我收到消息要求我先从集线器中拉出而不是推送到集线器,因为集线器中有代码,但生产文件夹中没有。
在不弄乱现有网站的情况下,这是一种明智的做法吗?还有什么我应该注意的吗?
这看起来基本正确(见下文),并且这一点:
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
是一个很好的技巧,可以避免依赖于 ref 格式,但我可能会作弊并将循环内部编写得更像:
while read oldrev newrev refname; do
case $refname in
refs/heads/master) deployto $PRODDEST prod master;;
refs/heads/develop) deployto $STAGDEST dev develop;;
esac
done
使用 deployto() 函数执行结帐(如果您愿意,也可以 git clean
,尽管似乎不需要执行此步骤)。请参阅下面的中间参数。
这就是 "largely correct" 的用武之地,这可能就是您需要 git clean
的原因。 Git 在 index
文件中保留目标目录($PRODDEST
或 $STAGDEST
)外观的缓存。它不希望目标从一个 git checkout
更改为下一个。它使用以前的缓存状态来优化将工作树更新到新状态的过程。如果暂存和生产完全不同,git 将不会在最后一次结帐到另一棵树时获得 "previous state" 正确。
我认为设置每个目标索引文件是处理此问题的 "right way"。有很多方法来构建它,但这里有一个使用中间参数的简单测试方法:
deployto() {
GIT_WORK_TREE= GIT_INDEX_FILE=$PWD/$GIT_DIR/.index git checkout
}
(此处也不需要 -f
,除非由于某种原因 Web 服务器修改了目标目录)。
假设我有一台服务器,它有一个现有的生产站点及其暂存站点。
现在我在 ~/
创建了一个裸仓库,它有一个 hook/post-receive
#!/bin/bash
# post-receive
# deploy production and staging to vhost dirs
# Directory we are deploying to. Should be the directory where the repo's root .gitignore would exist in.
PRODDEST="/path/to/destination/of/production"
STAGDEST="/path/to/destination/of/staging"
while read oldrev newrev refname; do
# Grab the name of the branch that was pushed.
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "master" = "$branch" ]; then
echo "Master push, deploy production..."
GIT_WORK_TREE=$PRODDEST git checkout -f master
GIT_WORK_TREE=$PRODDEST git clean -fd
elif [ "develop" = "$branch" ]; then
echo "Develop push, deploy staging..."
GIT_WORK_TREE=$STAGDEST git checkout -f develop
GIT_WORK_TREE=$STAGDEST git clean -fd
fi
done
通过从本地推送到任一远程分支,相应文件夹中的代码会在服务器上得到更新。这行得通,但我太谨慎了,因为我只在虚拟生产和暂存文件夹上这样做过。
现在如果我想在我现有的生产站点上使用它而不移动它的位置怎么办? (更改 PRODDEST
和 STAGDEST
位置后)
我进入所有现有代码所在的生产根文件夹,运行 git init
、git add .
、git commit -m "initial commit"
、git add remote hub ~/hub.git
和 git push hub master
。 (同时添加一个 bitbucket origin 并推送到那个)。
我将为 .htaccess
.git
文件夹添加重写
测试时,我收到消息要求我先从集线器中拉出而不是推送到集线器,因为集线器中有代码,但生产文件夹中没有。
在不弄乱现有网站的情况下,这是一种明智的做法吗?还有什么我应该注意的吗?
这看起来基本正确(见下文),并且这一点:
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
是一个很好的技巧,可以避免依赖于 ref 格式,但我可能会作弊并将循环内部编写得更像:
while read oldrev newrev refname; do
case $refname in
refs/heads/master) deployto $PRODDEST prod master;;
refs/heads/develop) deployto $STAGDEST dev develop;;
esac
done
使用 deployto() 函数执行结帐(如果您愿意,也可以 git clean
,尽管似乎不需要执行此步骤)。请参阅下面的中间参数。
这就是 "largely correct" 的用武之地,这可能就是您需要 git clean
的原因。 Git 在 index
文件中保留目标目录($PRODDEST
或 $STAGDEST
)外观的缓存。它不希望目标从一个 git checkout
更改为下一个。它使用以前的缓存状态来优化将工作树更新到新状态的过程。如果暂存和生产完全不同,git 将不会在最后一次结帐到另一棵树时获得 "previous state" 正确。
我认为设置每个目标索引文件是处理此问题的 "right way"。有很多方法来构建它,但这里有一个使用中间参数的简单测试方法:
deployto() {
GIT_WORK_TREE= GIT_INDEX_FILE=$PWD/$GIT_DIR/.index git checkout
}
(此处也不需要 -f
,除非由于某种原因 Web 服务器修改了目标目录)。