Git获取单独文件夹中每个分支的工作树-Bash

Git获取单独文件夹中每个分支的工作树-Bash,bash,git-branch,gitolite,git,Bash,Git Branch,Gitolite,Git,我需要编写一个bash脚本,每小时将存储库分支复制到本地linuxweb服务器上 我们有一个git远程存储库(gitolite),其分支名为“master”“testing”“feature featurename”“hotfix number” 每个分支都应该将其工作树复制到/var/www/html/branchname 首先:如何将不同的工作树复制到不同的文件夹中? 第二:如果“功能”和“修补程序”分支不断更改名称,我如何实现此过程的自动化 这与git钩子无关,它应该是运行在不同服务器上的

我需要编写一个bash脚本,每小时将存储库分支复制到本地linuxweb服务器上

我们有一个git远程存储库(gitolite),其分支名为
“master”“testing”“feature featurename”“hotfix number”
每个分支都应该将其工作树复制到
/var/www/html/branchname

首先:如何将不同的工作树复制到不同的文件夹中? 第二:如果“功能”和“修补程序”分支不断更改名称,我如何实现此过程的自动化

这与git钩子无关,它应该是运行在不同服务器上的脚本,由cron作业触发。

mkdir -p /var/www/html
git clone --bare user@git-server:/your-repo.git && cd your-repo.git

git for-each-ref --format='%(refname)' refs/heads/ | grep 'branch-pattern' | while read branchRef; do
  branchName=${branchRef#refs/heads/}
  git archive --format=tar --prefix="$branchName/" "$branchRef" | tar -C/var/www/html -x
done
让我们把它分解一下:

  • 确保目标目录存在。您可能不需要。

  • 克隆git存储库并输入目录

  • 列出分支。这将从克隆目录运行。请注意,没有使用该选项,因为在脚本中使用该选项时可能会产生令人惊讶的输出。

  • 筛选所需的分支。在您的例子中,模式可能类似于
    grep-E“(master)|(testing)|(feature-.*)”

  • while
    语句读取每个分支名称并将其分配给
    branch
    变量

  • 创建一个
    branchName
    变量,该变量是不包括ref前缀的分支名称。注意,这是特定于bash的
  • git archive
    创建所选分支的tar归档,并在所有条目前面加上分支名称。存档将发送到标准输出

  • 立即将存档提取到其目标位置


  • 因此,首先需要一个分支列表。为了编写脚本,最好使用的命令是
    For each ref
    。假设您只需要本地分支名称,请使用

    git for-each-ref refs/heads/* |cut -d\/ -f3
    
    另一方面,上面命令中的两件事假设您在“名称空间”中不使用分支。如果您使用包含
    /
    的分支名称,如
    qa/feature-1
    -那么这会改变一些事情。上面的命令只会变为

    git for-each-ref refs/heads |cut -d\/ -f3-
    
    但更大的问题是,您可能需要更多地考虑分支名称应该如何映射到目录名。所以现在我将继续假设分支名称不包含
    /

    您需要处理每个分支,因此

    git for-each-ref refs/heads/* |cut -d\/ -f3 |while read branch; do
      # ... will process each branch here
    done
    
    现在,您可以使用
    git-worktree
    简化单个签出。(请注意,这应该比使用
    archive
    为每个分支复制整个提交内容,然后调用
    tar
    撤消您最初不希望
    archive
    执行的工作更有效。)

    确保定义了所有必需的工作树

    git for-each-ref refs/heads/* |cut -d\/ -f3 |while read branch; do
      if [ ! -d .git/worktrees/$branch ]; then
        git worktree add /var/www/html/$branch $branch
      fi
    done
    
    现在关于这一点的一件事是,当分支移动时(即,当接收到推送时),它会使工作树“不同步”,因此您似乎已经对推送所做的每个更改进行了“撤消”。(默认工作树的保护似乎不适用。)

    但这似乎符合你的要求;另一种方法是,当推送进来时更新目录,在描述问题时,您会拒绝这样做。因此,在这种情况下,脚本应该通过“取消撤消”将工作树与新更改同步

    当然,有时树枝会脱落;如果不想使用过时的工作树元数据,可以添加

    git worktree prune
    
    您还可以使用
    git worktree list--
    而不是直接搜索worktree目录,这在一些奇怪的情况下(同样)可能更可取,比如命名空间分支

    如何将不同的工作树复制到不同的文件夹中

    这是通过git worktree完成的,如的所示

    这一答案的结尾是:

    您还可以使用
    git worktree list--
    而不是直接搜索worktree目录,这在一些奇怪的情况下(同样)可能更可取,比如命名空间分支

    实际上,您应该,特别是在Git2.31(2021年第1季度)中:()现在将工作树注释为可修剪的,在
    --cerial
    模式下显示锁定和可修剪的属性,并获得了
    --verbose
    选项

    参见,,(2021年1月27日)和,(2021年1月19日)作者 (于2021年2月10日合并)

    :设定
    列表
    详细模式
    帮助人:Eric Sunshine
    签字人:拉斐尔·席尔瓦
    审核人:Eric Sunshine

    “”()根据每个工作树的状态(如可修剪或已锁定)对其进行注释,但是不清楚为什么要对这些工作树进行注释。
    对于可修剪的工作树,
    should\u prune\u worktree()
    返回一个原因,对于锁定的工作树,用户可以通过
    lock
    命令提供一个原因

    让我们来教“
    git worktree list
    ”一种
    --verbose
    模式,该模式输出注释工作树的原因。
    原因是文本几乎可以采用任何大小,如果将文本附加到默认的列格式,则很难使用其他注释扩展命令,并且无法很好地显示在屏幕上。
    为了解决这个缺点,注释被移动到下一行缩进,后面跟着原因。如果原因不可用,注释将与工作树本身保持在同一行上

    带有verbose的“
    git worktree list
    ”的输出如下:

    $ git worktree list --verbose
    ...
    /path/to/locked-no-reason    acb124 [branch-a] locked
    /path/to/locked-with-reason  acc125 [branch-b]
        locked: worktree with a locked reason
    /path/to/prunable-reason     ace127 [branch-d]
        prunable: gitdir file points to non-existent location
    ...
    
    git worktree
    现在在其

    对于这些注释,可能还有一个原因,这可能是 使用详细模式查看。然后将注释移动到下一行 缩进,后跟附加信息

    $ git worktree list --verbose
    /path/to/linked-worktree              abcd1234 [master]
    /path/to/locked-worktree-no-reason    abcd5678 (detached HEAD) locked
    /path/to/locked-worktree-with-reason  1234abcd (brancha)
    locked: working tree path is mounted on a portable device
    /path/to/prunable-worktree            5678abc1 (detached HEAD)
    prunable: gitdir file points to non-existent location
    
    请注意,如果附加注释被删除,注释将移动到下一行 信息一
    $ git worktree list --verbose
    /path/to/linked-worktree              abcd1234 [master]
    /path/to/locked-worktree-no-reason    abcd5678 (detached HEAD) locked
    /path/to/locked-worktree-with-reason  1234abcd (brancha)
    locked: working tree path is mounted on a portable device
    /path/to/prunable-worktree            5678abc1 (detached HEAD)
    prunable: gitdir file points to non-existent location
    
    $ git worktree list
    /path/to/main      aba123 [main]
    /path/to/linked    123abc [branch-a]
    /path/to/prunable  ace127 (detached HEAD) prunable
    
    $ git worktree list --porcelain
    ...
    worktree /path/to/prunable
    HEAD abc1234abc1234abc1234abc1234abc1234abc12
    detached
    prunable gitdir file points to non-existent location
    ...
    
    $ git worktree list
    /path/to/linked-worktree    abcd1234 [master]
    /path/to/locked-worktreee   acbd5678 (brancha) locked
    /path/to/prunable-worktree  5678abc  (detached HEAD) prunable