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

时间:2017-09-07 17:24:07

标签: git bash git-branch gitolite git-commands

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

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

首先:如何将不同的工作树复制到不同的文件夹中? 第二:如果"功能 - "我该如何自动化这个过程?和"修补程序 - "分支机构不断改变名称?

这与git hook无关,这应该是一个在cron作业触发的不同服务器上运行的脚本。

3 个答案:

答案 0 :(得分:3)

可怕的几个班轮:

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

让我们分解一下:

  1. 确保目标目录存在。可能对你没必要。
    mkdir -p /var/www/html

  2. 克隆git存储库并输入目录
    git clone --bare user@git-server:/your-repo.git

  3. 列出分支机构。这将从克隆目录运行。请注意,未使用git branch,因为在脚本中使用时可能会出现令人惊讶的输出 git for-each-ref --format='%(refname)' refs/heads/

  4. 过滤所需的分支。在您的情况下,模式可能类似于grep -E "(master)|(testing)|(feature-.*)"grep 'branch-pattern'

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

  6. 创建一个branchName变量,该变量是除了ref前缀之外的分支的名称。请注意,这是特定于bash的。
  7. git archive创建所选分支的tar存档,为所有条目添加分支名称前缀。存档被发送到标准输出
    git archive --format=tar --prefix="$branch/" "$branch"

  8. 立即将存档提取到目标位置
    tar -C/var/www/html -x

答案 1 :(得分:2)

首先,您需要一个分支列表。出于脚本目的,最适合使用的命令是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来撤消您不想要的工作,这应该 更高效。 {1}}首先要做。)

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

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 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
  git reset --hard HEAD
done

你也可以 使用git worktree prune 而不是直接搜索worktree目录 - 这在奇怪的情况下可能更好,例如(再次)命名空间分支。

答案 2 :(得分:2)

<块引用>

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

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

该答案以:

<块引用>

您也可以使用 git worktree list --porcelain 而不是直接搜索工作树目录 - 这在奇怪的情况下可能更可取,例如(再次)命名空间分支。

实际上,您应该,尤其是使用 Git 2.31(2021 年第一季度):git worktree list(man) 现在将工作树注释为可修剪,在 {{ 中显示锁定和可修剪的属性1}} 模式,并获得了 --porcelain 选项。

参见 commit 076b444commit 9b19a58commit 862c723commit 47409e7(2021 年 1 月 27 日)和 commit eb36135commit fc0c7d5、{{3} }(2021 年 1 月 19 日)作者:commit a29a8b7
(2021 年 2 月 10 日在 Rafael Silva (raffs)Junio C Hamano -- gitster -- 合并)

<块引用>

commit 02fb216:教--verbose详细模式

帮助:Eric Sunshine
签字人:拉斐尔·席尔瓦
审核人:Eric Sunshine

<块引用>

"worktree"(git worktree list) 根据每个工作树的状态(例如可修剪或锁定)对其进行注释,但是为什么要注释这些工作树并不是很明显。
对于可修剪的工作树,一个由 list 返回的原因可用,对于锁定的工作树,一个原因可能由用户通过 should_prune_worktree() 命令提供。

让我们教“lock”一个 git worktree list 模式,输出工作树被注释的原因。 原因是文本几乎可以采用任何大小,并且将文本附加到默认的分栏格式将使得难以使用其他注释扩展命令并且不能很好地适应屏幕。
为了解决这个缺点,然后将注释移到下一行,缩进后跟原因。如果原因不可用,则注释与工作树本身保持在同一行。

带有详细信息的“--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 ... 现在包含在其 man 中:

<块引用>

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

git worktree

注意,如果附加的注释被移动到下一行 信息可用,否则它与 工作树本身。

还有:

<块引用>

man page:教$ 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 注释可修剪的工作树

帮助:Eric Sunshine
签字人:拉斐尔·席尔瓦
审核人:Eric Sunshine

<块引用>

worktree(git worktree list) 命令显示工作树的绝对路径、检出的提交、分支名称和“ list" 注释如果工作树被锁定,但是,它不指示工作树是否可修剪。

除非指定了 locked 选项,否则“修剪”命令将删除可修剪的工作树。
这可能会导致工作树被删除,而用户没有意识到为时已晚,例如,如果用户忘记传递 --dry-run
如果“list”命令显示哪个工作树是可修剪的,用户可以在运行“man(git worktree prune) 之前进行验证,并希望防止工作树被意外删除最坏的情况。

让我们教“--dry-run”显示工作树何时是默认格式和瓷器格式的可修剪候选者。

在默认格式中,附加了“可修剪”文本:

git worktree list

$ git worktree list /path/to/main aba123 [main] /path/to/linked 123abc [branch-a] /path/to/prunable ace127 (detached HEAD) prunable 格式中,添加了一个可修剪的标签,并附有其原因:

--porcelain

$ git worktree list --porcelain ... worktree /path/to/prunable HEAD abc1234abc1234abc1234abc1234abc1234abc12 detached prunable gitdir file points to non-existent location ... 现在包含在其 man 中:

<块引用>

分支当前已签出(如果没有,则为“分离的 HEAD”),如果为“已锁定” 工作树被锁定,如果工作树可以被git worktree修剪,则“可修剪” 命令。

prune 现在包含在其 man page 中:

<块引用>

该命令还根据其状态显示每个工作树的注释。 这些注释是:

  • git worktree,如果工作树被锁定。
  • locked,如果可以通过 prunable 修剪工作树。
git worktree prune