我需要编写一个bash脚本,每小时将我们的存储库分支复制到我们的本地linux Web服务器上。
我们有一个git远程存储库(gitolite),其分支名为"master" "testing" "feature-featurename" "hotfix-number"
这些分支中的每一个都应该将其工作树复制到/var/www/html/branchname
首先:如何将不同的工作树复制到不同的文件夹中? 第二:如果"功能 - "我该如何自动化这个过程?和"修补程序 - "分支机构不断改变名称?
这与git hook无关,这应该是一个在cron作业触发的不同服务器上运行的脚本。
答案 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
让我们分解一下:
确保目标目录存在。可能对你没必要。
mkdir -p /var/www/html
克隆git存储库并输入目录
git clone --bare user@git-server:/your-repo.git
列出分支机构。这将从克隆目录运行。请注意,未使用git branch
,因为在脚本中使用时可能会出现令人惊讶的输出
git for-each-ref --format='%(refname)' refs/heads/
过滤所需的分支。在您的情况下,模式可能类似于grep -E "(master)|(testing)|(feature-.*)"
等
grep 'branch-pattern'
while
语句读取每个分支名称并将其分配给branch
变量
branchName
变量,该变量是除了ref前缀之外的分支的名称。请注意,这是特定于bash的。 git archive
创建所选分支的tar存档,为所有条目添加分支名称前缀。存档被发送到标准输出
git archive --format=tar --prefix="$branch/" "$branch"
立即将存档提取到目标位置
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 Adelsberger 的 answer 所示。
该答案以:
<块引用>您也可以使用 git worktree list --porcelain
而不是直接搜索工作树目录 - 这在奇怪的情况下可能更可取,例如(再次)命名空间分支。
实际上,您应该,尤其是使用 Git 2.31(2021 年第一季度):git worktree list
(man) 现在将工作树注释为可修剪,在 {{ 中显示锁定和可修剪的属性1}} 模式,并获得了 --porcelain
选项。
参见 commit 076b444、commit 9b19a58、commit 862c723、commit 47409e7(2021 年 1 月 27 日)和 commit eb36135、commit fc0c7d5、{{3} }(2021 年 1 月 19 日)作者:commit a29a8b7。
(2021 年 2 月 10 日在 Rafael Silva (raffs
) 被 Junio C Hamano -- gitster
-- 合并)
--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
注意,如果附加的注释被移动到下一行 信息可用,否则它与 工作树本身。
还有:
<块引用>$ 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