设置和配置
获取和创建项目
基本快照
分支与合并
共享和更新项目
检查和比较
打补丁
调试
电子邮件
外部系统
服务器管理
指南
管理
底层命令
- 2.48.1 → 2.50.1 无更改
-
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
概要
git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]] [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>] git worktree list [-v | --porcelain [-z]] git worktree lock [--reason <string>] <worktree> git worktree move <worktree> <new-path> git worktree prune [-n] [-v] [--expire <expire>] git worktree remove [-f] <worktree> git worktree repair [<path>…] git worktree unlock <worktree>
描述
管理附加到同一仓库的多个工作区。
Git 仓库支持多个工作区,允许您同时检出多个分支。通过 git
worktree
add
命令,可以将新的工作区与仓库关联起来,并附带额外的元数据,以区分同一仓库中的不同工作区。工作区连同其元数据被称为“工作区”。
这个新的工作区被称为“链接工作区”(linked worktree),与 git-init[1] 或 git-clone[1] 准备的“主工作区”(main worktree)相对。一个仓库有一个主工作区(如果它不是裸仓库),以及零个或多个链接工作区。当您完成使用链接工作区后,请使用 git
worktree
remove
命令将其删除。
最简单的形式是,git
worktree
add
<path> 会自动创建一个新分支,其名称为 <path> 的最后一个组件,如果您打算处理一个新主题,这会很方便。例如,git
worktree
add
../hotfix
会创建新分支 hotfix
并将其检出到路径 ../hotfix
。如果要在新的工作区中处理现有分支,请使用 git
worktree
add
<path> <branch>。另一方面,如果您只是计划进行一些实验性更改或测试,而不想干扰现有开发,那么创建一个不与任何分支关联的*一次性*工作区通常会很方便。例如,git
worktree
add
-d
<path> 会创建一个新的工作区,其 HEAD
处于分离状态,指向与当前分支相同的提交。
如果一个工作区在没有使用 git
worktree
remove
的情况下被删除,那么其相关的管理文件(位于仓库中,参见下文“详情”)最终会被自动移除(参见 git-config[1] 中的 gc.worktreePruneExpire
),或者您可以在主工作区或任何链接工作区中运行 git
worktree
prune
来清理任何过时的管理文件。
如果链接工作区的工作目录存储在便携设备或网络共享上,并且不总是挂载的,您可以通过执行 git
worktree
lock
命令来防止其管理文件被修剪,您可以选择指定 --reason
来解释锁定该工作区的原因。
命令
- add <path> [<commit-ish>]
-
在 <path> 创建一个工作区并检出 <commit-ish> 到其中。新的工作区链接到当前仓库,共享除每个工作区特有的文件(如
HEAD
、index
等)之外的所有内容。为方便起见,<commit-ish> 可以是裸的“-
”,这等同于@{-1}
。如果 <commit-ish> 是一个分支名称(称之为 <branch>)且未找到,并且没有使用
-b
、-B
或--detach
,但恰好在一个远程仓库(称之为 <remote>)中存在一个同名跟踪分支,则将其视为等同于$ git worktree add --track -b <branch> <path> <remote>/<branch>
如果分支存在于多个远程仓库中,并且其中一个由
checkout.defaultRemote
配置变量指定,我们将使用该远程仓库进行消歧,即使 <branch> 在所有远程仓库中并非唯一。例如,将其设置为checkout.defaultRemote=origin
,以便在 <branch> 模棱两可但存在于origin
远程仓库时,总是从那里检出远程分支。另请参阅 git-config[1] 中的checkout.defaultRemote
。如果省略 <commit-ish> 并且没有使用
-b
、-B
或--detach
,那么为方便起见,新的工作区将与一个分支(称之为 <branch>)关联,该分支以$
(basename
<path>) 命名。如果 <branch> 不存在,则会自动创建一个基于HEAD
的新分支,如同给定了-b
<branch>。如果 <branch> 确实存在,并且没有在其他地方被检出,它将在新的工作区中被检出,否则命令将拒绝创建该工作区(除非使用了--force
)。如果省略 <commit-ish>,且没有使用
--detach
或--orphan
,并且没有有效的本地分支(如果指定了--guess-remote
则也没有远程分支),那么为方便起见,新的工作区将与一个新的未出生(unborn)分支 <branch> 关联(如果既没有使用-b
也没有使用-B
,则以$
(basename
<path>) 命名),如同向命令传递了--orphan
。如果仓库有远程且使用了--guess-remote
,但不存在任何远程或本地分支,则命令将失败并发出警告,提醒用户首先从远程仓库抓取(fetch)(或通过使用-f/--force
覆盖)。 - list
-
列出每个工作区的详细信息。主工作区首先列出,然后是每个链接工作区。输出详细信息包括工作区是否为裸仓库、当前检出的版本、当前检出的分支(如果没有则是“分离的 HEAD”)、如果工作区被锁定则显示“locked”、如果工作区可以通过
prune
命令修剪则显示“prunable”。 - lock
-
如果一个工作区位于便携设备或网络共享上且并非总是挂载的,则将其锁定以防止其管理文件被自动修剪。这也能防止它被移动或删除。您可以选择使用
--reason
来指定锁定的原因。 - move
-
将工作区移动到新位置。请注意,主工作区或包含子模块的链接工作区不能使用此命令移动。(但是,如果您手动移动了主工作区,
git
worktree
repair
命令可以重新建立与链接工作区的连接。) - prune
-
修剪
$GIT_DIR/worktrees
中的工作区信息。 - remove
-
移除一个工作区。只有干净的工作区(没有未跟踪的文件且跟踪文件没有修改)才能被移除。不干净的工作区或包含子模块的工作区可以使用
--force
移除。主工作区不能被移除。 - repair [<path>…]
-
如果工作区管理文件因外部因素而损坏或过时,则尽可能修复它们。
例如,如果主工作区(或裸仓库)被移动,链接工作区将无法找到它。在主工作区中运行
repair
将重新建立从链接工作区到主工作区的连接。同样,如果链接工作区的工作目录在没有使用
git
worktree
move
的情况下被移动,主工作区(或裸仓库)将无法找到它。在最近移动的工作区内运行repair
将重新建立连接。如果移动了多个链接工作区,从任何工作区运行repair
并以每个工作区的新 <path> 作为参数,将重新建立与所有指定路径的连接。如果主工作区和链接工作区都已被手动移动或复制,那么在主工作区中运行
repair
并指定每个链接工作区的新 <path>,将重新建立双向的所有连接。 - unlock
-
解锁一个工作区,允许其被修剪、移动或删除。
选项
- -f
- --force
-
默认情况下,当 <commit-ish> 是一个分支名称且已被另一个工作区检出,或者 <path> 已被分配给某个工作区但其目录缺失(例如,如果 <path> 被手动删除)时,
add
会拒绝创建新的工作区。此选项会覆盖这些安全保护措施。要添加一个缺失但被锁定的工作区路径,请指定两次--force
。move
拒绝移动锁定的工作区,除非指定两次--force
。如果目标路径已被分配给其他工作区但其目录缺失(例如,如果 <new-path> 被手动删除),则--force
允许继续移动;如果目标路径被锁定,则使用两次--force
。remove
拒绝移除不干净的工作区,除非使用--force
。要移除锁定的工作区,请指定两次--force
。 - -b <new-branch>
- -B <new-branch>
-
使用
add
命令,创建一个名为 <new-branch> 的新分支,从 <commit-ish> 开始,并将 <new-branch> 检出到新的工作区中。如果省略 <commit-ish>,则默认为HEAD
。默认情况下,如果新分支已存在,-b
会拒绝创建。-B
会覆盖此安全措施,将 <new-branch> 重置为 <commit-ish>。 - -d
- --detach
-
使用
add
命令,分离新工作区中的HEAD
。参见 git-checkout[1] 中的“分离的 HEAD”(DETACHED HEAD)。 - --[no-]checkout
-
默认情况下,
add
会检出 <commit-ish>,但是,可以使用--no-checkout
来抑制检出,以便进行自定义,例如配置稀疏检出(sparse-checkout)。参见 git-read-tree[1] 中的“稀疏检出”(Sparse checkout)。 - --[no-]guess-remote
-
使用
worktree
add
<path>,且不带 <commit-ish> 时,如果恰好有一个远程跟踪分支的名称与 <path> 的基本名称匹配,则新分支将基于该远程跟踪分支创建,并将其标记为新分支的“上游”,而不是从HEAD
创建新分支。这也可以通过使用
worktree.guessRemote
配置选项设置为默认行为。 - --[no-]relative-paths
-
使用相对路径或绝对路径(默认)链接工作区。此选项会覆盖
worktree.useRelativePaths
配置选项,详见 git-config[1]。使用
repair
时,如果存在绝对/相对路径不匹配的情况,即使链接是正确的,链接文件也会被更新。 - --[no-]track
-
创建新分支时,如果 <commit-ish> 是一个分支,则将其标记为新分支的“上游”。如果 <commit-ish> 是一个远程跟踪分支,则这是默认行为。详见 git-branch[1] 中的
--track
。 - --lock
-
创建后保持工作区锁定。这等同于在
git
worktree
add
之后执行git
worktree
lock
,但没有竞争条件。 - -n
- --dry-run
-
使用
prune
时,不移除任何内容;只报告它将移除什么。 - --orphan
-
使用
add
时,使新的工作区和索引为空,并将该工作区与一个名为 <new-branch> 的新的未出生分支关联起来。 - --porcelain
-
使用
list
时,以易于脚本解析的格式输出。这种格式在不同 Git 版本之间以及无论用户配置如何都将保持稳定。建议将其与-z
结合使用。详见下文。 - -z
-
当
list
命令指定--porcelain
时,每行以 NUL 字符而不是换行符终止。这使得当工作区路径包含换行符时,可以解析输出。 - -q
- --quiet
-
使用
add
时,抑制反馈消息。 - -v
- --verbose
-
使用
prune
时,报告所有移除操作。使用
list
时,输出关于工作区的额外信息(详见下文)。 - --expire <time>
-
使用
prune
时,只使旧于 <time> 的未使用的工作区过期。使用
list
时,如果缺失的工作区旧于 <time>,则将其标注为可修剪(prunable)。 - --reason <string>
-
使用
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=true
,则不应共享core.bare
。 -
core.sparseCheckout
不应被共享,除非您确定所有工作区都始终使用稀疏检出(sparse checkout)。
详见 git-config[1] 中 extensions.worktreeConfig
的文档。
详情
每个链接工作区在仓库的 $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
目录(如果 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
。 -
如果工作区可以通过
git
worktree
prune
修剪,则显示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
对于这些注释,可能还会提供原因,可以在详细模式下查看。注释会移到下一行,缩进后跟着附加信息。
$ 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
请注意,如果有附加信息,注释会移到下一行,否则它会留在工作区本身的同一行。
瓷器格式
瓷器格式中,每个属性占据一行。如果给定 -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