# git-worktree
> 原文: [https://git-scm.com/docs/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>]
```
創建`<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]](https://git-scm.com/docs/git-config) 中的`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
```
解鎖工作樹,允許對其進行修剪,移動或刪除。
## OPTIONS
```
-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]](https://git-scm.com/docs/git-checkout) 中的“DETACHED HEAD”。
```
--[no-]checkout
```
默認情況下,`add`檢出`<commit-ish>`,但是,`--no-checkout`可用于抑制檢出以進行自定義,例如配置稀疏檢出。請參見 [git-read-tree [1]](https://git-scm.com/docs/git-read-tree) 中的“稀疏檢出”。
```
--[no-]guess-remote
```
使用`worktree add <path>`,不使用`<commit-ish>`,而不是從HEAD創建新分支,如果在一個與`<path>`的基本名稱匹配的遠程中存在跟蹤分支,則將新分支基于遠程跟蹤分支,并標記遠程跟蹤分支作為新分支的“上游”。
也可以使用`worktree.guessRemote`配置選項將其設置為默認行為。
```
--[no-]track
```
創建新分支時,如果`<commit-ish>`是分支,則將其標記為新分支的“上游”。如果`<commit-ish>`是遠程跟蹤分支,則這是默認值。有關詳細信息,請參閱 [git-branch [1]](https://git-scm.com/docs/git-branch) 中的“--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”足以指向前工作樹。
## 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]](https://git-scm.com/docs/git-rev-parse) 或 [git-update-ref [1]](https://git-scm.com/docs/git-update-ref) 之類的命令,它們將正確處理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]](https://git-scm.com/docs/gitrepository-layout) 。經驗法則是,當您需要直接訪問$ 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]](https://git-scm.com/docs/gitrepository-layout) 。
啟用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]](https://git-scm.com/docs/git-stash) 臨時存儲您的更改,但是,您的工作樹處于混亂狀態(使用新的,移動的和刪除的文件以及其他零碎的部分)散落在你周圍,你不想冒任何干擾它的風險。相反,您創建一個臨時鏈接工作樹來進行緊急修復,完成后將其刪除,然后恢復您之前的重構會話。
```
$ 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]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree