"master" "testing" "feature-featurename" "hotfix-number"
。这些分支中的每一个都应该复制其工作树到/var/www/html/branchname
。
首先:如何将不同的工作树复制到不同的文件夹中?
其次:如果“feature-”和“hotfix-”分支名称经常更改,如何自动化此过程?
这与git挂钩无关,这应该是在不同服务器上运行的脚本,并由cron job触发。"master" "testing" "feature-featurename" "hotfix-number"
。这些分支中的每一个都应该复制其工作树到/var/www/html/branchname
。
首先:如何将不同的工作树复制到不同的文件夹中?
其次:如果“feature-”和“hotfix-”分支名称经常更改,如何自动化此过程?
这与git挂钩无关,这应该是在不同服务器上运行的脚本,并由cron job触发。可怕的几行代码:
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
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
变量。branchName
变量,它是不包括ref前缀的分支名称。请注意,这是特定于bash的。git archive
创建所选分支的tar归档文件,并使用分支名称作为所有条目的前缀。将存档发送到标准输出。git archive --format=tar --prefix="$branch/" "$branch"
8. 立即将档案提取到其目标位置。tar -C/var/www/html -x
git worktree list --porcelain
代替直接搜索工作树目录 - 在特殊情况下(例如命名空间分支)这可能更可取。git worktree list --porcelain -z
实际上,你应该这样做,特别是在 Git 2.31(2021年第一季度)之后:git worktree list
(man) 现在将工作树标注为可清除的,在 --porcelain
模式下显示锁定和可清除属性,并增加了一个 --verbose
选项。
请查看提交 076b444, 提交 9b19a58, 提交 862c723, 提交 47409e7 (2021年1月27日),以及提交 eb36135, 提交 fc0c7d5, 提交 a29a8b7(2021年1月19日)由Rafael Silva (raffs
)撰写。
(已在提交02fb216(2021年2月10日)中由Junio C Hamano -- gitster
--合并)
worktree
: 教授list
的详细模式协助者:Eric Sunshine
签署者:Rafael Silva
审查者:Eric Sunshine
"
git worktree list
"(man) annotates each worktree according to its state such as prunable or locked, however it is not immediately obvious why these worktrees are being annotated.
For prunable worktrees a reason is available that is returned byshould_prune_worktree()
and for locked worktrees a reason might be available provided by the user vialock
command.Let's teach "
git worktree list
" a--verbose
mode that outputs the reason why the worktrees are being annotated.
The reason is a text that can take virtually any size and appending the text on the default columned format will make it difficult to extend the command with other annotations and not fit nicely on the screen.
In order to address this shortcoming the annotation is then moved to the next line indented followed by the reason If the reason is not available the annotation stays on the same line as the worktree itself.The output of "
git worktree list
" with verbose becomes like so:$ 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
现在在其手册页面中包含:
For these annotations, a reason might also be available and this can be seen using the verbose mode. The annotation is then moved to the next line indented followed by the additional information.
$ 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
Note that the annotation is moved to the next line if the additional information is available, otherwise it stays on the same line as the working tree itself.
并且:
worktree
: 教授list
如何注释可修剪的工作树协助者:Eric Sunshine
签名者:Rafael Silva
审核者:Eric Sunshine
The "
git worktree list
"(man) command shows the absolute path to the worktree, the commit that is checked out, the name of the branch, and a "locked
" annotation if the worktree is locked, however, it does not indicate whether the worktree is prunable.The "prune" command will remove a worktree if it is prunable unless
--dry-run
option is specified.
This could lead to a worktree being removed without the user realizing before it is too late, in case the user forgets to pass--dry-run
for instance.
If the "list" command shows which worktree is prunable, the user could verify before running "git worktree prune
"(man) and hopefully prevents the working tree to be removed accidentally on the worse case scenario.Let's teach "
git worktree list
" to show when a worktree is a prunable candidate for both default and porcelain format.In the default format a "prunable" text is appended:
$ git worktree list /path/to/main aba123 [main] /path/to/linked 123abc [branch-a] /path/to/prunable ace127 (detached HEAD) prunable
In the
--porcelain
format a prunable label is added followed by its reason:$ git worktree list --porcelain ... worktree /path/to/prunable HEAD abc1234abc1234abc1234abc1234abc1234abc12 detached prunable gitdir file points to non-existent location ...
git worktree
现在在其手册页面中包括:
当前检出的分支(如果没有,则为“分离的HEAD”),如果工作树被锁定,则为“已锁定”,如果可以通过
prune
命令修剪工作树,则为“可修剪”。
git worktree
现在在其手册页面中包括:
The command also shows annotations for each working tree, according to its state. These annotations are:
locked
, if the working tree is locked.prunable
, if the working tree can be pruned viagit worktree prune
.$ git worktree list /path/to/linked-worktree abcd1234 [master] /path/to/locked-worktreee acbd5678 (brancha) locked /path/to/prunable-worktree 5678abc (detached HEAD) prunable
在 Git 2.36(2022年第二季度)之前, "git worktree list --porcelain
"(man) 没有正确引用路径名和锁定原因的不安全字节,通过引入以“-z”结尾的输出格式进行解决。
请参见 提交 d97eb30 (2022年3月31日) 由Phillip Wood (phillipwood
)。
(由Junio C Hamano -- gitster
--合并于提交 7c6d8ee,2022年4月4日)
为了处理包含换行符的工作树路径,现在在
工作树
:为列表子命令添加-z选项签署人:Phillip Wood
git worktree
中添加了一个-z
选项,用于与--porcelain
一起使用并提供NUL终止的输出。由于'worktree list --porcelain'不会引用工作树路径,因此这使得它能够处理包含换行符的工作树路径。现在git worktree
的man page中推荐将其与-z
结合使用。当使用--porcelain
和list
时,将每行以NUL而不是换行符终止,这样可以解析包含换行符的工作树路径的输出。
git worktree
现在在其man page中包括:
瓷器格式每个属性占一行。
如果给出
-z
,则行以NUL而不是换行符终止。
首先你需要一个分支列表。为了脚本化的目的,最好使用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 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
您还可以使用git worktree list --porcelain
而不是直接搜索工作树目录-在一些奇怪的情况下,这可能更可取,比如(再次)命名空间分支。
.git
实际上是一个文本文件,指向.git/worktree/foo
目录,而不是它自己的元数据目录;但仍然有一定用途。) - Mark Adelsberger
archive
将每个分支打成tar包,然后再让tar
程序撤销此步骤。其次,它必须为每个分支复制整个工作树,因为它绕过了git仅更新已更改内容的能力。还有一件事-与性能无关,但是...branch
不是用于脚本列出分支的最佳命令。 - Mark Adelsberger