Php GIT post接收更多分支的钩子-工作流还是时间戳问题?
我在同一台服务器上有一个开发和生产文件夹,后面有一个repo,可以根据所推送的分支推送到这两个文件夹。我希望在将dev推送到repo时部署开发(测试)文件夹,在推送到master时部署生产文件夹(www) 这是可行的,但我有重写所有文件的问题,而不仅仅是那些已更改的文件 示例:Php GIT post接收更多分支的钩子-工作流还是时间戳问题?,php,git,timestamp,branch,workflow,Php,Git,Timestamp,Branch,Workflow,我在同一台服务器上有一个开发和生产文件夹,后面有一个repo,可以根据所推送的分支推送到这两个文件夹。我希望在将dev推送到repo时部署开发(测试)文件夹,在推送到master时部署生产文件夹(www) 这是可行的,但我有重写所有文件的问题,而不仅仅是那些已更改的文件 示例: 我在本地开发分支,只对index.php文件进行更改,提交, 推送-更改部署在do development文件夹中,仅使用 index.php已更改(新文件时间戳) 下一步:git签出主机,git与开发分支合并,然后
- 我在本地开发分支,只对index.php文件进行更改,提交, 推送-更改部署在do development文件夹中,仅使用 index.php已更改(新文件时间戳)
- 下一步:git签出主机,git与开发分支合并,然后
推送到主文件夹-更改已正确部署到生产文件夹, 但不仅index.php被更改,FTP上的所有文件都有新的
时间戳 - 下一步:git签出dev,对fileX.php进行一些更改,提交并推送到dev-更改被正确地部署到dev文件夹,但FTP上的所有文件都有新的时间戳,而不仅仅是fileX.php
#!/bin/sh
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
if [ "master" == "$branch" ]; then
git --work-tree=/home/www/domain.com/subdomains/www --git-dir=/home/www/domain.com/subdomains/repos/myrepo.git checkout master -f
echo 'changes pushed to production'
else
git --work-tree=/home/www/domain.com/subdomains/test--git-dir=/home/www/domain.com/subdomains/repos/myrepo.git checkout dev -f
echo 'changes pushed to dev'
fi
done
这根柱子的挂钩有严重缺陷。好消息是它很容易修复 具体问题的根源在于,每个Git存储库,包括在这里接收推送的裸存储库,都从一个(只有一个)索引开始。该索引跟踪(单个工作树,就像在一个工作树中一样)。这是正确的,即使裸存储库的全部要点是没有工作树:它仍然有一个索引 当您使用
git--work tree=
与这个裸存储库一起执行git签出操作时,该签出操作使用(一个,单个)索引来跟踪它在(临时添加的)工作树中存储的内容。也就是说,在git checkout
期间,这个裸存储库变为非裸存储库:它有一个索引和一个工作树,工作树是为这个git checkout
操作选择的
对于每个后续的git--worktree=checkout
操作,git将假定索引正确地描述了目标工作树的当前签出。(Git在工作时可能会发现索引没有正确地描述目标工作树,但它一开始是假设它正确地描述了目标工作树。)Git决定在该工作树中更新的文件将基于此假设,并可能(但不总是)插入一些更正。这个主要假设,即索引正确地描述了当前对工作树的签出,当且仅当后续的git签出中使用的path
参数与之前的git签出中使用的path
参数相同时成立
但是我们有两个不同的git checkout
命令:
git --work-tree=/home/www/domain.com/subdomains/www ...
以及:
(此处略作旁白:由于--git dir
选项与--work tree
融合,上面的剪切粘贴出现了一些问题;我在这里提出了自己的修复设想)
这是两条不同的道路。因此,它们需要两个不同的索引文件,或者根本不需要索引
1A bare repository是一个Git存储库,其中core.bare
设置为true
。裸存储库没有工作树,其Git数据库文件存储在顶层,而不是单独的.Git
目录下
2当没有索引时,如在初始的git签出中,git将根据需要构建一个索引。这是计算密集型的,在一个非裸存储库中,我们实际上使用索引来构建下一次提交,破坏索引会丢失我们精心构建的下一次提交:Git再次从当前提交构建新的提交,因此我们必须重新开始
工作树本身不受此重建过程的影响,但是如果我们能够为每个工作树提供一个索引文件的空间,并且索引文件通常非常小,那么我们似乎应该这样做。不过,如果你愿意的话,这也是一种选择
解决问题
首先,尽管这不是真正相关的问题,但让我们解决另一个明显(但很小)的问题:
假设我们添加一个名为master/v1.1
的标记。此ref的完整拼写为名称refs/tags/master/v1.1
。让我们看看我们在这里得到了什么:
$ ref=refs/tags/master/v1.1
$ branch=`echo $ref | cut -d/ -f3`
$ echo $branch
master
哎呀:当我们添加标签master/v1.1
时,我们的代码会认为我们已经更新了分支master
。我们可能不会使用这样的标签,但为什么不正确地使用呢?与其使用cut
,不如检查整个参考:
案例中的$ref
refs/heads/*)分支=${ref#refs/heads/};;
*)继续;#没有分支
以撒
使用我们的测试参考进行测试,我们得到:
中的$case$ref
>refs/heads/*)分支=${ref#refs/heads/};;
>*)不是分支;;
>以撒
没有分支
将ref
替换为refs/heads/master
我们得到:
$ref=refs/heads/master
$case$ref in
refs/heads/*)分支=${ref#refs/heads/};;
*)不呼应树枝;;
以撒
$echo$branch
主人
(本节中没有PS2
输出,因为我使用control-p重做了前面的case
)
对于真正的正确性,我们还应该查看$old
和$new
,以确定正在创建、更新或删除的ref;但是在这种情况下,我们可以假设分支名称master
和dev
永远不会被删除。因此,我们的新代码如下:
#/垃圾箱/垃圾箱
当读取oldrev newrev ref时
做
案例$ref in
refs/heads/*)分支=${ref#refs/heads/};;
*)继续;#不是一个分支-不要删除
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
$ ref=refs/tags/master/v1.1
$ branch=`echo $ref | cut -d/ -f3`
$ echo $branch
master
git symbolic-ref HEAD refs/heads/master