git-worktree

原文: https://git-scm.com/docs/git-worktree

名称

git-worktree - 管理多个工作树

概要

git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>]
git worktree list [--porcelain]
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 unlock <worktree>

描述

管理连接到同一存储库的多个工作树。

git存储库可以支持多个工作树,允许您一次签出多个分支。使用git worktree add,新的工作树与存储库相关联。这个新的工作树称为“链接工作树”,而不是“git init”或“git clone”编写的“主工作树”。存储库有一个主要工作树(如果它不是裸存储库)和零个或多个链接工作树。完成链接的工作树后,使用git worktree remove将其删除。

如果在不使用git worktree remove的情况下删除工作树,则其关联的管理文件(位于下面的“详细信息”)最终将自动删除(请参阅 [git-config中的gc.worktreePruneExpire [1] ]](https://git-scm.com/docs/git-config) ),或者您可以在主要或任何链接的工作树中运行git worktree prune来清理任何陈旧的管理文件。

如果链接的工作树存储在并非总是挂载的便携式设备或网络共享上,则可以通过发出git worktree lock命令来阻止其管理文件被修剪,可选择指定--reason来解释工作树被锁定的原因。

COMMANDS

 add <path> [<commit-ish>] 

创建&lt;path&gt;并将&lt;commit-ish&gt;签出到其中。新的工作目录链接到当前存储库,共享除工作目录特定文件(如HEAD,索引等)之外的所有内容。-也可以指定为&lt;commit-ish&gt;;它与@{-1}同义。

如果&lt; commit-ish&gt;是一个分支名称(称之为&lt;branch&gt;)并且未找到,并且既没有使用-b也没有-B--detach,但是在一个远程中确实存在跟踪分支(称之为&lt;remote&gt;)使用匹配的名称,视为等效于:

$ git worktree add --track -b <branch> <path> <remote>/<branch>

如果分支存在于多个遥控器中,并且其中一个由checkout.defaultRemote配置变量命名,我们将使用该分支用于消除歧义,即使&lt;branch&gt;在所有遥控器中都不是唯一的。将其设置为例如如果&lt;branch&gt;不明确但存在于_原点_遥控器上,checkout.defaultRemote=origin总是从那里检出远程分支。另见 git-config [1] 中的checkout.defaultRemote

如果省略&lt;commit-ish&gt;并且既不使用-b也不使用-B--detach,那么为方便起见,新工作树与以$(basename &lt;path&gt;)命名的分支(称为&lt;branch&gt;)相关联。如果&lt;branch&gt;不存在,将自动创建基于HEAD的新分支,就像给出-b &lt;branch&gt;一样。如果&lt;branch&gt;确实存在,它将在新的工作树中检出,如果它没有在其他任何地方检出,否则命令将拒绝创建工作树(除非使用--force)。

 list 

列出每个工作树的详细信息。首先列出主要工作树,然后列出每个链接的工作树。输出详细信息包括工作树是否裸露,当前检出的修订版,以及当前检出的分支(或者分离HEAD ,如果没有)。

 lock 

如果工作树位于未始终安装的便携式设备或网络共享上,请将其锁定以防止其管理文件被自动修剪。这也可以防止它被移动或删除。 (可选)使用--reason指定锁定的原因。

 move 

将工作树移动到新位置。请注意,无法移动主工作树或包含子模块的链接工作树。

 prune 

修剪$ GIT_DIR / worktrees中的工作树信息。

 remove 

删除一个工作树。只能删除干净的工作树(没有未跟踪的文件,也不会删除跟踪文件中的修改)。可以使用--force删除不干净的工作树或带子模块的工作树。无法删除主工作树。

 unlock 

解锁工作树,允许对其进行修剪,移动或删除。

OPTIONS

 -f 
 --force 

默认情况下,add拒绝创建新的工作树,当&lt;commit-ish&gt;是分支名称并且已经被另一个工作树检出,或者&lt;path&gt;已经分配给某个工作树但是丢失了(例如,如果&lt;path&gt;被手动删除)。此选项会覆盖这些安全措施。要添加缺失但已锁定的工作树路径,请指定--force两次。

move拒绝移动锁定的工作树,除非指定了两次--force

remove拒绝删除不干净的工作树,除非使用--force。要删除锁定的工作树,请指定--force两次。

 -b <new-branch> 
 -B <new-branch> 

使用add,从&lt;commit-ish&gt;开始创建一个名为&lt;new-branch&gt;的新分支,并将&lt;new-branch&gt;签出到新的工作树中。如果省略&lt;commit-ish&gt;,则默认为HEAD。默认情况下,-b拒绝创建新分支(如果已存在)。 -B会覆盖此保护措施,将&lt;new-branch&gt;重置为&lt;commit-ish&gt;

 --detach 

使用add,在新工作树中分离HEAD。请参见 git-checkout [1] 中的“DETACHED HEAD”。

 --[no-]checkout 

默认情况下,add检出&lt;commit-ish&gt;,但是,--no-checkout可用于抑制检出以进行自定义,例如配置稀疏检出。请参见 git-read-tree [1] 中的“稀疏检出”。

 --[no-]guess-remote 

使用worktree add &lt;path&gt;,不使用&lt;commit-ish&gt;,而不是从HEAD创建新分支,如果在一个与&lt;path&gt;的基本名称匹配的远程中存在跟踪分支,则将新分支基于远程跟踪分支,并标记远程跟踪分支作为新分支的“上游”。

也可以使用worktree.guessRemote配置选项将其设置为默认行为。

 --[no-]track 

创建新分支时,如果&lt;commit-ish&gt;是分支,则将其标记为新分支的“上游”。如果&lt;commit-ish&gt;是远程跟踪分支,则这是默认值。有关详细信息,请参阅 git-branch [1] 中的“–track”。

 --lock 

创建后保持工作树锁定。这相当于git worktree add之后的git worktree lock,但没有竞争条件。

 -n 
 --dry-run 

使用prune时,不要删除任何东西;只需报告它将删除的内容。

 --porcelain 

使用list,以易于解析的格式输出脚本。无论用户配置如何,这种格式在Git版本中都将保持稳定。请参阅下文了解详情。

 -q 
 --quiet 

使用_添加_,禁止反馈消息。

 -v 
 --verbose 

使用prune,报告所有删除。

 --expire <time> 

使用prune,仅使未使用的工作树超过&lt; time&gt;。

 --reason <string> 

使用lock解释工作树被锁定的原因。

 <worktree> 

工作树可以通过路径来识别,无论是相对的还是绝对的。

如果工作树路径中的最后一个路径组件在工作树中是唯一的,则可以使用它来识别工作树。例如,如果你只有两个工作树,在“/ abc / def / ghi”和“/ abc / def / ggg”,那么“ghi”或“def / ghi”足以指向前工作树。

REFS

在多个工作树中,一些参考树可以在所有工作树之间共享,一些参考树是本地的。一个例子是HEAD对于所有工作树都是不同的。本节介绍共享规则以及如何从另一个工作树访问refs。

通常,所有伪引用都是每个工作树,并且所有以“refs /”开头的引用都是共享的。伪引用类似HEAD,直接在GIT_DIR下而不是在GIT_DIR / refs内。这有一个例外:refs / bisect中的refs和不共享refs / worktree。

仍然可以通过两个特殊路径(main-worktree和worktree)从另一个工作树访问每个工作树的引用。前者允许访问主工作树的每个工作树参考,而后者访问所有链接的工作树。

例如,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相同。

要访问refs,最好不要直接查看GIT_DIR。而是使用诸如 git-rev-parse [1]git-update-ref [1] 之类的命令,它们将正确处理refs。

配置文件

默认情况下,存储库“config”文件在所有工作树之间共享。如果配置变量core.barecore.worktree已经存在于配置文件中,它们将仅应用于主工作树。

为了具有特定于工作树的配置,您可以打开“worktreeConfig”扩展名,例如:

$ git config extensions.worktreeConfig true

在此模式下,特定配置保留在git rev-parse --git-path config.worktree指向的路径中。您可以使用git config --worktree在此文件中添加或更新配置。较旧的Git版本将拒绝使用此扩展名访问存储库。

请注意,在此文件中,core.barecore.worktree的例外消失了。如果您之前在$ GIT_DIR / config中有它们,则必须将它们移动到主工作树的config.worktree。您也可以借此机会查看并移动您不想共享的其他配置到所有工作树:

  • 永远不要共享core.worktreecore.bare

  • 除非您确定始终对所有工作树使用稀疏检出,否则建议每个工作树使用core.sparseCheckout

细节

每个链接的工作树在存储库的$ 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在所有工作树之间共享,refs /除外平分和参考/工作树。

有关详细信息,请参阅 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_DIR / worktrees条目被修剪(这在某些情况下很有用,例如当条目的工作树存储在便携式设备上时),请使用git worktree lock命令,该命令添加名为_的文件锁定_到条目的目录。该文件包含纯文本的原因。例如,如果链接的工作树的.git文件指向/path/main/.git/worktrees/test-next,则名为/path/main/.git/worktrees/test-next/locked的文件将阻止test-next条目被修剪。有关详细信息,请参阅 gitrepository-layout [5]

启用extensions.worktreeConfig时,在.git/config之后读取配置文件.git/worktrees/&lt;id&gt;/config.worktree

列表输出格式

worktree list命令有两种输出格式。默认格式显示包含列的单行详细信息。例如:

$ git worktree list
/path/to/bare-source            (bare)
/path/to/linked-worktree        abcd1234 [master]
/path/to/other-linked-worktree  1234abc  (detached HEAD)

瓷器格式

瓷器格式每个属性都有一行。列出的属性标签和值由单个空格分隔。布尔属性(如_裸_和_分离_)仅作为标签列出,仅当值为真时才存在。工作树的第一个属性始终是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

例子

您正处于重构阶段,您的老板进来并要求您立即修复。您通常可以使用 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

BUGS

一般的多次检出仍然是实验性的,对子模块的支持是不完整的。建议不要对超级项目进行多次检出。

GIT

部分 git [1] 套件