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
来解释工作树被锁定的原因。
add <path> [<commit-ish>]
创建<path>
并将<commit-ish>
签出到其中。新的工作目录链接到当前存储库,共享除工作目录特定文件(如HEAD,索引等)之外的所有内容。-
也可以指定为<commit-ish>
;它与@{-1}
同义。
如果< commit-ish>是一个分支名称(称之为<branch>
)并且未找到,并且既没有使用-b
也没有-B
或--detach
,但是在一个远程中确实存在跟踪分支(称之为<remote>
)使用匹配的名称,视为等效于:
$ git worktree add --track -b <branch> <path> <remote>/<branch>
如果分支存在于多个遥控器中,并且其中一个由checkout.defaultRemote
配置变量命名,我们将使用该分支用于消除歧义,即使<branch>
在所有遥控器中都不是唯一的。将其设置为例如如果<branch>
不明确但存在于_原点_遥控器上,checkout.defaultRemote=origin
总是从那里检出远程分支。另见 git-config [1] 中的checkout.defaultRemote
。
如果省略<commit-ish>
并且既不使用-b
也不使用-B
和--detach
,那么为方便起见,新工作树与以$(basename <path>)
命名的分支(称为<branch>
)相关联。如果<branch>
不存在,将自动创建基于HEAD的新分支,就像给出-b <branch>
一样。如果<branch>
确实存在,它将在新的工作树中检出,如果它没有在其他任何地方检出,否则命令将拒绝创建工作树(除非使用--force
)。
list
列出每个工作树的详细信息。首先列出主要工作树,然后列出每个链接的工作树。输出详细信息包括工作树是否裸露,当前检出的修订版,以及当前检出的分支(或者_分离HEAD_ ,如果没有)。
lock
如果工作树位于未始终安装的便携式设备或网络共享上,请将其锁定以防止其管理文件被自动修剪。这也可以防止它被移动或删除。 (可选)使用--reason
指定锁定的原因。
move
将工作树移动到新位置。请注意,无法移动主工作树或包含子模块的链接工作树。
prune
修剪$ GIT_DIR / worktrees中的工作树信息。
remove
删除一个工作树。只能删除干净的工作树(没有未跟踪的文件,也不会删除跟踪文件中的修改)。可以使用--force
删除不干净的工作树或带子模块的工作树。无法删除主工作树。
unlock
解锁工作树,允许对其进行修剪,移动或删除。
-f
--force
默认情况下,add
拒绝创建新的工作树,当<commit-ish>
是分支名称并且已经被另一个工作树检出,或者<path>
已经分配给某个工作树但是丢失了(例如,如果<path>
被手动删除)。此选项会覆盖这些安全措施。要添加缺失但已锁定的工作树路径,请指定--force
两次。
move
拒绝移动锁定的工作树,除非指定了两次--force
。
remove
拒绝删除不干净的工作树,除非使用--force
。要删除锁定的工作树,请指定--force
两次。
-b <new-branch>
-B <new-branch>
使用add
,从<commit-ish>
开始创建一个名为<new-branch>
的新分支,并将<new-branch>
签出到新的工作树中。如果省略<commit-ish>
,则默认为HEAD。默认情况下,-b
拒绝创建新分支(如果已存在)。 -B
会覆盖此保护措施,将<new-branch>
重置为<commit-ish>
。
--detach
使用add
,在新工作树中分离HEAD。请参见 git-checkout [1] 中的“DETACHED HEAD”。
--[no-]checkout
默认情况下,add
检出<commit-ish>
,但是,--no-checkout
可用于抑制检出以进行自定义,例如配置稀疏检出。请参见 git-read-tree [1] 中的“稀疏检出”。
--[no-]guess-remote
使用worktree add <path>
,不使用<commit-ish>
,而不是从HEAD创建新分支,如果在一个与<path>
的基本名称匹配的远程中存在跟踪分支,则将新分支基于远程跟踪分支,并标记远程跟踪分支作为新分支的“上游”。
也可以使用worktree.guessRemote
配置选项将其设置为默认行为。
--[no-]track
创建新分支时,如果<commit-ish>
是分支,则将其标记为新分支的“上游”。如果<commit-ish>
是远程跟踪分支,则这是默认值。有关详细信息,请参阅 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
,仅使未使用的工作树超过< time>。
--reason <string>
使用lock
解释工作树被锁定的原因。
<worktree>
工作树可以通过路径来识别,无论是相对的还是绝对的。
如果工作树路径中的最后一个路径组件在工作树中是唯一的,则可以使用它来识别工作树。例如,如果你只有两个工作树,在“/ abc / def / ghi”和“/ abc / def / ggg”,那么“ghi”或“def / ghi”足以指向前工作树。
在多个工作树中,一些参考树可以在所有工作树之间共享,一些参考树是本地的。一个例子是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.bare
或core.worktree
已经存在于配置文件中,它们将仅应用于主工作树。
为了具有特定于工作树的配置,您可以打开“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.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/<id>/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
一般的多次检出仍然是实验性的,对子模块的支持是不完整的。建议不要对超级项目进行多次检出。
部分 git [1] 套件