设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.55.0 无变更
-
2.54.0
2026-04-20
-
2.53.0
2026-02-02
-
2.52.0
2025-11-17
- 2.48.1 → 2.51.2 无更改
-
2.48.0
2025-01-10
- 2.43.2 → 2.47.3 无变更
-
2.43.1
2024-02-09
- 2.42.2 → 2.43.0 无变更
-
2.42.1
2023-11-02
-
2.42.0
2023-08-21
- 2.39.1 → 2.41.3 无变更
-
2.39.0
2022-12-12
- 2.36.1 → 2.38.5 无更改
-
2.36.0
2022-04-18
- 2.35.1 → 2.35.8 无更改
-
2.35.0
2022-01-24
- 2.33.1 → 2.34.8 无变化
-
2.33.0
2021-08-16
- 2.31.1 → 2.32.7 无更改
-
2.31.0
2021-03-15
- 2.30.1 → 2.30.9 无更改
-
2.30.0
2020-12-27
- 2.29.1 → 2.29.3 无更改
-
2.29.0
2020-10-19
- 2.28.1 无更改
-
2.28.0
2020-07-27
- 2.22.1 → 2.27.1 无变更
-
2.22.0
2019-06-07
- 2.20.1 → 2.21.4 无更改
-
2.20.0
2018-12-09
- 2.19.3 → 2.19.6 无更改
-
2.19.2
2018-11-21
- 2.19.1 无更改
-
2.19.0
2018-09-10
- 2.18.1 → 2.18.5 无更改
-
2.18.0
2018-06-21
- 2.17.1 → 2.17.6 无更改
-
2.17.0
2018-04-02
-
2.16.6
2019-12-06
- 2.14.6 → 2.15.4 无变更
-
2.13.7
2018-05-22
-
2.12.5
2017-09-22
- 2.11.4 无更改
-
2.10.5
2017-09-22
-
2.9.5
2017-07-30
- 2.8.6 无更改
-
2.7.6
2017-07-30
-
2.6.7
2017-05-05
-
2.5.6
2017-05-05
概要
gitworktreeadd[-f] [--detach] [--checkout] [--lock[--reason<string>]] [--orphan] [(-b|-B) <new-branch>] <path> [<commit-ish>]gitworktreelist[-v|--porcelain[-z]]gitworktreelock[--reason<string>] <worktree>gitworktreemove<worktree> <new-path>gitworktreeprune[-n] [-v] [--expire<expire>]gitworktreeremove[-f] <worktree>gitworktreerepair[<path>…]gitworktreeunlock<worktree>
描述
管理连接到同一个仓库的多个工作区。
一个 Git 仓库可以支持多个工作区,允许您一次检出多个分支。使用 git worktree add,一个新的工作区将与该仓库关联,并附带额外的元数据,用于将该工作区与同一仓库中的其他工作区区分开来。该工作区以及这些元数据一起被称为一个“工作区”(worktree)。
这个新的工作区被称为“链接工作区”(linked worktree),与由 git-init[1] 或 git-clone[1] 准备的“主工作区”(main worktree)相对。一个仓库拥有一个主工作区(如果它不是裸仓库)以及零个或多个链接工作区。当您使用完链接工作区后,可以使用 git worktree remove 将其删除。
在最简单的情况下,git worktree add <路径> 会自动创建一个新分支,其名称是 <路径> 的最后一部分,如果您计划在新的主题上工作,这会非常方便。例如,git worktree add ../hotfix 会创建新分支 hotfix 并在路径 ../hotfix 检出它。如果想在新工作区中处理现有分支,请使用 git worktree add <路径> <分支>。另一方面,如果您只是计划进行一些实验性的更改或测试,而不干扰现有的开发,那么创建一个不与任何分支关联的一次性工作区通常会很方便。例如,git worktree add -d <路径> 会创建一个新的工作区,其处于分离的 HEAD 状态,并指向与当前分支相同的提交。
如果未通过使用 git worktree remove 删除了工作区,则其位于仓库中的相关管理文件(见下文“详细信息”)最终会被自动删除(见 git-config[1] 中的 gc.worktreePruneExpire),或者您可以在主工作区或任何链接工作区中运行 git worktree prune 来清理所有过时的管理文件。
如果链接工作区的工作目录存储在便携式设备或并非总是挂载的网络共享上,您可以通过发出 git worktree lock 命令来防止其管理文件被修剪,并可选择指定 --reason 来解释锁定工作区的原因。
命令
add<路径> [<提交对象>]-
在 <路径> 处创建一个工作区并检出 <提交对象> 到其中。新工作区与当前仓库链接,共享除每个工作区专属文件(如
HEAD、index等)之外的所有内容。为方便起见,<提交对象> 可以是单独的“-”,这与@{-1}同义。如果 <提交对象> 是一个分支名称(称其为 <分支>)且未找到,同时既未使用
-b、-B,也未使用--detach,但确有一个远程仓库(称其为 <remote>)中存在同名的跟踪分支,则视其等同于$ git worktree add --track -b <branch> <path> <remote>/<branch>
如果该分支存在于多个远程仓库中,且其中一个已被
checkout.defaultRemote配置变量指定,我们将使用它来消除歧义,即使该 <分支> 在所有远程仓库中并不唯一。可以将其设置为例如checkout.defaultRemote=origin,以便在 <分支> 存在歧义但存在于origin远程仓库时,始终从那里检出远程分支。另请参阅 git-config[1] 中的checkout.defaultRemote。如果省略了 <提交对象> 且未使用
-b、-B或--detach,那么为方便起见,新工作区将与一个以$(basename<路径>) 命名的分支(称其为 <分支>)关联。如果 <分支> 不存在,则会自动创建一个基于HEAD的新分支,效果就如同指定了-b<分支>。如果 <分支> 确实存在,且未在其他任何地方检出,它将在新工作区中被检出,否则该命令将拒绝创建工作区(除非使用了--force)。如果省略了 <提交对象>,且未使用
--detach或--orphan,并且不存在有效的本地分支(或者在指定了--guess-remote的情况下不存在远程分支),那么为方便起见,新工作区将与一个名为 <分支> 的全新未出生(unborn)分支关联(如果未使用-b或-B,则根据$(basename<路径>) 命名),效果就如同向命令传递了--orphan。如果仓库包含远程仓库并使用了--guess-remote,但不存在任何远程或本地分支,则命令失败并显示警告,提醒用户首先从远程仓库获取(fetch)(或者使用-f/--force强制覆盖)。 list-
列出每个工作区的详细信息。主工作区会首先列出,随后是每个链接工作区。输出的详细信息包括工作区是否为裸(bare)仓库、当前检出的版本、当前检出的分支(如果没有则为 "detached HEAD")、如果工作区已被锁定则显示 "locked"、如果工作区可以通过
prune命令修剪则显示 "prunable"。 lock-
如果工作区位于便携式设备或并非总是挂载的网络共享上,请将其锁定以防止其管理文件被自动修剪。这还可以防止其被移动或删除。可选地,使用
--reason指定锁定的原因。 move-
将工作区移动到新位置。请注意,主工作区或包含子模块的链接工作区无法使用此命令移动。(但是,如果您手动移动了主工作区,可以使用
gitworktreerepair命令重新建立与链接工作区的连接。) prune-
对于其工作目录已丢失的工作区,删除其在
$GIT_DIR/worktrees中的工作区信息。这在手动删除了不再需要的工作目录后非常有用(但下次需要删除时,请使用 "git worktree remove")。此外,如果您将工作目录移动到了别处,导致工作区信息变得悬空(dangling),请参阅 "git worktree repair" 以重新将该工作区连接到新的工作目录位置。 remove-
删除工作区。只有干净的工作区(没有未跟踪的文件,且已跟踪的文件没有被修改)才能被删除。不干净的工作区或带有子模块的工作区可以使用
--force删除。主工作区无法被删除。 repair[<路径>...]-
如果工作区管理文件由于外部因素而损坏或过期,在可能的情况下对其进行修复。
例如,如果主工作区(或裸仓库)被移动,链接工作区将无法定位它。在主工作区中运行
repair将重新建立从链接工作区回到主工作区的连接。同样,如果在未使用
gitworktreemove的情况下移动了链接工作区的工作目录,主工作区(或裸仓库)将无法找到它。在最近移动的工作区中运行repair将重新建立连接。如果移动了多个链接工作区,可以从任何工作区中运行repair并将每个工作区的新 <路径> 作为参数传入,从而重新建立到所有指定路径的连接。如果主工作区和链接工作区都是手动移动或复制的,那么在主工作区中运行
repair并指定每个链接工作区的新 <路径>,将重新建立所有双向的连接。 unlock-
解锁工作区,允许其被修剪、移动或删除。
选项
-f--force-
默认情况下,当 <提交对象> 是一个已被另一个工作区检出的分支名称,或者 <路径> 已经分配给某个工作区但该路径已丢失(例如,如果手动删除了 <路径>)时,
add会拒绝创建新的工作区。此选项会覆盖这些安全保护。要添加一个丢失但已锁定的工作区路径,请指定两次--force。move拒绝移动已锁定的工作区,除非指定了两次--force。如果目标路径已分配给其他工作区但该路径已丢失(例如手动删除了 <新路径>),则使用--force允许继续移动;如果目标路径被锁定,请指定两次--force。remove拒绝删除不干净的工作区,除非使用了--force。要删除锁定的工作区,请指定两次--force。 -b<新分支>-B<新分支>-
配合
add使用时,创建一个名为 <新分支> 的新分支(起点为 <提交对象>),并在新工作区中检出 <新分支>。如果省略了 <提交对象>,则默认为HEAD。默认情况下,如果新分支已经存在,-b将拒绝创建它。-B则会覆盖此保护措施,将 <新分支> 重置为 <提交对象>。 -d--detach-
配合
add使用时,在新工作区中使HEAD处于分离状态。参见 git-checkout[1] 中的“DETACHED HEAD”(分离头指针)。 --checkout--no-checkout-
默认情况下,
add会检出 <提交对象>,但是,可以使用--no-checkout来抑制检出,以便进行自定义(例如配置稀疏检出)。参见 git-read-tree[1] 中的“稀疏检出(Sparse checkout)”。 --guess-remote--no-guess-remote-
配合
worktreeadd<路径> 使用且没有 <提交对象> 时,如果在恰好一个远程仓库中存在与 <路径> 的基名(basename)匹配的跟踪分支,则不会从HEAD创建新分支,而是将新分支基于该远程跟踪分支,并将该远程跟踪分支标记为新分支的“上游(upstream)”。这也可以通过使用
worktree.guessRemote配置选项设置为默认行为。 --relative-paths--no-relative-paths-
使用相对路径或绝对路径(默认)链接工作区。覆盖
worktree.useRelativePaths配置选项,请参见 git-config[1]。配合
repair使用时,如果存在绝对/相对路径不匹配,即使链接本身是正确的,链接文件也会被更新。 --track--no-track-
创建新分支时,如果 <提交对象> 是一个分支,则将其标记为新分支的“上游”。如果 <提交对象> 是远程跟踪分支,则这是默认行为。有关详细信息,请参阅 git-branch[1] 中的
--track。 --lock-
在创建后保持工作区锁定。这相当于在
gitworktreeadd之后运行gitworktreelock,但这样可以避免竞态条件。 -n--dry-run-
配合
prune使用时,不删除任何内容;仅报告它将要删除的内容。 --orphan-
配合
add使用时,使新工作区和索引(index)为空,并将工作区与一个名为 <新分支> 的未出生分支关联。 --porcelain-
配合
list使用时,输出易于脚本解析的格式。此格式在不同 Git 版本之间以及不受用户配置影响下将保持稳定。建议将其与-z结合使用。详见下文。 -z-
在
list中指定--porcelain时,用 NUL 而不是换行符来结束每一行。这使得在工作区路径包含换行符时仍然能够解析输出。 -q--quiet-
配合
add使用时,抑制反馈消息。 -v--verbose-
配合
prune使用时,报告所有被删除的内容。配合
list使用时,输出关于工作区的额外信息(见下文)。 --expire<时间>-
配合
prune使用时,仅修剪早于 <时间> 的丢失工作区。配合
list使用时,如果丢失的工作区早于 <时间>,则将其标注为可修剪(prunable)。 --reason<字符串>-
配合
lock或与add--lock一起使用时,说明锁定工作区的原因。 - <工作区>
-
可以通过相对或绝对路径来标识工作区。
如果工作区路径中的最后几个路径组件在所有工作区中是唯一的,则可用于标识该工作区。例如,如果您只有两个工作区,分别位于
/abc/def/ghi和/abc/def/ggg,那么使用ghi或def/ghi就足以指向前者。
引用
当使用多个工作区时,某些引用(refs)在所有工作区之间共享,而其他引用则特定于单个工作区。一个例子是 HEAD,它在每个工作区中都是不同的。本节介绍共享规则以及如何从一个工作区访问另一个工作区的引用。
通常,所有伪引用(pseudo refs)都是每个工作区专属的,而所有以 refs/ 开头的引用都是共享的。伪引用是指像 HEAD 这样直接位于 $GIT_DIR 下而不是在 $GIT_DIR/refs 内部的引用。然而也有例外:refs/bisect、refs/worktree 和 refs/rewritten 内部的引用是不共享的。
每个工作区专属的引用仍可通过两个特殊路径 main-worktree 和 worktrees 从另一个工作区进行访问。前者提供了对主工作区的专属引用的访问,而后者则提供了对所有链接工作区的访问。
例如,main-worktree/HEAD 或 main-worktree/refs/bisect/good 会分别解析为与主工作区的 HEAD 和 refs/bisect/good 相同的值。类似地,worktrees/foo/HEAD 或 worktrees/bar/refs/bisect/bad 与 $GIT_COMMON_DIR/worktrees/foo/HEAD 和 $GIT_COMMON_DIR/worktrees/bar/refs/bisect/bad 相同。
要访问引用,最好不要直接在 $GIT_DIR 内部查看。相反,请使用诸如 git-rev-parse[1] 或 git-update-ref[1] 之类的命令,它们会正确处理引用。
配置文件
默认情况下,仓库的 config 配置文件在所有工作区之间共享。如果公共配置文件中存在配置变量 core.bare 或 core.worktree,且未启用 extensions.worktreeConfig,则它们将仅应用于主工作区。
为了实现特定于工作区的配置,您可以启用 worktreeConfig 扩展,例如:
$ git config extensions.worktreeConfig true
在此模式下,特定的配置会保留在由 git rev-parse --git-path config.worktree 指向的路径中。您可以使用 git config --worktree 在此文件中添加或更新配置。旧版本的 Git 将拒绝访问带有此扩展的仓库。
请注意,在此文件中,core.bare 和 core.worktree 的例外不复存在。如果它们存在于 $GIT_DIR/config 中,则必须将它们移至主工作区的 config.worktree 中。您也可以借此机会审查并移动您不想共享到所有工作区的其他配置。
-
core.worktree绝不应该被共享。 -
core.bare如果其值被设为core.bare=true,则不应该被共享。 -
core.sparseCheckout不应当共享,除非您确定始终对所有工作区使用稀疏检出。
有关更多详细信息,请参阅 git-config[1] 中关于 extensions.worktreeConfig 的文档。
详细信息
每个链接工作区在仓库的 $GIT_DIR/worktrees 目录中都有一个专属的子目录。该专属子目录的名称通常是链接工作区路径的基名(base name),可能会在末尾附加一个数字以使其唯一。例如,当 $GIT_DIR=/path/main/.git 时,命令 git worktree add /path/other/test-next next 将在 /path/other/test-next 中创建链接工作区,并创建 $GIT_DIR/worktrees/test-next 目录(如果 test-next 已被占用,则为 $GIT_DIR/worktrees/test-next1)。
在链接工作区中,$GIT_DIR 被设置为指向该专属目录(例如示例中的 /path/main/.git/worktrees/test-next),而 $GIT_COMMON_DIR 被设置为指向主工作区的 $GIT_DIR(例如 /path/main/.git)。这些设置是在位于链接工作区顶层目录下的一个 .git 文件中进行的。
通过 git rev-parse --git-path 进行的路径解析会根据具体路径使用 $GIT_DIR 或 $GIT_COMMON_DIR。例如,在链接工作区中,git rev-parse --git-path HEAD 将返回 /path/main/.git/worktrees/test-next/HEAD(而不是 /path/other/test-next/.git/HEAD 或 /path/main/.git/HEAD),而 git rev-parse --git-path refs/heads/master 会使用 $GIT_COMMON_DIR 并返回 /path/main/.git/refs/heads/master,因为引用在所有工作区中是共享的,除了 refs/bisect、refs/worktree 和 refs/rewritten。
欲了解更多信息,请参见 gitrepository-layout[5]。经验法则是在您需要直接访问 $GIT_DIR 内部的某些内容时,不要对路径属于 $GIT_DIR 还是 $GIT_COMMON_DIR 做任何假设。请使用 git rev-parse --git-path 来获取最终路径。
如果您手动移动了链接工作区,您需要更新该条目目录下的 gitdir 文件。例如,如果链接工作区被移动到 /newpath/test-next 并且其 .git 文件指向 /path/main/.git/worktrees/test-next,那么请将 /path/main/.git/worktrees/test-next/gitdir 更新为指向 /newpath/test-next。更好的是,直接运行 git worktree repair 自动重新建立连接。
为了防止 $GIT_DIR/worktrees 条目被修剪(这在某些情况下很有用,例如条目的工作区存储在便携式设备上时),可以使用 git worktree lock 命令,该命令会在该条目的目录下添加一个名为 locked 的文件。该文件以纯文本形式包含锁定原因。例如,如果链接工作区的 .git 文件指向 /path/main/.git/worktrees/test-next,那么一个名为 /path/main/.git/worktrees/test-next/locked 的文件将防止 test-next 条目被修剪。详见 gitrepository-layout[5]。
当启用了 extensions.worktreeConfig 时,配置文件 .git/worktrees/<id>/config.worktree 会在读取 .git/config 之后被读取。
列表输出格式
worktree list 命令有两种输出格式。默认格式以单行分列显示详细信息。例如:
$ git worktree list /path/to/bare-source (bare) /path/to/linked-worktree abcd1234 [master] /path/to/other-linked-worktree 1234abc (detached HEAD)
该命令还会根据工作区的状态显示标注。这些标注为:
-
如果工作区被锁定,则显示
locked。 -
如果工作区可以通过
gitworktreeprune被修剪,则显示prunable。
$ git worktree list /path/to/linked-worktree abcd1234 [master] /path/to/locked-worktree acbd5678 (brancha) locked /path/to/prunable-worktree 5678abc (detached HEAD) prunable
对于这些标注,可能还提供了一个原因,可以在详细(verbose)模式下查看。届时,标注会移动到下一行并缩进,随后跟着附加信息。
$ git worktree list --verbose /path/to/linked-worktree abcd1234 [master] /path/to/locked-worktree-no-reason abcd5678 (detached HEAD) locked /path/to/locked-worktree-with-reason 1234abcd (brancha) locked: worktree path is mounted on a portable device /path/to/prunable-worktree 5678abc1 (detached HEAD) prunable: gitdir file points to non-existent location
请注意,如果存在附加信息,标注会移动到下一行,否则它会保留在与工作区本身相同的行上。
Porcelain 格式
Porcelain 格式的每个属性占用一行。如果指定了 -z,则行以 NUL 结束而不是换行符。属性列出时包含一个标签和一个值,中间用单个空格分隔。布尔值属性(如 bare 和 detached)仅列出标签,并且仅在值为真时才会出现。某些属性(如 locked)可以仅列出标签,也可以带上值,这取决于是否提供了原因。工作区的第一个属性始终是 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 worktree /path/to/linked-worktree-locked-no-reason HEAD 5678abc5678abc5678abc5678abc5678abc5678c branch refs/heads/locked-no-reason locked worktree /path/to/linked-worktree-locked-with-reason HEAD 3456def3456def3456def3456def3456def3456b branch refs/heads/locked-with-reason locked reason why is locked worktree /path/to/linked-worktree-prunable HEAD 1233def1234def1234def1234def1234def1234b detached prunable gitdir file points to non-existent location
除非使用了 -z,否则锁定原因中的任何“异常”字符(例如换行符)都会被转义,并且整个原因将被加引号,这与配置变量 core.quotePath 所解释的机制相同(参见 git-config[1])。例如:
$ git worktree list --porcelain ... locked "reason\nwhy is locked" ...
示例
您正处于重构会话的中途,您的老板进来了,要求您立即修复一些问题。通常您可能会使用 git-stash[1] 将当前的修改临时存储起来,但是,由于您的工作区处于极其混乱的状态(包含了各种新建、移动和删除的文件,以及零零散散扔得到处都是的代码碎片),您不想冒任何干扰它的风险。相反,您可以创建一个临时的链接工作区来进行紧急修复,完成后将其删除,然后恢复之前未完成的重构会话。
$ git worktree add -b emergency-fix ../temp master $ pushd ../temp # ... hack hack hack ... $ git commit -a -m 'emergency fix for boss' $ popd $ git worktree remove ../temp
配置
本节中以下所有内容均从 git-config[1] 文档中选择性地包含。内容与彼处相同:
worktree.guessRemote-
如果未指定分支且未使用
-b、-B、--detach,那么gitworktreeadd默认会从 HEAD 创建一个新分支。如果将worktree.guessRemote设置为 true,则worktreeadd将尝试寻找一个远程跟踪分支,其名称与新分支名称唯一匹配。如果存在这样的分支,它将被检出并被设置为新分支的“上游(upstream)”。如果找不到匹配的分支,它会回退到从当前的HEAD创建一个新分支。 worktree.useRelativePaths-
使用相对路径(当为 “
true” 时)或绝对路径(当为 “false” 时)来链接工作区。这对于仓库和工作区可能在不同位置或环境之间移动的配置特别有用。默认为 “false”。请注意,将
worktree.useRelativePaths设置为 “true” 意味着启用extensions.relativeWorktrees配置(参见 git-config[1]),从而使其与旧版本的 Git 不兼容。