我不确定Git是否支持这一点,但理论上它对我来说应该是可行的。

我的工作流程经常涉及同时编辑多个分支中的文件。换句话说,我经常想在一个分支中打开几个文件,而在另一个分支中编辑另一个文件的内容。

我的典型解决方案是进行两次签出,但遗憾的是,我不能在它们之间共享分支和引用。我想要的是用相同的.git文件夹管理两个工作目录。

我知道本地git克隆解决方案(默认的是硬链接共享对象,以及——shared选项,它在原始的repo中设置一个替代对象存储),但这些解决方案只减少了磁盘空间的使用,尤其是在——shared的情况下,似乎充满了危险。

是否有一种方法可以使用一个。git文件夹,并有两个工作目录支持它?或者Git是硬编码的,在任何时候只有一个工作目录签出?


当前回答

Git 2.5从2015年7月开始提议替换contrib/workdir/ Git -new-workdir: Git工作树

参见june C Hamano (gitster)提交68a2e6a。

发布说明中提到:

代替contrib/workdir/git-new-workdir,它不依赖于符号链接,通过使借方和借方相互意识到对方,使对象和引用的共享更加安全。

参见commit 799767cc9 (Git 2.5rc2)

这意味着你现在可以做一个git工作树添加<path> [<branch>]

Create <path> and checkout <branch> into it. The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. The git worktree section adds: A git repository can support multiple working trees, allowing you to check out more than one branch at a time. With git worktree add, a new working tree is associated with the repository. This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by "git init" or "git clone". A repository has one main working tree (if it's not a bare repository) and zero or more linked working trees.

细节:

Each linked working tree has a private sub-directory in the repository's $GIT_DIR/worktrees directory. The private sub-directory's name is usually the base name of the linked working tree's path, possibly appended with a number to make it unique. For example, when $GIT_DIR=/path/main/.git the command git worktree add /path/other/test-next next creates: the linked working tree in /path/other/test-next and also creates a $GIT_DIR/worktrees/test-next directory (or $GIT_DIR/worktrees/test-next1 if test-next is already taken). Within a linked working tree: $GIT_DIR is set to point to this private directory (e.g. /path/main/.git/worktrees/test-next in the example) and $GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR (e.g. /path/main/.git). These settings are made in a .git file located at the top directory of the linked working tree. When you are done with a linked working tree you can simply delete it. The working tree's administrative files in the repository will eventually be removed automatically (see gc.pruneworktreesexpire in git config), or you can run git worktree prune in the main or any linked working tree to clean up any stale administrative files.


警告:仍然有一个git工作树“BUGS”部分需要注意。

对子模块的支持不完整。 不建议对一个超级工程进行多次签出。


Note: with git 2.7rc1 (Nov 2015) you are able to list your worktrees. See commit bb9c03b, commit 92718b7, commit 5193490, commit 1ceb7f9, commit 1ceb7f9, commit 5193490, commit 1ceb7f9, commit 1ceb7f9 (08 Oct 2015), commit 92718b7, commit 5193490, commit 1ceb7f9, commit 1ceb7f9 (08 Oct 2015), commit 5193490, commit 1ceb7f9 (08 Oct 2015), commit 1ceb7f9 (08 Oct 2015), and commit ac6c561 (02 Oct 2015) by Michael Rappazzo (rappazzo). (Merged by Junio C Hamano -- gitster -- in commit a46dcfb, 26 Oct 2015)

工作树:添加“list”命令

'git worktree list' iterates through the worktree list, and outputs details of the worktree including the path to the worktree, the currently checked out revision and branch, and if the work tree is bare. $ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD) There is also porcelain format option available. The porcelain format has a line per attribute. Attributes are listed with a label and value separated by a single space. Boolean attributes (like 'bare' and 'detached') are listed as a label only, and are only present if and only if the value is true. An empty line indicates the end of a worktree

例如:

$ 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

注意:如果MOVE一个工作树文件夹,需要手动更新gitdir文件。

参见nguyThái ngibmc Duy (pclouds)的commit 618244e(2016年1月22日)和commit d4cddd6(2016年1月18日)。 帮助:Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在commit d0a1cbc中合并,2016年2月10日)

git 2.8(2016年3月)中的新文档将包括:

如果你移动一个链接的工作树,你需要更新“gitdir”文件 在条目的目录中。 例如,如果一个链接的工作树被移动到/newpath/test-next,它的.git文件指向/path/main/。Git /worktrees/test-next,然后更新 / /主/路径。Git /worktrees/test-next/gitdir改为引用/newpath/test-next。


在删除分支时要小心:在git 2.9(2016年6月)之前,你可以在另一个工作树中删除一个正在使用的分支。

当使用“git工作树”特性时,允许使用“git branch -d” 删除在另一个工作树中签出的分支。

参见Kazuki Yamaguchi(铼)的commit f292244(2016年3月29日)。 帮助:Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在commit 4fca4e3中合并,2016年4月13日)

分支-d:拒绝删除当前签出的分支

当当前工作树签出分支时,删除 禁止分支。 但是,当分支只被其他工作树签出时,错误地删除成功。 使用find_shared_symref()检查分支是否正在使用,而不仅仅是 与当前工作树的HEAD进行比较。


类似地,在git 2.9(2016年6月)之前,重命名另一个工作树中签出的分支并不会调整该工作树中的符号HEAD。

参见Kazuki Yamaguchi(铼)提交18eb3a9(2016年4月8日)和提交70999e9,提交2233066(2016年3月27日)。 (由Junio C Hamano—gitster—在commit 741a694中合并,2016年4月18日)

branch -m:更新每个工作树的head

When renaming a branch, currently only the HEAD of current working tree is updated, but it must update HEADs of all working trees which point at the old branch. This is the current behavior, /path/to/wt's HEAD is not updated: % 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] This patch fixes this issue by updating all relevant worktree HEADs when renaming a branch.


git 2.10正式支持锁定机制(2016年第三季度)

参见nguyn Thái ngeconc Duy (pclouds)的commit 080739b、commit 6d30862、commit 58142c0、commit 346ef53、commit 346ef53、commit 58142c0、commit 346ef53、commit 346ef53(2016年6月13日)和commit 984ad9e、commit 6835314(2016年6月03日)。 建议:Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在提交2c608e0中合并,2016年7月28日)

git worktree lock [--reason <string>] <worktree>
git worktree unlock <worktree>

If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from being pruned by issuing the git worktree lock command, optionally specifying --reason to explain why the working tree is locked. <worktree>: If the last path components in the working tree's path is unique among working trees, it can be used to identify worktrees. For example if you only have to working trees at "/abc/def/ghi" and "/abc/def/ggg", then "ghi" or "def/ghi" is enough to point to the former working tree.


Git 2.13 (2017 Q2)在提交507e6e9(2017年4月12日)中添加了一个锁定选项。 建议:David Taylor (dt)。 帮助:Jeff King (peff)。 (由Junio C Hamano—gitster—在commit e311597中合并,2017年4月26日)

允许在创建工作树后立即锁定它。 这有助于防止“git工作树添加;Git工作树锁”和 “git工作树修剪”。

所以git worktree add'——lock是等价于git worktree add后的git worktree lock,但是没有竞态条件。


Git 2.17+(2018年第二季度)增加了Git工作树移动/ Git工作树移除:参见这个答案。


Git 2.19(2018年Q3)增加了一个“——quiet”选项,以减少“Git工作树添加” 详细的。

参见Elia Pinto (devzero2000)提交的371979c(2018年8月15日)。 协助:Martin Ågren martin.agren@gmail.com, Duy Nguyen (pclouds)和Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在commit a988ce9中合并,2018年8月27日)

工作树:添加——静音选项

将“——quiet”选项添加到git工作树中,就像其他git命令一样。 'add'是唯一受它影响的命令,因为所有其他命令,除了'list',目前默认是沉默的。


注意,“git工作树添加”用来做一个“查找可用的名称与stat 然后是mkdir",这是有竞争倾向的。 Git 2.22(2019年第二季度)通过使用mkdir并在循环中对EEXIST进行响应来修复这一问题。

参见Michal Suchanek (hramrach)的commit 7af01f2(2019年2月20日)。 (由Junio C Hamano - gitster -在commit 20fe798, 2019年4月9日合并)

工作树:修复工作树添加种族

Git运行一个统计循环来查找可用的工作树名称和 然后在找到的名称上执行mkdir。 将其转换为mkdir循环,以避免再次调用worktree add查找相同的空闲名称并首先创建目录。


Git 2.22 (Q2 2019)修复了判断Git存储库是否有工作树的逻辑,保护“Git branch -D”不删除当前选中的分支 不小心出来了。 对于具有不寻常名称的存储库,这种逻辑的实现被破坏了,不幸的是,这是目前子模块的规范。

参见Jonathan Tan (jhowtan)提交f3534c9(2019年4月19日)。 (由Junio C Hamano—gitster—在commit ec2642a中合并,2019年5月8日)

工作树:update is_bare启发式

When "git branch -D <name>" is run, Git usually first checks if that branch is currently checked out. But this check is not performed if the Git directory of that repository is not at "<repo>/.git", which is the case if that repository is a submodule that has its Git directory stored as "super/.git/modules/<repo>", for example. This results in the branch being deleted even though it is checked out. This is because get_main_worktree() in worktree.c sets is_bare on a worktree only using the heuristic that a repo is bare if the worktree's path does not end in "/.git", and not bare otherwise. This is_bare code was introduced in 92718b7 ("worktree: add details to the worktree struct", 2015-10-08, Git v2.7.0-rc0), following a pre-core.bare heuristic. This patch does 2 things: Teach get_main_worktree() to use is_bare_repository() instead, introduced in 7d1864c ("Introduce is_bare_repository() and core.bare configuration variable", 2007-01-07, Git v1.5.0-rc1) and updated in e90fdc3 ("Clean up work-tree handling", 2007-08-01, Git v1.5.3-rc4). This solves the "git branch -D <name>" problem described above. However... If a repository has core.bare=1 but the "git" command is being run from one of its secondary worktrees, is_bare_repository() returns false (which is fine, since there is a worktree available). And, treating the main worktree as non-bare when it is bare causes issues: for example, failure to delete a branch from a secondary worktree that is referred to by a main worktree's HEAD, even if that main worktree is bare. In order to avoid that, also check core.bare when setting is_bare. If core.bare=1, trust it, and otherwise, use is_bare_repository().


在Git 2.29 (Q4 2020)中,“工作树”API提供了更好的工作树路径确定。

参见Eric Sunshine (sunshineco)的commit 918d8ff, commit 1c4854e, commit 246756f, commit 62573a5(2020年7月31日)。 (由Junio C Hamano - gitster -在commit 197253e中合并,2020年8月10日)

工作树:删除虚假和不必要的路径修改 署名:Eric Sunshine

The content of .git/worktrees/<id>/gitdir must be a path of the form "/path/to/worktree/.git". Any other content would be indicative of a corrupt "gitdir" file. To determine the path of the worktree itself one merely strips the "/.git" suffix, and this is indeed how the worktree path was determined from inception. However, 5193490442 ("worktree: add a function to get worktree details", 2015-10-08, Git v2.7.0-rc0 -- merge listed in batch #7) extended the path manipulation in a mysterious way. If it is unable to strip "/.git" from the path, then it instead reports the current working directory as the linked worktree's path: if (!strbuf_strip_suffix(&worktree_path, "/.git")) { strbuf_reset(&worktree_path); strbuf_add_absolute_path(&worktree_path, "."); strbuf_strip_suffix(&worktree_path, "/."); } This logic is clearly bogus; it can never be generally correct behavior. It materialized out of thin air in 5193490442 with neither explanation nor tests to illustrate a case in which it would be desirable. It's possible that this logic was introduced to somehow deal with a corrupt "gitdir" file, so that it returns some sort of meaningful value, but returning the current working directory is not helpful. In fact, it is quite misleading (except in the one specific case when the current directory is the worktree whose "gitdir" entry is corrupt). Moreover, reporting the corrupt value to the user, rather than fibbing about it and hiding it outright, is more helpful since it may aid in diagnosing the problem. Therefore, drop this bogus path munging and restore the logic to the original behavior of merely stripping "/.git".

其他回答

我能想到的唯一解决方案是克隆两个目录,并将它们添加为彼此的远程存储库。然后,您可以继续将内容从更改后的一个存储库拉到另一个存储库,而无需实际将任何内容推到远程存储库。

我假设您希望有两个工作目录,而不是远程的两个克隆目录,因为您不想将一些分支推到远程。否则,两个克隆的遥控器就可以工作了——你只需要做一些推和拉来保持三个同步。

git发行版附带了一个名为git-new-workdir的贡献脚本。 你可以这样使用它:

git-new-workdir project-dir new-workdir branch

project-dir是包含你的.git存储库的目录名。 这个脚本创建了另一个.git目录,其中包含许多到原始目录的符号链接,除了不能共享的文件(如当前分支),允许您在两个不同的分支中工作。

这听起来有点脆弱,但这是一个选择。

我偶然遇到这个问题,希望找到一个我在这里没有找到的解决方案。所以现在我确实找到了我需要的东西,我决定把它贴在这里给其他人看。

警告:如果你需要同时编辑多个分支,比如OP状态,这可能不是一个好的解决方案。它用于同时检出您不打算编辑的多个分支。(由一个.git文件夹支持的多个工作目录。)

自从我第一次提出这个问题以来,我学到了一些东西:

什么是“裸库”。它本质上是.git目录的内容,不位于工作树中。 事实上,您可以在命令行上使用git选项——git-dir=指定您正在使用的repo的位置(.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选项来签出,因为我实际上根本不打算在本地进行任何更改。只要使用-f选项,我就可以为任何工作树签出任何标签或分支。)

对于我在同一台计算机上共存多个签出而不需要编辑它们的用例来说,这非常有效。我不知道是否有任何方法可以在没有其他答案所涵盖的脚本的情况下为多个工作树提供多个head,但我希望这对其他人有所帮助。

Git 2.5从2015年7月开始提议替换contrib/workdir/ Git -new-workdir: Git工作树

参见june C Hamano (gitster)提交68a2e6a。

发布说明中提到:

代替contrib/workdir/git-new-workdir,它不依赖于符号链接,通过使借方和借方相互意识到对方,使对象和引用的共享更加安全。

参见commit 799767cc9 (Git 2.5rc2)

这意味着你现在可以做一个git工作树添加<path> [<branch>]

Create <path> and checkout <branch> into it. The new working directory is linked to the current repository, sharing everything except working directory specific files such as HEAD, index, etc. The git worktree section adds: A git repository can support multiple working trees, allowing you to check out more than one branch at a time. With git worktree add, a new working tree is associated with the repository. This new working tree is called a "linked working tree" as opposed to the "main working tree" prepared by "git init" or "git clone". A repository has one main working tree (if it's not a bare repository) and zero or more linked working trees.

细节:

Each linked working tree has a private sub-directory in the repository's $GIT_DIR/worktrees directory. The private sub-directory's name is usually the base name of the linked working tree's path, possibly appended with a number to make it unique. For example, when $GIT_DIR=/path/main/.git the command git worktree add /path/other/test-next next creates: the linked working tree in /path/other/test-next and also creates a $GIT_DIR/worktrees/test-next directory (or $GIT_DIR/worktrees/test-next1 if test-next is already taken). Within a linked working tree: $GIT_DIR is set to point to this private directory (e.g. /path/main/.git/worktrees/test-next in the example) and $GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR (e.g. /path/main/.git). These settings are made in a .git file located at the top directory of the linked working tree. When you are done with a linked working tree you can simply delete it. The working tree's administrative files in the repository will eventually be removed automatically (see gc.pruneworktreesexpire in git config), or you can run git worktree prune in the main or any linked working tree to clean up any stale administrative files.


警告:仍然有一个git工作树“BUGS”部分需要注意。

对子模块的支持不完整。 不建议对一个超级工程进行多次签出。


Note: with git 2.7rc1 (Nov 2015) you are able to list your worktrees. See commit bb9c03b, commit 92718b7, commit 5193490, commit 1ceb7f9, commit 1ceb7f9, commit 5193490, commit 1ceb7f9, commit 1ceb7f9 (08 Oct 2015), commit 92718b7, commit 5193490, commit 1ceb7f9, commit 1ceb7f9 (08 Oct 2015), commit 5193490, commit 1ceb7f9 (08 Oct 2015), commit 1ceb7f9 (08 Oct 2015), and commit ac6c561 (02 Oct 2015) by Michael Rappazzo (rappazzo). (Merged by Junio C Hamano -- gitster -- in commit a46dcfb, 26 Oct 2015)

工作树:添加“list”命令

'git worktree list' iterates through the worktree list, and outputs details of the worktree including the path to the worktree, the currently checked out revision and branch, and if the work tree is bare. $ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD) There is also porcelain format option available. The porcelain format has a line per attribute. Attributes are listed with a label and value separated by a single space. Boolean attributes (like 'bare' and 'detached') are listed as a label only, and are only present if and only if the value is true. An empty line indicates the end of a worktree

例如:

$ 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

注意:如果MOVE一个工作树文件夹,需要手动更新gitdir文件。

参见nguyThái ngibmc Duy (pclouds)的commit 618244e(2016年1月22日)和commit d4cddd6(2016年1月18日)。 帮助:Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在commit d0a1cbc中合并,2016年2月10日)

git 2.8(2016年3月)中的新文档将包括:

如果你移动一个链接的工作树,你需要更新“gitdir”文件 在条目的目录中。 例如,如果一个链接的工作树被移动到/newpath/test-next,它的.git文件指向/path/main/。Git /worktrees/test-next,然后更新 / /主/路径。Git /worktrees/test-next/gitdir改为引用/newpath/test-next。


在删除分支时要小心:在git 2.9(2016年6月)之前,你可以在另一个工作树中删除一个正在使用的分支。

当使用“git工作树”特性时,允许使用“git branch -d” 删除在另一个工作树中签出的分支。

参见Kazuki Yamaguchi(铼)的commit f292244(2016年3月29日)。 帮助:Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在commit 4fca4e3中合并,2016年4月13日)

分支-d:拒绝删除当前签出的分支

当当前工作树签出分支时,删除 禁止分支。 但是,当分支只被其他工作树签出时,错误地删除成功。 使用find_shared_symref()检查分支是否正在使用,而不仅仅是 与当前工作树的HEAD进行比较。


类似地,在git 2.9(2016年6月)之前,重命名另一个工作树中签出的分支并不会调整该工作树中的符号HEAD。

参见Kazuki Yamaguchi(铼)提交18eb3a9(2016年4月8日)和提交70999e9,提交2233066(2016年3月27日)。 (由Junio C Hamano—gitster—在commit 741a694中合并,2016年4月18日)

branch -m:更新每个工作树的head

When renaming a branch, currently only the HEAD of current working tree is updated, but it must update HEADs of all working trees which point at the old branch. This is the current behavior, /path/to/wt's HEAD is not updated: % 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] This patch fixes this issue by updating all relevant worktree HEADs when renaming a branch.


git 2.10正式支持锁定机制(2016年第三季度)

参见nguyn Thái ngeconc Duy (pclouds)的commit 080739b、commit 6d30862、commit 58142c0、commit 346ef53、commit 346ef53、commit 58142c0、commit 346ef53、commit 346ef53(2016年6月13日)和commit 984ad9e、commit 6835314(2016年6月03日)。 建议:Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在提交2c608e0中合并,2016年7月28日)

git worktree lock [--reason <string>] <worktree>
git worktree unlock <worktree>

If a linked working tree is stored on a portable device or network share which is not always mounted, you can prevent its administrative files from being pruned by issuing the git worktree lock command, optionally specifying --reason to explain why the working tree is locked. <worktree>: If the last path components in the working tree's path is unique among working trees, it can be used to identify worktrees. For example if you only have to working trees at "/abc/def/ghi" and "/abc/def/ggg", then "ghi" or "def/ghi" is enough to point to the former working tree.


Git 2.13 (2017 Q2)在提交507e6e9(2017年4月12日)中添加了一个锁定选项。 建议:David Taylor (dt)。 帮助:Jeff King (peff)。 (由Junio C Hamano—gitster—在commit e311597中合并,2017年4月26日)

允许在创建工作树后立即锁定它。 这有助于防止“git工作树添加;Git工作树锁”和 “git工作树修剪”。

所以git worktree add'——lock是等价于git worktree add后的git worktree lock,但是没有竞态条件。


Git 2.17+(2018年第二季度)增加了Git工作树移动/ Git工作树移除:参见这个答案。


Git 2.19(2018年Q3)增加了一个“——quiet”选项,以减少“Git工作树添加” 详细的。

参见Elia Pinto (devzero2000)提交的371979c(2018年8月15日)。 协助:Martin Ågren martin.agren@gmail.com, Duy Nguyen (pclouds)和Eric Sunshine (sunshineco)。 (由Junio C Hamano—gitster—在commit a988ce9中合并,2018年8月27日)

工作树:添加——静音选项

将“——quiet”选项添加到git工作树中,就像其他git命令一样。 'add'是唯一受它影响的命令,因为所有其他命令,除了'list',目前默认是沉默的。


注意,“git工作树添加”用来做一个“查找可用的名称与stat 然后是mkdir",这是有竞争倾向的。 Git 2.22(2019年第二季度)通过使用mkdir并在循环中对EEXIST进行响应来修复这一问题。

参见Michal Suchanek (hramrach)的commit 7af01f2(2019年2月20日)。 (由Junio C Hamano - gitster -在commit 20fe798, 2019年4月9日合并)

工作树:修复工作树添加种族

Git运行一个统计循环来查找可用的工作树名称和 然后在找到的名称上执行mkdir。 将其转换为mkdir循环,以避免再次调用worktree add查找相同的空闲名称并首先创建目录。


Git 2.22 (Q2 2019)修复了判断Git存储库是否有工作树的逻辑,保护“Git branch -D”不删除当前选中的分支 不小心出来了。 对于具有不寻常名称的存储库,这种逻辑的实现被破坏了,不幸的是,这是目前子模块的规范。

参见Jonathan Tan (jhowtan)提交f3534c9(2019年4月19日)。 (由Junio C Hamano—gitster—在commit ec2642a中合并,2019年5月8日)

工作树:update is_bare启发式

When "git branch -D <name>" is run, Git usually first checks if that branch is currently checked out. But this check is not performed if the Git directory of that repository is not at "<repo>/.git", which is the case if that repository is a submodule that has its Git directory stored as "super/.git/modules/<repo>", for example. This results in the branch being deleted even though it is checked out. This is because get_main_worktree() in worktree.c sets is_bare on a worktree only using the heuristic that a repo is bare if the worktree's path does not end in "/.git", and not bare otherwise. This is_bare code was introduced in 92718b7 ("worktree: add details to the worktree struct", 2015-10-08, Git v2.7.0-rc0), following a pre-core.bare heuristic. This patch does 2 things: Teach get_main_worktree() to use is_bare_repository() instead, introduced in 7d1864c ("Introduce is_bare_repository() and core.bare configuration variable", 2007-01-07, Git v1.5.0-rc1) and updated in e90fdc3 ("Clean up work-tree handling", 2007-08-01, Git v1.5.3-rc4). This solves the "git branch -D <name>" problem described above. However... If a repository has core.bare=1 but the "git" command is being run from one of its secondary worktrees, is_bare_repository() returns false (which is fine, since there is a worktree available). And, treating the main worktree as non-bare when it is bare causes issues: for example, failure to delete a branch from a secondary worktree that is referred to by a main worktree's HEAD, even if that main worktree is bare. In order to avoid that, also check core.bare when setting is_bare. If core.bare=1, trust it, and otherwise, use is_bare_repository().


在Git 2.29 (Q4 2020)中,“工作树”API提供了更好的工作树路径确定。

参见Eric Sunshine (sunshineco)的commit 918d8ff, commit 1c4854e, commit 246756f, commit 62573a5(2020年7月31日)。 (由Junio C Hamano - gitster -在commit 197253e中合并,2020年8月10日)

工作树:删除虚假和不必要的路径修改 署名:Eric Sunshine

The content of .git/worktrees/<id>/gitdir must be a path of the form "/path/to/worktree/.git". Any other content would be indicative of a corrupt "gitdir" file. To determine the path of the worktree itself one merely strips the "/.git" suffix, and this is indeed how the worktree path was determined from inception. However, 5193490442 ("worktree: add a function to get worktree details", 2015-10-08, Git v2.7.0-rc0 -- merge listed in batch #7) extended the path manipulation in a mysterious way. If it is unable to strip "/.git" from the path, then it instead reports the current working directory as the linked worktree's path: if (!strbuf_strip_suffix(&worktree_path, "/.git")) { strbuf_reset(&worktree_path); strbuf_add_absolute_path(&worktree_path, "."); strbuf_strip_suffix(&worktree_path, "/."); } This logic is clearly bogus; it can never be generally correct behavior. It materialized out of thin air in 5193490442 with neither explanation nor tests to illustrate a case in which it would be desirable. It's possible that this logic was introduced to somehow deal with a corrupt "gitdir" file, so that it returns some sort of meaningful value, but returning the current working directory is not helpful. In fact, it is quite misleading (except in the one specific case when the current directory is the worktree whose "gitdir" entry is corrupt). Moreover, reporting the corrupt value to the user, rather than fibbing about it and hiding it outright, is more helpful since it may aid in diagnosing the problem. Therefore, drop this bogus path munging and restore the logic to the original behavior of merely stripping "/.git".