4

当我这样做时git worktree list,它会显示如下。

/path/to/workspace  c943d35 [master]
/path/to/workspace  ef4df56 (detached HEAD)

这是我的工作目录(不是工作树目录)。我不知道它是怎么发生的,以及如何清洁它。我试过git worktree prune了,但它并没有改变任何东西。任何帮助将不胜感激。非常感谢。

4

1 回答 1

7

git worktree-- 细节提到:

每个链接的工作树在存储库目录中都有一个私有子目录$GIT_DIR/worktrees

检查您的内容,main repo/.git/worktrees看看是否有可以手动删除的子文件夹。


Git 2.20(2018 年第四季度)修复了一个错误,如果该路径丢失(例如,手动删除),同一路径可能会在多个工作树条目下注册。
此外,为方便起见,扩大--force适用的案例数量。

请参阅Jeff King ( ) 的提交 684e742(2018 年 8 月 30 日。 请参阅Eric Sunshine ( )的提交3a54043、提交f414310提交 68a6b3a提交 e19831c提交 cb56f55提交 45059e6提交 602aaed提交 e5353be提交 4c5fa9e(2018 年 8 月 28 日) 。(由Junio C Hamano 合并 -- --提交 1c515bf中,2018 年 9 月 17 日)peff
sunshineco
gitster

worktree: 如果在 ' '.git/worktrees之后为空,则删除remove

为了清洁,如果目录在修剪完成后为空,“ git worktree prune”将删除该目录。.git/worktrees

为保持一致性,如果删除后为空,则“ git worktree remove <path>”同样删除。.git/worktrees


同样的 Git 2.20,在遍历对象以获得可达性并决定哪些对象是未引用和可消耗的时,也被教导要考虑其他工作树的每个工作树引用作为防止数据丢失的起点。

请参阅Nguyễn Thái Ngọc的提交14f74d5 ( 2018 年 11 月 3 日)、提交 c9ef0d9提交 b29759d提交 ab3e1f7提交 061e420提交 3a3b9d8(2018 年 10 月 21 日)和提交 8aff1a9提交 5c79f74(2018 年 9 月 29 日。 请参阅Elijah Newren ( ) 的提交 a8c754d(2018 年 10 月 21 日(由Junio C Hamano 合并 -- --提交 e146cc9中,2018 年 11 月 13 日)pclouds
newren
gitster

特别是(提交 3a3b9d8):

refs: 新的 ref 类型,使每个工作树的 ref 对所有工作树可见

多个工作树的问题之一是从另一个工作树访问一个工作树的每个工作树引用
这在某种程度上是通过多个 ref 存储解决的,其中代码可以打开另一个工作树的 ref 存储并可以访问该工作树的 ref 空间。

问题在于报告。
另一个 ref 空间中的“ HEAD”也称为“HEAD”,就像在当前 ref 空间中一样。
为了区分它们,所有代码都必须以某种方式携带 ref 存储并打印类似“ HEAD from this ref store”的内容。

我们没有进入单独的 ref 空间,而是使来自其他工作树的 ref 在当前 ref 空间中可用
所以“ HEAD”总是当前工作树的 HEAD,但是我们可以用“ worktrees/blah/HEAD”来表示名为“”的工作树的 HEAD blah
这种语法巧合地与底层目录结构相匹配,这使得实现更容易一些。

必须对主工作树进行特殊处理,因为...它从一开始就很特别。
所以主工作树的 HEAD 可以通过名称“ main-worktree/HEAD”而不是“ worktrees/main/HEAD”访问,因为“ main”可能只是另一个辅助工作树。

此补丁还可以在另一个工作树中指定来自一个工作树的引用,例如

git log worktrees/foo/HEAD

那个(新的引用“ worktrees/<name>/HEAD”)导致 Git 2.23(2019 年第二季度),代码现在清理给工作树的名称,以确保这些引用格式正确。

请参阅Nguyễn Thái Ngọc Duy ( ) 的提交 1de16ae(2019 年 3 月 8 日。 帮助者:Jeff King ( )(由Junio C Hamano 合并 -- --0d107b1 提交中,2019 年 6 月 13 日)pclouds
peff
gitster

worktree add: 清理工作树名称

工作树名称基于$(basename $GIT_WORK_TREE).
它们直到3a3b9d8 才有意义(refs:新的 ref 类型使每个工作树的 ref 对所有工作树可见 - 2018-10-21,Git v2.20.0-rc0),其中工作树名称可以是 refname 的一部分,并且必须遵循 refname规则。

更新“ worktree add”代码删除特殊字符以遵循这些规则。将来,如果用户对这种愚蠢的字符替换不满意,他们将能够自己指定工作树名称。


同样的 Git 2.22.1(2019 年第三季度)提到“ git worktree add”在连接到同一存储库的另一个工作树损坏时会失败,这已得到纠正。

请参阅Nguyễn Thái Ngọc Duy ( ) 的提交 105df73(2019 年 5 月 13 日(由Junio C Hamano 合并 -- --提交 933f294中,2019 年 7 月 25 日)pclouds
gitster

worktree add:容忍损坏的工作树

find_worktree()可以 die() 意外,因为它使用real_path() 而不是更温和的版本。

当它用于'git worktree add'时(在cb56f55中添加(worktree:不允许多次添加相同的路径,2018-08-28,Git v2.20.0-rc0),或者从v2.20.0开始。虽然真正的错误find_worktree()要老得多) 并且工作树不好,这die()可能会阻止人们添加新的工作树。

触发此事件的“坏”条件是删除工作树位置的父级时。然后real_path()会抱怨。

使用其他版本,这样糟糕的工作树就不会影响“ worktree add”。
坏的最终会被修剪,我们只需要容忍它们一点。


在 Git 2.26(2020 年第一季度)之前,在极少数情况下,“ ”可能会认为它已经是注册的工作树,即使它不是,并拒绝添加新的工作树。 这已得到纠正。git worktree add <path><path>

请参阅Eric Sunshine ( )的提交 bb69b3b提交 bb4995f提交 a80c4c2(2020 年 2 月 24 日) 。(由Junio C Hamano 合并 -- --提交 49e5043中,2020 年 3 月 5 日)sunshineco
gitster

worktree: 不允许“ add”验证被后缀匹配所迷惑

报告人:Cameron Gunnin
签字人:Eric Sunshine

" " 在批准为新工作树的有效位置之前执行各种检查。git worktree add <path><path>

除了确保它<path>不存在之外,它提出的问题之一是它是否<path>已经是一个注册的工作树。
要执行此检查,它会查询并在找到匹配项时find_worktree()禁止“ add”操作。 然而,为了方便起见,它使用了一个过于宽泛的网络,以允许用户通过速记来识别工作树,以便将输入保持在最低限度。 例如,它执行后缀匹配,给定子树“ ”和“ ”,当仅询问“ ”时,它可以正确选择后者。find_worktree()<path>
find_worktree()
foo/barfoo/bazbaz

" add" 验证知道它正在询问的确切路径,所以这种基于启发式的匹配充其量对于这个用例来说是有问题的,最坏的情况是,可能会意外地解释<path>为匹配现有的工作树并错误地将其报告为已经即使没有注册。
(事实上​​,validate_worktree_add()已经包含了一个特殊情况,以避免意外匹配主工作树,正是由于这个问题。)

避免潜在的意外匹配现有工作树的问题,而是利用find_worktree_by_path()确定性匹配路径,而不应用任何类型的魔术速记匹配find_worktree()

和:

worktree: 改进find_worktree()文档

签字人:Eric Sunshine

更好地解释它find_worktree()的主要目的是根据用户的输入定位工作树,这可能是识别工作树而不是实际路径的某种速记。

例如,用户可以用来识别工作树的一种简写方式是通过唯一的路径后缀(即在路径“ foo/bar”和“ foo/baz”处给定工作树,后者可以简单地识别为“ baz”)。将来可能会扩展用于选择工作树
的实际启发式方法(例如,有一天它可能允许通过管理目录选择工作树),因此文档没有提供如何执行匹配的精确描述,而是将其保留开放式,以允许将来增强。find_worktree()<id>.git/worktrees/<id>/

在此期间,长期以来一直允许prefix提及非 NULL 要求。NULL

例如,自116fb64e43prefix_filename()以来已明确允许(:丢弃长度参数,2017-03-20,Git v2.13.0-rc0),以及自e4da43b1f0以来其自身:返回新分配的字符串,2017-03-20,Git v2.13.0-rc0 )。NULLprefix_filenamefind_worktree() (prefix_filename


请注意,同一个工作树目录只能注册​​一次,但“ git worktree move”允许违反此不变量,已在 Git 2.28(2020 年第三季度)中更正。

请参阅Eric Sunshine ( ) 的提交 810382e提交 d179af6提交 916133e提交 4a3ce47提交 dd9609a提交 1b14d40(2020 年 6 月 10 日)和提交 c9b77f2(2020 年 6 月 8日(由Junio C Hamano 合并 -- --提交 9740ef8中,2020 年 6 月 22 日)sunshineco
gitster

使用 Git 2.28(2020 年第三季度),同一个工作树目录只能注册​​一次,但“git worktree移动”允许违反此不变量,已更正。

请参阅Eric Sunshine ( ) 的提交 810382e提交 d179af6提交 916133e提交 4a3ce47提交 dd9609a提交 1b14d40(2020 年 6 月 10 日)和提交 c9b77f2(2020 年 6 月 8日(由Junio C Hamano 合并 -- --提交 9740ef8中,2020 年 6 月 22 日)sunshineco
gitster

worktree:修剪引用相同工作树路径的重复条目

签字人:Eric Sunshine

链接工作树的一个基本限制是必须永远只有一个工作树与特定路径相关联,因此“ git worktree add”明确禁止在与现有注册工作树相同的位置创建新工作树。

尽管如此,用户仍然可以通过在.git/worktree/<id>/.

更糟糕的是,“ git worktree move”是粗心的,它允许将工作树移动到已注册但丢失的工作树上(例如,如果工作树位于可移动媒体上,则可能发生这种情况)。

例如:

$ git clone foo.git
$ cd foo
$ git worktree add ../bar
$ git worktree add ../baz
$ rm -rf ../bar
$ git worktree move ../baz ../bar
$ git worktree list
.../foo beefd00f [master]
.../bar beefd00f [bar]
.../bar beefd00f [baz]

git worktree prune通过教导“ ”来检测多个工作树何时与同一路径相关联,帮助用户从这种形式的损坏中恢复。

和:

worktree:修剪链接的工作树引用主工作树路径

报告人:Jonathan Müller
签字人:Eric Sunshine

" git worktree prune" 检测多个条目何时与同一路径相关联并删除重复项。

但是,它不会检测链接的工作树何时指向主工作树的路径。
尽管 " git worktree add" 不允许创建与主工作树具有相同路径的新工作树,但即使用户不处理.git/worktree/<id>/管理文件,这种情况也可能出现在 Git 的控制之外。

例如:

$ git clone foo.git
$ git -C foo worktree add ../bar
$ rm -rf bar
$ mv foo bar
$ git -C bar worktree list
.../bar deadfeeb [master]
.../bar deadfeeb [bar]

通过扩展“”来帮助用户从此类损坏中恢复,git worktree prune以检测链接的工作树何时与主工作树的路径相关联。


请注意,Git 2.30 确实列出了锁定的工作树:

请参阅提交 c57b336

工作树:教list注解锁定的工作树

git worktree list” 显示工作树的绝对路径、签出的提交和分支的名称。哪些工作树(如果有的话)被锁定并不是很明显。

“git worktree remove”拒绝删除带有错误消息的锁定工作树。如果“ git worktree list”在其输出中告知哪些工作树被锁定,则用户甚至不会尝试删除这样的工作树,或者会意识到“ git worktree remove -f -f <path>”是必需的。

教“ git worktree list”将“”附加locked到其输出。
该命令的输出如下所示:

$ git worktree list
/path/to/main             abc123 [master]
/path/to/worktree         456def (detached HEAD)
/path/to/locked-worktree  123abc (detached HEAD) locked

在 Git 2.33(2021 年第三季度)中,“ git worktree add --lockman学会了用自定义消息记录工作树被锁定的原因。

请参阅提交 0db4961(2021 年 7 月 15 日)和提交 f7c35ea提交 f9365c0(2021 年 7 月 11 日),作者是Stephen Manz ( SRManz)
(由Junio C Hamano 合并gitster——提交 01369fd中,2021 年 7 月 28 日)

worktree:教add接受--reason <string>--lock

签字人:Stephen Manz
审核人:Eric Sunshine

存储在锁定文件中的默认原因“ added with --lock”不太可能是用户在单独的( man )命令中给出的原因。 允许在添加工作树时指定,使用户无需第二个命令即可控制锁定原因。git worktree lock
--reason--lock

git worktree现在在其手册页中包含:

git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]] [-b <new-branch>] <path> [<commit-ish>]

git worktree现在在其手册页中包含:

Withlock或 with add --lock,解释为什么工作树被锁定。

于 2016-02-24T10:19:50.887 回答