Php GIT post接收更多分支的钩子-工作流还是时间戳问题?

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与开发分支合并,然后

我在同一台服务器上有一个开发和生产文件夹,后面有一个repo,可以根据所推送的分支推送到这两个文件夹。我希望在将dev推送到repo时部署开发(测试)文件夹,在推送到master时部署生产文件夹(www)

这是可行的,但我有重写所有文件的问题,而不仅仅是那些已更改的文件

示例:

  • 我在本地开发分支,只对index.php文件进行更改,提交, 推送-更改部署在do development文件夹中,仅使用 index.php已更改(新文件时间戳)
  • 下一步:git签出主机,git与开发分支合并,然后
    推送到主文件夹-更改已正确部署到生产文件夹, 但不仅index.php被更改,FTP上的所有文件都有新的
    时间戳

  • 下一步:git签出dev,对fileX.php进行一些更改,提交并推送到dev-更改被正确地部署到dev文件夹,但FTP上的所有文件都有新的时间戳,而不仅仅是fileX.php

这是正常的还是我做错了什么?如果我有一台本地PC和一个git-1开发域和一个生产域,你能推荐一个更好的git工作流吗

谢谢你的帮助

后接钩:

#!/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