Git从现有的远程分支添加工作树

vah*_*eds 18 git git-remote git-branch git-worktree

我是Git的新手.我搜索了很多,但没有发现与我的情况完全匹配.

我有一个个人的WinForms应用程序,在我的远程仓库中有3个分支(主分支和2个长分支):

master  #the common features are here like Core, DAL,...
north   #customized for A company (long-running)
razavi  #customized for B company (long-running)
Run Code Online (Sandbox Code Playgroud)

在我的办公室电脑上,我worktree为这些northrazavi分支机构添加2 :

$ git worktree list
C:/Source/nis     a6fb6e1 [master]
C:/Source/north   ebc7670 [north]
C:/Source/razavi  eed08a2 [razavi]
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都还可以,我决定从家里开始研究这个项目,但是在我的家用电脑上,当我尝试为这两个分支添加工作树时,它给了我一个错误:

$git worktree add -b north ../north north
fatal: A branch named 'north' already exists.
Run Code Online (Sandbox Code Playgroud)

我删除-b开关以不添加新分支,但它也不起作用.

如何worktree从现有的非本地分支添加远程?

更新(解决方案)

在解决了一段时间之后,我找到了解决问题的方法,实际上,这是一个--checkout错过的开关:

$ git worktree add --checkout ../north north
Run Code Online (Sandbox Code Playgroud)

我也会把它放在答案中.

tor*_*rek 24

TL; DR:你可能想要 git worktree add ../north north

首先,提醒(或其他人碰到这个问题,即将到来的信息):git worktree add要创建一个新的工作树,在同一时间,确保了这款新作树是使用不同的分支名从每一个其他工作树.这是因为,虽然每个添加的工作树都有自己的索引HEAD,但HEAD文件最终共享共享存储库中的底层分支指针.具有独立索引对象但具有相同底层分支的两个不同工作树导致用户处理一些棘手的问题.而不是试图弄清楚如何处理这些 - 通过教育程序员或提供工具来处理问题 - git worktree完全禁止这种情况.

因此,在创建新的工作树时想要创建新的分支名称是非常典型的.根据定义,新分支名称将自动与每个现有分支名称不同:

$ git checkout -b newbranch
Switched to a new branch 'newbranch'
$ git checkout -b newbranch
fatal: A branch named 'newbranch' already exists.
Run Code Online (Sandbox Code Playgroud)

这似乎很自然:没有人会对此感到惊讶.

除了在新添加的工作树中进行结账外,您的运行git worktree add方式与此类似git checkout -b.但是你已经有了一个名为的分支north.

如果此现有north分支无用,则可以将其删除.现在您没有命名的本地分支north,您可以创建一个新分支.

如果现有的north分支有用的,请不要删除它!如果它已经在某个现有的工作树中检出,请移动到该工作树并在那里进行处理.如果它不是在现有的一些工作树签出,你可以做一个新的工作树确实已经签出; 你只需要避免使用-b标志(和相应的分支名称):

git worktree add ../north north
Run Code Online (Sandbox Code Playgroud)

请注意,当您创建分支时,您不必重复自己:

git worktree add -b newbranch ../path
Run Code Online (Sandbox Code Playgroud)

将创建一个新的工作树../path,并用于git checkout -b newbranch填充它.您在以下情况下只需要分支名称:

  1. 你没用-b,而且
  2. 路径参数不分支的名称结束.

例如,如果要zorg在路径中的新工作树中签出现有分支../zorg,则可以运行:

git worktree add ../zorg
Run Code Online (Sandbox Code Playgroud)

这里,因为既没有-b zorg,也不是最后一个参数,Git的计算出的分支名称使用的最后一部分../zorg,这当然只是zorg,所以这种尝试将现有分行检查出zorg到新的工作树.

  • 它不起作用!我尝试`git worktree add ../north north`,正如我所说,它给了我一个错误`fatal: 'north' is already check out at 'C:/Source/nis'` (3认同)
  • 这个限制的原因很简单但很微妙:当你进行*新*提交时,Git 会将新提交的哈希 ID 写入 HEAD 所附加的分支名称中。假设您有两个工作树,W1 和 W2。进一步假设每个都将其 HEAD 附加到名称 B(用于分支)。这意味着两个工作树具有相同的*当前提交*。然后,您在 W1 中进行新提交,它将新提交的哈希 ID 写入名称 B。由于 *名称* 是共享的,因此两个工作树现在都有不同的 *当前提交* ...但是 W2 中的签出是*前一个*提交的。 (2认同)
  • 换句话说,W1 中更新名称 B 的提交行为“破坏”了 W2 中的设置。Git 需要名称 B 来包含 W1 中的“新”哈希 ID,但需要名称 B 来包含 W2 中的“旧”哈希 ID。这是不可能的,因此 `git worktree add` 通过禁止 W1 和 W2 同时使用 B 来禁止出现这种情况。 (2认同)

Von*_*onC 14

除了“猜测远程分支”之外,正如我在其他答案中解释的那样,Git 2.18(2018 年第二季度)还将提供一个新功能:
git worktree add”学会检查现有分支。

请参阅Thomas Gummerer ( )的提交 f60a7b7提交 6427f87提交 2c27002提交 d861d34(2018 年 4 月 24 日)。 帮助者:Eric Sunshine ( )(由Junio C Hamano 合并 -- --提交 10174da中,2018 年 5 月 23 日)tgummerer
sunshineco
gitster

worktree:教“ add”检查现有分支

当前“ git worktree add <path>”默认创建一个以路径的基本名称命名的新分支。
如果具有该名称的分支已存在,则该命令将拒绝执行任何操作,除非--force给出“ ”选项。

然而,我们可以做得更好一点,如果分支没有在其他地方签出,则将其签出。
这将帮助那些只想将现有分支签入新工作树的用户
,并节省一些击键次数。

As the current behaviour is to simply 'die()' when a branch with the name of the basename of the path already exists, there are no backwards compatibility worries here.

We will still 'die()' if the branch is checked out in another worktree, unless the --force flag is passed.

The documentation now states:

$ git worktree add --track -b <branch> <path> <remote>/<branch>
Run Code Online (Sandbox Code Playgroud)

If <commit-ish> is omitted and neither -b nor -B nor --detach used, then, as a convenience, the new worktree is associated with a branch (call it <branch>) named after $(basename <path>).

  • If <branch> doesn't exist, a new branch based on HEAD is automatically created as if -b <branch> was given.
  • If <branch> does exist, it will be checked out in the new worktree, if it's not checked out anywhere else, otherwise the command will refuse to create the worktree (unless --force is used).

Git 2.30 (Q1 2021) fixes the formulation of an error message with two placeholders in "git worktree add"(man) subcommand.

See commit b86339b (20 Nov 2020) by Matheus Tavares (matheustavares).
(Merged by Junio C Hamano -- gitster -- in commit f73ee0c, 30 Nov 2020)

worktree: fix order of arguments in error message

Signed-off-by: Matheus Tavares
Reviewed-by: Eric Sunshine

git worktree add(man) (without --force) errors out when given a path that is already registered as a worktree and the path is missing on disk.
But the cmd and path strings are switched on the error message.
Let's fix that.

This is about the error messages:

<path> is a missing but locked worktree
use '<cmd> -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear
Run Code Online (Sandbox Code Playgroud)

Or:

<path> is a missing but already registered worktree
use '<cmd> -f' to override, or 'unlock' and 'prune' or 'remove' to clear
Run Code Online (Sandbox Code Playgroud)

From the comments:

It doesn't work! I try git worktree add ../north north, and as I said it gives me an error fatal:

'north' is already checked out at 'C:/Source/nis'
Run Code Online (Sandbox Code Playgroud)

That error message should be clearer now (Q1 2022).

With Git 2.35 (Q1 2022), "git worktree add"(man) showed "Preparing worktree" message to the standard output stream, but when it failed, the message from die() went to the standard error stream.
Depending on the order the stdio streams are flushed at the program end, this resulted in confusing output.
It has been corrected by sending all the chatty messages to the standard error stream.

See commit b502524, commit da8fb6b (02 Dec 2021) by Eric Sunshine (sunshineco).
(Merged by Junio C Hamano -- gitster -- in commit 986eb34, 15 Dec 2021)

worktree: send "chatty" messages to stderr

Reported-by: Baruch Burstein
Signed-off-by: Eric Sunshine

The order in which the stdout and stderr streams are flushed is not guaranteed to be the same across platforms or libc implementations.
This lack of determinism can lead to anomalous and potentially confusing output if normal (stdout) output is flushed after error (stderr) output.
For instance, the following output which clearly indicates a failure due to a fatal error:

% git worktree add ../foo bar
Preparing worktree (checking out 'bar')
fatal: 'bar' is already checked out at '.../wherever'
Run Code Online (Sandbox Code Playgroud)

has been reported on Microsoft Windows to appear as:

% git worktree add ../foo bar
fatal: 'bar' is already checked out at '.../wherever'
Preparing worktree (checking out 'bar')
Run Code Online (Sandbox Code Playgroud)

which may confuse the reader into thinking that the command somehow recovered and ran to completion despite the error.

This problem crops up because the "chatty" status message "Preparing worktree" is sent to stdout, whereas the "fatal" error message is sent to stderr.

A common practice in Git is for "chatty" messages to be sent to stderr.
Therefore, a more appropriate fix is to adjust git-worktree to conform to that practice by sending its chatty messages to stderr rather than stdout as is currently the case.

There may be concern that relocating messages from stdout to stderr could break existing tooling, however, these messages are already internationalized, thus are unstable.
And, indeed, the "Preparing worktree" message has already been the subject of somewhat significant changes in 2c27002 ("worktree: improve message when creating a new worktree", 2018-04-24, Git v2.18.0-rc0 -- merge listed in batch #6).
Moreover, there is existing precedent, such as 68b939b ("clone: send diagnostic messages to stderr", 2013-09-18, Git v1.8.5-rc0 -- merge) which likewise relocated "chatty" messages from stdout to stderr for git-clone.


vah*_*eds 5

对于这个问题,worktree add确实需要一个--checkout开关来做到这一点:

$ git worktree add --checkout ../north north
$ git worktree add --checkout ../razavi razavi
Run Code Online (Sandbox Code Playgroud)

  • `--checkout` 是默认值:它仅存在以便您可以使用 `--no-checkout`。它成功的原因可能是你的工作树已经老化到 Git 运行 `git worktree prune` *自动* 并注意到你现有的 `north` 检出已经消失的地步。 (4认同)