多个工作目录与Git?
我不确定这是Git支持的东西,但理论上它似乎应该适用于我。
我的工作stream程经常涉及到我同时在多个分支中编辑文件。 换句话说,我经常要在一个分支中打开几个文件,而我在另一个分支中编辑另一个文件的内容。
我典型的解决办法是做两个结账,但这是一个耻辱,我不能分享他们之间的分支机构和参考。 我想只是有两个工作目录由相同的.git文件夹pipe理。
我知道本地git克隆解决scheme(默认,这是硬链接共享对象,和 – 共享选项,它设置了一个替代的对象存储与原始的回购),但这些解决scheme只减less磁盘空间的使用,特别是在共享的情况下,似乎充满了危险。
有没有办法使用一个.git文件夹,并有两个工作目录支持它? 还是Git硬编码只有一个工作目录在任何时候签出?
Git 2.5自2015年7月起提议replacecontrib/workdir/git-new-workdir
: git worktree
见Junio C gitster
( gitster
)的 提交68a2e6a 。
发行说明提到 :
替代
contrib/workdir/git-new-workdir
,它不依赖于符号链接,通过使借款人和借款人相互了解,使对象和参考资料共享更安全。
参见提交799767cc9 (Git 2.5rc2)
这意味着你现在可以做一个git worktree add <path> [<branch>]
创build
<path>
并签出<branch>
。 新的工作目录链接到当前的存储库,除了工作目录特定的文件,如HEAD,索引等,共享一切git worktree
部分添加:一个git仓库可以支持多个工作树 ,允许你一次签出多个分支。
使用git worktree add
一个新的工作树与存储库相关联。这个新的工作树称为“链接工作树”,而不是由“
git init
”或“git clone
”准备的“主工作树” 。
一个仓库有一个主工作树(如果它不是一个裸仓库)和零个或多个链接的工作树。细节:
每个链接的工作树在存储库的
$GIT_DIR/worktrees
目录中都有一个私有的子目录。
私人子目录的名称通常是链接工作树的path的基本名称,可能会附加一个数字以使其唯一。
例如,当$GIT_DIR=/path/main/.git
,命令git worktree add /path/other/test-next next
创build:
- 链接的工作树在
/path/other/test-next
和- 还会创build一个
$GIT_DIR/worktrees/test-next
目录(如果test-next
已经被使用,则创build$GIT_DIR/worktrees/test-next1
)。在一个链接的工作树中:
$GIT_DIR
被设置为指向这个私人目录(例如/path/main/.git/worktrees/test-next
)$GIT_COMMON_DIR
被设置为指向主工作树的$GIT_DIR
(例如/path/main/.git
)。这些设置是在位于链接工作树顶部目录的
.git
文件中进行的。当你完成一个链接的工作树,你可以简单地删除它。
存储库中的工作树pipe理文件最终会自动删除(请参阅git config
gc.pruneworktreesexpire
),或者可以在主或任何链接的工作树中运行git worktree prune
来清除任何失效的pipe理文件。
警告:仍然有一个git worktree
“BUGS”部分需要注意。
子模块的支持是不完整的 。
不build议多次签出一个超级项目。
注意:使用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
合并- gitster
– in commit a46dcfb ,2015年10月26日)
worktree
:添加“list
”命令'
git worktree list
'循环遍历工作树列表,并输出工作树的详细信息,包括工作树的path,当前检出的修订和分支,以及工作树是否裸露。
$ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD)
还有瓷器格式选项可用。
瓷器格式每个属性都有一行。
- 属性以一个空格分隔的标签和值列出。
- 布尔属性(比如“裸”和“分离”)仅作为标签列出,只有当值为真时才存在。
- 空行表示工作树的结束
例如:
$ 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日),并提交NguyễnTháiNgọcDuy ( pclouds )的d4cddd6 (2016年1月18日) 。
帮助: 埃里克阳光( sunshineco
) 。
(由Junio C gitster
合并- gitster
– in 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
”function时,“git branch -d
”允许删除在另一个工作树中检出的分支。
见山口一木( rhenium
) 提交f292244 (2016年3月29日) 。
帮助: 埃里克阳光( sunshineco
) 。
(由Junio C gitster
合并- gitster
-在4fca4e3 ,2016年4月13日提交 )
branch -d
:拒绝删除当前检出的分支当前工作树签出分支时,删除分支是被禁止的。
但是,当分支仅由其他工作树检出时,删除不正确成功。
使用find_shared_symref()
来检查分支是否在使用中,而不仅仅是与当前工作树的HEAD进行比较。
同样,在git 2.9(2016年6月)之前,重命名在另一个工作树中检出的分支不会调整其他工作树中的符号HEAD。
参见承诺18eb3a9 (2016年4月8日), 承诺70999e9 , 承诺2233066 (2016年3月27日)由Kazuki Yamaguchi( rhenium
) 。
(由Junio C gitster
合并- gitster
-在承诺741a694 ,2016年4月18日)
branch -m
:更新所有per-worktree头当重命名一个分支时,当前只有当前工作树的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来解决此问题。
locking机制是官方支持与git 2.10(Q3 2016)
请参阅提交080739b , 提交6d30862 , 提交58142c0 , 提交346ef53 , 提交346ef53 , 提交58142c0 , 提交346ef53 , 提交346ef53 (2016年6月13日),并提交984ad9e , 提交6835314 (2016年6月3日)由NguyễnTháiNgọcDuy( pclouds
) 。
build议: 埃里克阳光( sunshineco
) 。
(由Junio C gitster
合并- gitster
– in commit 2c608e0 ,2016年7月28日)
git worktree lock [--reason <string>] <worktree> git worktree unlock <worktree>
如果链接的工作树存储在便携式设备或networking共享上,而这些共享并不总是挂载,那么可以通过发出
git worktree lock
命令来防止其pipe理文件被修剪,可以指定 – 解释为什么工作树被locking。
<worktree>
:如果工作树的最后一个path组件在工作树中是唯一的,那么它可以用来标识工作树。
例如,如果只需要在“/abc/def/ghi
”和“/abc/def/ggg
”中工作树,那么“ghi
”或“def/ghi
”就足以指向前一个工作树。
Git 2.13(Q2 2017)在NguyễnTháiNgọcDuy( pclouds
)的 commit 507e6e9 (2017年4月12日)中添加了一个lock
选项 。
build议: David Taylor( dt
) 。
帮助: 杰夫·金( peff
) 。
(由Junio C gitster
合并- gitster
– 2017年4月26日在e311597提交 )
允许在创build后立即locking工作树。
这有助于防止“git worktree add; git worktree lock
”和“git worktree prune
”之间的竞争。
所以git worktree add' --lock
git worktree lock
git worktree add
,但没有竞争条件git worktree lock
相当于。
git
发行版带有一个名为git-new-workdir
的贡献脚本 。 你会使用它如下:
git-new-workdir project-dir new-workdir branch
其中project-dir是包含.git
存储库的目录的名称。 这个脚本创build另一个`.git'目录,除了不能被共享的文件(比如当前分支)之外,还有许多与原始文件相符的符号链接,允许你在两个不同的分支中工作。
这听起来有点脆弱,但它是一个选项。
我遇到了这个问题希望find一个解决scheme,我没有在这里find。 所以现在我确实find了我需要的东西,所以我决定把它发布给其他人。
警告:如果您需要同时编辑多个分支(如OP状态),这可能不是一个好的解决scheme。 这是为了同时签出多个分支,你不打算编辑。 (由一个.git文件夹支持的多个工作目录。)
自从我第一次提到这个问题以来,我学到了一些东西:
-
什么是“ 裸仓库 ”。 它实质上是
.git
目录的内容,不在工作树中。 -
事实上你可以在命令行中用
git
选项指定你正在使用的repo的位置(你的.git
目录的位置)–git
--git-dir=
-
您可以使用
--work-tree=
来指定工作副本的位置 -
什么是“镜子回购”?
这最后是一个非常重要的区别。 我其实不想在回购上工作 ,我只需要同时签出不同分支和/或标签的副本。 实际上,我需要保证分支机构不会与我的分支机构不同。 所以一面镜子对我来说是完美的。
所以对于我的用例,我得到了我所需要的:
git clone --mirror <remoteurl> <localgitdir> # Where localgitdir doesn't exist yet mkdir firstcopy mkdir secondcopy git --git-dir=<localgitdir> --work-tree=firstcopy checkout -f branch1 git --git-dir=<localgitdir> --work-tree=secondcopy checkout -f branch2
关于这个的一个大警告是,这两个副本没有单独的HEAD。 因此,在上面的结果之后,运行git --git-dir=<localgitdir> --work-tree=firstcopy status
会显示从branch2到branch1的所有不同之处,因为未提交的更改 – 因为HEAD指向branch2。 (这就是为什么我使用-f
选项来checkout
,因为我实际上并没有计划在本地进行任何更改,只要使用-f
选项,就可以签出任何工作树的标签或分支。 )
对于在同一台计算机上同时存在多个结帐而无需编辑它们的情况 ,此function完美无缺。 我不知道是否有任何方法可以有多个HEAD的多个工作树没有一个脚本,如其他答案中涵盖的脚本,但我希望这对其他人有帮助。
我能想到的唯一的解决scheme是克隆两个目录,并将它们添加为彼此的远程存储库。 然后,您可以不断将东西从已更改的东西拖到另一个中,而无需将任何东西推送到远程存储库。
我假设你想有两个工作目录,而不是两个克隆的远程,因为你不想把一些分支到远程。 否则,你的遥控器的两个克隆将工作得很好 – 你只需要做一些推动和保持所有三个同步。