所以,我理解分支的价值,但有一点是混淆了我。 我有我的本地回购。 我将更改到远程,具有后收到钩设立写一个网站上的文件。 所以,我创建一个分支(新分支)尝试了一些东西。 我编辑的文件,提交和推送到远程的。 大。 问题是,当我的遥控器上的回购是最新的,我想这是仍设置为主控,在新分支的更改不会在网站上反映出来。 如何远程设置为一个特定的分支,使分支驱动后收到钩,而不仅仅是默认到主分支? 我只想合并上主,但我还没有准备好,因为我仍然在分支上工作了扭结。
Answer 1:
OK,根据意见,这听起来像你控制服务器也一样,这是需要在这里。 (也就是说,在我写的“他们”的,它只是你自己,而是戴着不同的帽子,因为它是。)
让我们先从一些背景: git push
和“裸”库
但从混帐的角度来看,你对你的回购工作,他们(无论他们是谁),他们的回购工作。 所以,当你做一个git push
,它提供了你直接向他们提交回购,他们可能工作在他们的回购。 他们可能有一些分支签出,并且在编辑其副本的中间xyz.html
或什么的。
如果你推改写他们的xyz.html
,那不是给他们带来困扰? 他们在编辑的中间! 因此,对于传统的存储库,git会拒绝尝试推到任何分支,目前已签出(在一个git status
打印为“#分支......”,或显示git symbolic-ref --short HEAD
) 。 1您只能推到其他部门,根据定义,他们没有工作,所以他们不会生气。
现在,其实很多这样的集中“推这里”仓库没有任何人对他们的工作。 他们通常被设置为“裸”库,这意味着他们没有工作树都没有。 这反过来又意味着“他们” -whoever“他们”可能是,也不可能是工作在他们的副本xyz.html
,因为他们没有工作拷贝xyz.html
摆在首位。 与克隆--bare
或常规库转换成裸之一,禁用“不能推到当前分支”检查,这是他们想要的这里。
1特别是,你得到一个“拒绝更新签出分支”的错误。 这实际上是可配置的,通过receive.denyCurrentBranch
,在(非裸)资源库服务器上。
自动部署
到现在为止还挺好; 但现在他们可能希望自己的中央推送服务器裸露的回购协议也将自动部署到一个网站(或者,对于代码库,到测试系统像詹金斯,或其他)-the关键的一点是,“他们”,他们是谁再次,有一个后收到钩可部署一个特定的分支。 但是,我们刚才所描述的纯仓库为没有工作树。 这是如何自动部署的工作? 让我们把我们的其他的帽子,成为“他们”。
因为这是git的,其实有很多方法,但通常的(也许,最好的)方法是使用后收到脚本,检查哪个分支(ES)正在更新,如果有趣的一个(或多个)/被推到,做的部署。
下面是一个可笑的简单的例子post-receive
的是有一个未实现的挂钩shell脚本deploy
壳功能部署推向master
:
#! /bin/sh
deploy()
{
local newref=$1 branch=$2
echo deploy invoked: $newref $branch
}
while read oldsha newsha refname; do
case "$refname" in
refs/heads/master) deploy $newsha ${refname#refs/heads/};;
esac
done
GIT中运行,其标准输入被馈送一系列输入线 - 接收后钩。 每行有三个项目。 最后一个是引用的全名,所以分支的主人是refs/heads/master
。 前两个是“旧” SHA-1和“新” SHA-1分别用于该引用。
在旧的和新的SHA-1值的至多一个可以是40个0
字符:这意味着正在创建参考(旧-SHA-1是全零)或删除(新是全零)。 否则,参考目前存在并且简单地被更新(尖到一个新的提交,正常):它用来指向旧的标识,现在指向新。
(在预 -接收钩,它得到完全一样的东西,你可以拒绝尝试更新的参考。在后 -接收挂钩的更新已经发生了,你唯一可以做的就是在它的报告或利用它以某种方式。)
在我们的例子中,我们真的不关心旧值。 如果分支不要紧, master
从来没有存在过,或者被部署又是什么。 (好吧,我们可能想它,在这种情况下,我们可以将其添加:这只是一个shell脚本,毕竟)。我们甚至不真正需要的新的价值,因为我们可以看到对出库的有Git的命令,但它是不错的,特别是如果我们要检查,如果该分支已被删除抱怨。 (如果阅读的尝试分支可能是删除master
分支参考失败,但如果服务器已经起火可能发生,仓库在半毁,也尽管在这种情况下,我们可能并不关心任何更多: - ))
主要是,虽然,我们需要做的是从分公司签出的所有文件master
,坚持他们进入一个部署区域。 事实证明,我们可以用一个简单的做到这一点git checkout
,即使在纯仓库,通过指定交替工作树:
NULL_SHA1=0000000000000000000000000000000000000000 # 40 0s
deploy() {
local newref=$1 branch=$2
if [ $newref = $NULL_SHA1 ]; then
echo "deploy: branch $branch is deleted!"
return 1
fi
# next bit is stupid, hardcodes "master" even though
# we have "$branch", but read on...
git --work-tree=/deploy/master checkout master
}
(附注:有时你会认为这是GIT_WORK_TREE=/deploy/master git checkout master
。或类似这不完全是一回事。如果你不指定--work-tree
Git使用$GIT_WORK_TREE
。如果它被设置)
如果我们要的不仅仅是一个(多master
)自动部署分支,我们可以添加更多的分支名称到调用一套deploy
在我们的脚本,并修复哑位:检查出$branch
到/deploy/$branch
,例如。
有一些潜在的故障,虽然在这里:
- 目标目录(这里
/deploy/master
)必须存在。 - 这种
git checkout
更新“当前分支”的Git的概念。 纯仓库还有这样一件事:有一个名为还是一个文件HEAD
包含当前分支名。 如果我们git checkout otherbranch
我们将改变它; 这会影响git clone
,从这个纯仓库克隆操作。 - Git会确保我们不会破坏修改的文件。 根据部署目录和得到什么方面所做的工作,这可能不是一个问题。
- Git的喜欢优化检出。
第1项是很容易的,首先做一个固定mkdir -p
。
第2项是不是一个问题,如果我们只部署master
,或者如果我们不介意新的克隆可能检查出的分支otherbranch
自动。 但是,我们可以通过使用不同形式的修复git checkout
。 我们可以添加-f
以及修复3项。
git --work-tree=/deploy/$branch checkout -f $branch -- .
这一切都引入了一个新的问题,虽然,这与第4项一起去。
第4项是最棘手的。 当你检出不 -- .
最后,让你切换分支机构,Git就会更新它的索引(暂存区)文件来跟踪什么已经在工作树。 然后,当你做一个新git checkout
,它取代了以前的一个,它可以告诉哪些文件可以被单独留在家中,哪些必须的,如果任何被删除,哪些必须重写或添加。 一些部署脚本(即检查出一个分支,像master
)依赖此行为。
如果我们切换部署代码来使用-- .
形式,混帐仍然更新索引,但不会为我们删除文件。 这意味着我们需要清洁的是走了的文件。 (它也卷起做出很杂乱指数,但通常这是确定:这是一个--bare
库,没有人,无论如何作品。)
清理出恰到好处的文件是棘手的。 我们可以用$oldsha
方法,比较新旧和提交,以确定哪些文件删除。 或者,我们可以简单地吹走/deploy/$branch
目录完全:
rm -rf /deploy/$branch
mkdir /deploy/$branch
git --work-tree=/deploy/$branch checkout -f $branch -- .
这通常就足够了。 它仍然有一个错误:有当旧部署的版本已经被删除,而新部署的版本正在建立起来的,当事情是在deploy目录乱七八糟一小段时间。 但有时这是确定。
周围切换顺序,我们可以主要-修复bug:做一个新的空目录,填充它,然后mv
新目录到位( mv
荷兰国际集团旧的方式进行),然后才rm -rf
的(moved-僻)旧的。 目前仍然在此期间,deploy目录不存在一个小窗户,但它是尽可能小。 (嗯,有一个潜在的与符号链接完全关闭它。见下面的评论)
还有最后一个窍门,我们可以做的,这是我从来没有实际测试:我们可以得到的git做的大部分工作,通过使用不同的索引文件每个deploy目录。 Git使用$GIT_INDEX_FILE
,如果它被设置,或$GIT_DIR/index
如果不。 所以,如果我们设置GIT_INDEX_FILE=$GIT_DIR/index.$branch
,我们应该得到独一无二的特殊分支名称的文件。 然后我们就可以回去的“签出特定分支”形式git checkout
,让如果需要的话它删除文件。
最后这个方法打开不一致窗宽一点:如果Git有删除十几文件和更新或创建另一个100个文件,不管是一个使用部署的版本有更多的机会看到部分去除并/或更新,因为git checkout
的进展。 但它是一个非常简单并且在工作树少“多余的动作”。
最后一个具有讽刺意味的沉思,因为它是
请注意,我们的deploy
功能建立了一个工作树或几种也许有,如果我们有多个分支机构部署,作为文字git的工作树,甚至可能使用$GIT_WORK_TREE
。 然后,它则会覆盖无论是在这项工作的树,在有趣的分支的最新版本替换它。 这正是我们所说的是烦人,后面的“背景”部分。 这是完全没有干扰,它只是我们所希望的!
嗯,有点。 关于这项工作的树的好处,VS裸仓库,就是你可以不小心cd /deploy/master
,看到一个.git
目录,并开始它的工作。 没有 .git
此目录。 尽管如此,“工作目录这里”加“裸仓库存在”的组合真的只是等于“定期,非纯仓库”,几乎在每一个感觉。