git worktree
命令:新的工作目录与当前仓库相连,共享除HEAD、index等工作目录特有的文件之外的一切内容。
但文档还指出:
…对子模块的支持不完整。不建议对超级项目进行多次检出。
没有进一步解释会出现什么问题。
有人能为我解释一下可能遇到的问题吗?例如,如果我只在这种方式生成的单独工作树中进行不影响子模块的更改,那么我是否安全?
git worktree
命令:提交 a83a66a 很清楚:
git-submodule.sh
期望$GIT_DIR/config
至少对于submodule.* 部分
是每个工作树,这里我认为我们有两个选择:
- 要么更新
config.c
以便除了读取共享的$GIT_DIR/config
外,还要读取每个工作树特定的$GIT_DIR/config.worktree
并将工作树特定变量存储在新位置,- 要么更新
git-submodule.sh
直接从每个工作树的$GIT_DIR/config.submodule
中直接读写submodule.*
。这些需要时间来适当地解决。同时,请注意告知用户不要在子模块上下文中使用多个工作树。
更普遍地说,应该把这些子模块放在哪里?
有几个选项:$SUB
子仓库保留在其他地方(例如集中位置),而不是 $SUPER
中。对于嵌套子模块也是如此,其中一个超级项目可能是另一个超级项目的子模块。$SUB
子仓库都放在 $SUPER/modules
(或 $SUPER
的其他位置)中。$SUB
子仓库合并到 $SUPER
中,而不是将它们单独存储。但这至少需要启用 ref 命名空间。这个提交是对commit df56607的回答。
从git用户的角度来看,这意味着git submodule update --init --recursive
不知道精确地在哪里检出子模块。
它们是分布在所有工作树上,还是集中在某个地方?目前尚未正式指定。
motherrepo.git/worktree/<worktreename>/modules/<submodule>
下),因此如果您有一个大的子模块,则面临严重的磁盘使用问题。
处理子树中的子模块的Git别名:
别名 git wtas
需要全局定义git wta
,或者至少对所有涉及的仓库都进行定义。不包含任何保证。如果您的路径名称中有空格,您最喜欢的宠物可能会感染疼痛的感染。
它期望您的仓库结构与子模块初始化的非裸仓库中的结构相同,因此如果您有一个裸仓库,则必须模仿该设置。具有名称(而不是路径)foo
的子模块位于<your-.git-directory>/modules/foo
中(而不是.../foo.git
)。如果某个模块在仓库中不存在,它将不会崩溃,而只是跳过它。
还有改进的空间。它无法处理子模块内的子模块,它只能向下一级。尝试将子模块git wta
调用更改为git wtas
调用可能有效,但我尚未验证。
-- clacke
另请参阅git worktree move
(使用 Git 2.17+,2018年第二季度可用)。
实际上,在Git 2.21之前(2019年第一季度),当涉及子模块时,"git worktree remove
"和"git worktree move
"会拒绝工作。
现在已经放宽了对未初始化子模块的限制。
请参见提交00a6d4d(由Nguyễn Thái Ngọc Duy (pclouds
)于2019年1月5日提交)。
(由Junio C Hamano -- gitster
--合并于提交726f89c,2019年1月18日)
worktree
: allow to (re)move worktrees with uninitialized submodulesUninitialized submodules have nothing valuable for us to be worried about. They are just SHA-1.
Let "worktree remove
" and "worktree move
" continue in this case so that people can still use multiple worktrees on repos with optional submodules that are never populated, likesha1collisiondetection
ingit.git
when checked out bydoc-diff
script.Note that for "
worktree remove
", it is possible that a user initializes a submodule (*
), makes some commits (but not push), then deinitializes it.
At that point, the submodule is unpopulated, but the precious new commits are still in:
$GIT_COMMON_DIR/worktrees/<worktree>/modules/<submodule>
directory and we should not allow removing the worktree or we lose those commits forever.
The new directory check is added to prevent this.(
*
) yes they are screwed anyway by doing this since "git submodule
" would addsubmodule.*
in$GIT_COMMON_DIR/config
, which is shared across multiple worktrees.
But it does not mean we let them be screwed even more.
在 Git 2.25 之前(2020 年第一季度),如果你设置了 submodule.recurse
配置选项,在已初始化子模块的超级项目中执行 git worktree add
将会失败。
参见 提交 4782cf2ab6(由 Philippe Blain (phil-blain
) 于 2019 年 10 月 27 日提交)
(由 Junio C Hamano -- gitster
-- 合并于 提交 726f89c,2019 年 12 月 1 日)
worktree
: 教授 "add
" 忽略 submodule.recurse
配置"worktree add
" 内部调用 "reset --hard
",但如果设置了 submodule.recurse
,reset
尝试递归到已初始化的子模块,这使得 start_command
尝试进入不存在的子模块路径并死亡。
通过确保 "worktree add
" 中对 reset
的调用不进行递归来解决此问题。
较早版本的解决方法是暂时禁用配置:
git -c submodule.recurse=0 worktree add ...
在 Git 2.26 之前(2020 年第二季度),在初始化子模块的仓库的链接工作树中执行 git checkout --recurse-submodules
(或 reset
或 read-tree
)会错误地移动主工作树 git 仓库中的子模块 HEAD,并清除链接工作树中子模块的工作目录中的 .git
gitfile:
查看 提交 a9472afb63(2020年1月21日)由Philippe Blain (phil-blain
)完成。
(由Junio C Hamano -- gitster
--合并于提交 ff5134b2,2020年2月5日)
submodule.c
: 使用get_git_dir()
替代get_git_common_dir()
自从 df56607 (git-common-dir: make "
modules/
" 为每个工作目录的目录,2014-11-30) 以来, 链接工作树中的子模块被克隆到$GIT_DIR/modules
,即$GIT_COMMON_DIR/worktrees/<name>/modules
。然而,当工作树更新命令
checkout
、reset
和read-tree
学会递归进入子模块时, 并没有遵循这种约定。具体来说,submodule.c::submodule_move_head
(在 6e3c159 中引入)和submodule.c::submodule_unset_core_worktree
(在 898c2e6 中重新引入)使用get_git_common_dir()
而不是get_git_dir()
来获取子模块存储库的路径。这意味着,例如,在链接工作树中执行 '
git checkout --recurse-submodules <branch>
' 将正确地检出<branch>
,将子模块的 HEAD 分离到记录在<branch>
中的提交,并更新子模块的工作树, 但将移动的子模块 HEAD 是在$GIT_COMMON_DIR/modules/<name>/
中的, 即主超级项目工作树的子模块存储库。它还将重写链接工作树中子模块工作树中的 gitfile, 将其指向$GIT_COMMON_DIR/modules/<name>/
。这导致了主超级项目工作树中子模块工作树中的不正确(和令人困惑!)状态。此外,如果切换到不存在子模块的提交,则会调用
submodule_unset_core_worktree
并错误地从主超级项目工作树的子模块配置文件$GIT_COMMON_DIR/modules/<name>/config
中删除 'core.wortree
'。通过在
submodule_move_head
和submodule_unset_core_worktree
中都使用get_git_dir()
构建子模块存储库的路径来修复此问题。
motherrepo.git/worktree/<worktreename>/modules/<submodule>
下),因此如果您有一个大的子模块,您将面临一些严重的磁盘使用问题。 - clacke$GIT_COMMON_DIR/modules/<submodule>
中,并将管理文件存储在$GIT_COMMON_DIR/worktrees/<worktree>/modules/<submodule>
中。这样,工作目录将是独立的,而不会重复存储其子模块的对象。 - ScumCoder