自2015年7月以来,Git 2.5提议替代contrib/workdir/git-new-workdir
:git worktree
看看提交68a2e6a通过JUNIOÇ滨野(gitster
)。
该发行说明中提到:
替代方法contrib/workdir/git-new-workdir
不依赖于符号链接,而是通过使借方和借方彼此了解来使对象和引用的共享更加安全。
参见提交799767cc9(Git 2.5rc2)
这意味着您现在可以执行git worktree add <path> [<branch>]
创建<path>
并签<branch>
入。新的工作目录链接到当前存储库,共享除工作目录特定文件(如HEAD,索引等)外的所有git worktree
内容。该部分添加:
一个git仓库可以支持多个工作树,允许您一次签出多个分支。
使用git worktree add
,新的工作树与存储库关联。
与“ git init
”或“ git clone
” 准备的“主工作树”相对,该新工作树称为“链接工作树”。
存储库具有一个主工作树(如果不是裸存储库)和零个或多个链接的工作树。
细节:
每个链接的工作树在存储库的$GIT_DIR/worktrees
目录中都有一个私有子目录
。
私有子目录的名称通常是链接的工作树路径的基础名称,可能还会附加一个数字以使其唯一。
例如,当$GIT_DIR=/path/main/.git
命令git worktree add /path/other/test-next next
创建时:
- 在链接的工作树
/path/other/test-next
和
- 还创建一个
$GIT_DIR/worktrees/test-next
目录(或者$GIT_DIR/worktrees/test-next1
如果test-next
已经被占用)。
在链接的工作树中:
$GIT_DIR
设置为指向此私有目录(例如/path/main/.git/worktrees/test-next
,在示例中),并且
$GIT_COMMON_DIR
设置为指向主工作树$GIT_DIR
(例如/path/main/.git
)。
这些设置.git
在链接的工作树顶部目录中的文件中进行。
完成链接的工作树后,您只需删除它即可。
信息库中工作树的管理文件最终将被自动删除(请参阅gc.pruneworktreesexpire
中的git config
),或者您可以git worktree prune
在主工作树或任何链接的工作树中运行以清理所有过时的管理文件。
警告:还有一个git worktree
“ BUGS”部分需要注意。
对子模块的支持不完整。
不建议对一个超级项目进行多次检出。
注意:使用git 2.7rc1(2015年11月),您可以列出工作树。
见提交bb9c03b,提交92718b7,提交5193490,提交1ceb7f9,提交1ceb7f9,提交5193490,提交1ceb7f9,提交1ceb7f9(2015年10月8日),提交92718b7,提交5193490,提交1ceb7f9,提交1ceb7f9(2015年10月8日),提交5193490,提交1ceb7f9(2015年10月8日),提交1ceb7f9(2015年10月8日)和提交ac6c561(2015年10月2日),作者:Michael Rappazzo(rappazzo
)。
(由Junio C gitster
Hamano合并--在commit a46dcfb中,2015年10月26日)
worktree
:添加' list
'命令
“ git worktree list
”遍历工作树列表,并输出工作树的详细信息,包括工作树的路径,当前签出的修订和分支以及工作树是否裸露。
$ git worktree list
/path/to/bare-source (bare)
/path/to/linked-worktree abcd1234 [master]
/path/to/other-linked-worktree 1234abc (detached HEAD)
也提供瓷器格式选项。
瓷器格式每个属性都有一行。
- 属性用标签和值列出,并用单个空格分隔。
- 布尔属性(如“裸露”和“分离”)仅作为标签列出,并且仅当且仅当该值为true时才存在。
- 空行表示工作树的结尾
例如:
$ git worktree list --porcelain
worktree /path/to/bare-source
bare
worktree /path/to/linked-worktree
HEAD abcd1234abcd1234abcd1234abcd1234abcd1234
branch refs/heads/master
worktree /path/to/other-linked-worktree
HEAD 1234abc1234abc1234abc1234abc1234abc1234a
detached
注意:如果您移动工作树文件夹,则需要手动更新gitdir
文件。
见提交618244e(2016年1月22日),以及提交d4cddd6(2016年1月18日)由阮泰玉维战(pclouds
)。
协作者:Eric Sunshine(sunshineco
)。
(由Junio C gitster
Hamano合并--在commit d0a1cbc中,2016年2月10日)
git 2.8(2016年3月)中的新文档将包括:
如果移动链接的工作树,则需要更新gitdir
条目目录中的' '文件。
例如,如果链接的工作树移至/newpath/test-next
且其.git
文件指向/path/main/.git/worktrees/test-next
,则更新
/path/main/.git/worktrees/test-next/gitdir
为引用/newpath/test-next
。
删除分支时要小心:在git 2.9(2016年6月)之前,您可以删除另一个工作树中正在使用的分支。
当“ git worktree
”的特点是在使用,“ git branch -d
”允许了在另一个worktree签出一个分支删除。
参见Yamaguchi Kazuki()提交的f292244(2016年3月29日)。
协作者:Eric Sunshine()。(由Junio C Hamano合并--在commit 4fca4e3中,2016年4月13日)rhenium
sunshineco
gitster
branch -d
:拒绝删除当前已签出的分支
当当前工作树检出分支时,禁止删除该分支。
但是,当仅由其他工作树检出分支时,错误地删除会成功。
使用find_shared_symref()
来检查分支正在使用中,不仅与当前工作树的HEAD比较。
类似地,在git 2.9(2016年6月)之前,重命名在另一个工作树中签出的分支不会调整所述另一个工作树中的符号HEAD。
见提交18eb3a9(2016年4月8日),并提交70999e9,提交2233066(2016年3月27日),由山口和树(rhenium
)。
(通过合并JUNIOÇ滨野- gitster
-在提交741a694,2016年4月18日)
branch -m
:更新所有每个工作树的HEAD
重命名分支时,当前仅更新当前工作树的HEAD,但是它必须更新指向旧分支的所有工作树的HEAD。
这是当前行为,/ path / to / wt的HEAD未更新:
% git worktree list
/path/to 2c3c5f2 [master]
/path/to/wt 2c3c5f2 [oldname]
% git branch -m master master2
% git worktree list
/path/to 2c3c5f2 [master2]
/path/to/wt 2c3c5f2 [oldname]
% git branch -m oldname newname
% git worktree list
/path/to 2c3c5f2 [master2]
/path/to/wt 0000000 [oldname]
此修补程序通过在重命名分支时更新所有相关的工作树HEAD来解决此问题。
git 2.10(2016年第三季度)正式支持锁定机制
见提交080739b,提交6d30862,提交58142c0,提交346ef53,提交346ef53,提交58142c0,提交346ef53,提交346ef53(2016年6月13日),以及提交984ad9e,提交6835314由(2016年6月3日)阮泰玉维战(pclouds
)。
建议提供者:Eric Sunshine(sunshineco
)。
(由Junio C gitster
Hamano合并--在commit 2c608e0中,2016年7月28日)
git worktree lock [--reason <string>] <worktree>
git worktree unlock <worktree>
如果链接的工作树存储在并非始终挂载的便携式设备或网络共享上,则可以通过发出git worktree lock
命令来阻止修剪其管理文件,该命令可以选择指定--reason
以说明为什么锁定了工作树。
<worktree>
:如果工作树路径中的最后路径组件在工作树之间是唯一的,则可以用来标识工作树。
例如,如果您只需要在“ /abc/def/ghi
”和“ /abc/def/ggg
” 处工作树,则“ ghi
”或“ def/ghi
”足以指向先前的工作树。
GIT中2.13(Q2 2017)添加一个lock
选项在提交507e6e9(2017年4月12日)由阮泰玉维战(pclouds
)。
提出者:David Taylor(dt
)。
帮助:Jeff King(peff
)。
(通过合并JUNIOÇ滨野- gitster
-在提交e311597 4月26日2017)
创建工作树后,允许立即锁定它。
这有助于防止“ git worktree add; git worktree lock
”和“ git worktree prune
” 之间的竞争。
所以git worktree add' --lock
是相当于git worktree lock
后git worktree add
,但没有竞争条件。
Git 2.17+(Q2 2018)添加git worktree move
/ git worktree remove
:请参阅此答案。
Git 2.19(Q3 2018)添加了一个“ --quiet
”选项,以使“ git worktree add
”不再那么冗长。
参见Elia Pinto()提交371979c(2018年8月15日)。
帮助:MartinÅgren,Duy Nguyen()和Eric Sunshine()。(由Junio C Hamano合并--在commit a988ce9中,2018年8月27日)devzero2000
pclouds
sunshineco
gitster
worktree
:添加--quiet
选项
与其他命令一样,将' --quiet
'选项添加到。
“ ”是唯一受其影响的命令,因为除“ ” 以外的所有其他命令当前默认为静默。git worktree
git
add
list
请注意,“ git worktree add
”曾经用来“先在stat中找到一个可用名称,然后再进行mkdir
”,这很容易引起比赛。
Git 2.22(Q2 2019)已通过循环使用mkdir
和响应来解决EEXIST
此问题。
参见Michal Suchanek()的commit 7af01f2(2019年2月20日)。(通过合并JUNIOÇ滨野- -在提交20fe798,2019年4月9日)hramrach
gitster
worktree
:修复worktree add
种族
Git运行一个stat循环以查找可用的工作树名称,然后mkdir
对找到的名称进行处理。
将其mkdir
循环,以避免再次调用工作树,添加找到相同的免费名称并首先创建目录。
Git 2.22(2019年第二季度)修复了逻辑,以告知Git存储库是否具有工作树,以防止git branch -D
删除当前被错误检出的分支。
对于名称不寻常的存储库,此逻辑的实现已被破坏,不幸的是,如今这已成为子模块的规范。
请参阅Jonathan Tan()的commit f3534c9(2019年4月19日)。(通过合并JUNIOÇ滨野- -在提交ec2642a,2019年5月8日)jhowtan
gitster
代码提取请求178见解
worktree
:更新is_bare
启发式
git branch -D <name>
运行“ ”时,Git通常首先检查该分支当前是否已签出。
但是,如果该存储库的Git目录不在“ <repo>/.git
”时,则不会执行此检查,例如,如果该存储库是其Git目录存储为“ super/.git/modules/<repo>
” 的子模块,就是这种情况。
即使分支已签出,这也会导致该分支被删除。
这是因为get_main_worktree()
在工作树上的worktree.c
集合中is_bare
,仅使用试探法,即如果工作树的路径不以“ /.git
” 结尾,则仓库是裸露的,否则就不是裸露的。遵循启发式,
此is_bare
代码在92718b7中进行了介绍(“ worktree
:向工作树结构添加细节”,2015-10-08,Git v2.7.0-rc0)pre-core.bare
。
此补丁程序执行以下两项操作:
- 教
get_main_worktree()
使用is_bare_repository()
,而不是在介绍7d1864c( “引进is_bare_repository()和core.bare配置变量”,2007-01-07,Git的V1.5.0-RC1)和更新e90fdc3( “清理工作树处理”,2007年-08-01,Git v1.5.3-rc4)。
这样就解决了上述“ git branch -D <name>
”问题。
但是...如果存储库中有core.bare=1
一个“ git
”命令正在从其辅助工作树之一运行,则is_bare_repository()
返回false(这很好,因为有一个工作树可用)。
并且,在主工作树裸露时将其视为非裸露会导致问题:
例如,即使主工作树是空的,也无法从主工作树的HEAD所引用的辅助工作树中删除分支。
为了避免这种情况,还请core.bare
在设置时进行检查is_bare
。
如果core.bare=1
信任它,则使用is_bare_repository()
。
git-new-workdir
将git checkout --to=<path>
在Git 2.5中被替换。请在下面