Git add a worktree from existing remote branch
Asked Answered
H

6

78

In my remote repository there are 3 branches (master and 2 long running branches):

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

At my office PC, I add 2 worktree for those north and razavi branches:

$ git worktree list
C:/Source/nis     a6fb6e1 [master]
C:/Source/north   ebc7670 [north]
C:/Source/razavi  eed08a2 [razavi]

Everything is OK so far, I decide to work on this project from my home as well, but in my home PC, when I try to add worktree for those two branches, it gives me an error:

$git worktree add -b north ../north north
fatal: A branch named 'north' already exists.

I remove the -b switch to not add a new branch, but it doesn't work too.

How can I add a worktree from existing branch that is not local but remote?

Hymnology answered 3/8, 2017 at 17:50 Comment(4)
The Error-Message indicates, that the branches already exist on your local system. If you want to switch to one of them you have to use checkout: git checkout north for example.Emendation
git checkout works fine. the question is how to add a worktree that track that existing branch?Hymnology
Note: with Git 2.18 (Q2 2018), git worktree add can now checkout an existing branch: see my answer below.Unlawful
git worktree add -b new_branch ./path_for_newbranch existing_branchStamen
C
97

TL;DR: you probably wanted git worktree add ../north north

First, a reminder (or information for others coming across this question): git worktree add wants to create a new work-tree and, at the same time, make sure that this new work-tree is using a different branch name from every other work-tree. This is because, while each added work-tree has its own index and HEAD, the HEAD files wind up sharing the underlying branch pointers in the shared repository. Having two different work-trees with independent index objects but the same underlying branch leads to some tricky problems for users to deal with. Rather than trying to figure out how to deal with these—by either educating programmers or providing tools to deal with the problems—git worktree simply forbids the situation entirely.

Hence, it's pretty typical to want to create a new branch name when creating a new work-tree. By definition, a new branch name is automatically different from every existing branch name:

$ git checkout -b newbranch
Switched to a new branch 'newbranch'
$ git checkout -b newbranch
fatal: A branch named 'newbranch' already exists.

This seems pretty natural: no one is ever surprised by this.

You're running git worktree add in a way that is just like git checkout -b, except that the checkout occurs in the new added work-tree. But you already have a branch named north.

If this existing north branch is not useful, you can delete it. Now you don't have a local branch named north and you can create a new one.

If this existing north branch is useful, don't delete it! If it's already checked out in some existing work-tree, move to that work-tree and work on it there. If it's not checked out in some existing work-tree, you can make a new work-tree that does have it checked out; you just need to avoid using the -b flag (and the corresponding branch name):

git worktree add ../north north

Note that when you're creating a new branch, you do not have to repeat yourself:

git worktree add -b newbranch ../path

will create a new work-tree in ../path, and use git checkout -b newbranch to populate it. You only need the branch name when:

  1. you're not using -b, and
  2. the path argument does not end in the name of the branch.

For instance, if you want to check out the existing branch zorg in a new work-tree in path ../zorg, you can just run:

git worktree add ../zorg

Here, since there is neither a -b zorg nor a final argument, Git figures out the branch name by using the last part of ../zorg, which is of course just zorg, so this tries to check out the existing branch zorg into the new work-tree.

Chromatolysis answered 3/8, 2017 at 18:17 Comment(15)
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'Hymnology
In that case, Git believes you already have a work-tree with this branch checked out. If that's wrong—if you had one but removed it—run git worktree prune first, so that Git can correct its list of existing extra work-trees.Chromatolysis
Either that or you have north checked out in your primary git directoryChiasma
@torek, I appreciate you answer this, but I just need to use --checkout switch with worktree add like in my answer.Hymnology
as mentioned above git worktree add -b newbranch ../path works just fineFrown
So typically a worktree is associated with a single branch, but often not. is that right?Haller
@Honey: each work-tree (the original, plus each added one) has some current commit. Each work-tree has its own private HEAD, which is how Git finds that current commit in that work-tree. The HEAD in each work-tree is either attached (to a branch name) or detached. The constraint Git places on attached HEADs is that no other work-tree's HEAD may also be attached to the same branch name.Chromatolysis
The reason for this constraint is simple but subtle: when you make a new commit, Git will write the new commit's hash ID into the branch name to which HEAD is attached. So suppose you have two work-trees, W1 and W2. Suppose further that each one has its HEAD attached to name B (for branch). This means both work-trees have the same current commit. Then you make a new commit in W1, which writes the new commit's hash ID into the name B. Since the names are shared, both work-trees now have a different current commit ... but the checkout in W2 is of the previous commit.Chromatolysis
In other words, the act of committing in W1, which updated the name B, broke the setup in W2. Git needs the name B to contain the new hash ID in W1, but needs the name B to contain the old hash ID in W2. This is not possible, so git worktree add forbids the situation from even coming up by forbidding both W1 and W2 to use B at the same time.Chromatolysis
Thanks. I've read your comments a few times. Just to avoid confusion on my side, your answer was yes or no? :)Haller
@Honey: Well, the problem is: (1) I don't know what you mean by "branch". (2) What's typical for user A could be atypical for user B. So I don't know whether the answer for you would be yes or no. :-) We can say that git worktree add itself takes a branch name, or the --detach option, and will create a new branch name or use an existing one to set up an attached HEAD. After that, it's up to the user.Chromatolysis
It all makes sense now. After changing directories into my treeA I just tried checking out branchB that was the head of treeB on treeA, but I got: fatal: 'branchB' is already checked out at '/path/to/MyProject/treeA'. So basically a worktree is just as you said, tied to either an attached or detached HEADHaller
Having that said I was able to have two of my worktrees pointing to the same commit, only because they were both on a detached HEAD. So just as you said. Yet I don't understand why there's no restriction on a detached head. Do you have that explained anywhere?Haller
@Honey: With a detached HEAD, HEAD itself just contains a raw hash ID. So any new commits you make write the new commit hash ID into HEAD, which doesn't affect any branch names. No shared resource gets messed-up, in other words.Chromatolysis
That makes a lot of sense. Cause I just landed here :) when i tried checking out an existing branch i.e. git wants me to commit myself to a branch not just a detached commit/headHaller
U
14

In addition of "guessing the remote branch", as I explain in my other answer, Git 2.18 (Q2 2018) will offer a new feature:
"git worktree add" learned to check out an existing branch.

See commit f60a7b7, commit 6427f87, commit 2c27002, commit d861d34 (24 Apr 2018) by Thomas Gummerer (tgummerer).
Helped-by: Eric Sunshine (sunshineco).
(Merged by Junio C Hamano -- gitster -- in commit 10174da, 23 May 2018)

worktree: teach "add" to check out existing branches

Currently 'git worktree add <path>' creates a new branch named after the basename of the path by default.
If a branch with that name already exists, the command refuses to do anything, unless the '--force' option is given.

However we can do a little better than that, and check the branch out if it is not checked out anywhere else.
This will help users who just want to check an existing branch out into a new worktree
, and save a few keystrokes.

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>

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

Or:

<path> is a missing but already registered worktree
use '<cmd> -f' to override, or 'unlock' and 'prune' or 'remove' to clear

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'

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'

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')

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.

Unlawful answered 24/5, 2018 at 20:46 Comment(2)
I'm having trouble understanding the reasoning behind the two separate answers you've posted. Are you hoping to clarify or update the accepted answer? Why are two responses necessary for that?Stamen
@Stamen This is about separating explicit and implicit ("guessRemote") ways to add a worktree, as asked in the original question ("how to add a worktree from existing branch that is not local but remote?"). By experience, if I put them together, the all answer gets downvoted, because way too long.Unlawful
H
8

For this problem, worktree add does need a --checkout switch to do so:

$ git worktree add --checkout ../north north
$ git worktree add --checkout ../razavi razavi
Hymnology answered 15/8, 2017 at 18:11 Comment(2)
--checkout is the default: it exists only so that you can use --no-checkout. Probably the reason it succeeded is that your worktrees had aged to the point that Git ran git worktree prune automatically and noticed that your existing checkout of north had gone away.Chromatolysis
@Chromatolysis I agree with you!Hymnology
U
3

In addition of git worktree add --checkout, Git 2.16 (Q1 2018) will propose another alternative:

The way "git worktree add" determines what branch to create from where and checkout in the new worktree has been updated a bit.

See commit e92445a, commit 71d6682 (29 Nov 2017), and commit 4e85333, commit e284e89, commit c4738ae, commit 7c85a87 (26 Nov 2017) by Thomas Gummerer (tgummerer).
(Merged by Junio C Hamano -- gitster -- in commit 66d3f19, 19 Dec 2017)

add worktree.guessRemote config option

Some users might want to have the --guess-remote option introduced in the previous commit on by default, so they don't have to type it out every time they create a new worktree.

Add a config option worktree.guessRemote that allows users to configure the default behaviour for themselves.

The documentation for git config now reads:

worktree.guessRemote::

With add, if no branch argument, and neither of -b nor -B nor --detach are given, the command defaults to creating a new branch from HEAD.
If worktree.guessRemote is set to true, worktree add tries to find a remote-tracking branch whose name uniquely matches the new branch name.

  • If such a branch exists, it is checked out and set as "upstream" for the new branch.
  • If no such match can be found, it falls back to creating a new branch from the current HEAD.

Actually, Git 2.21 (Q1 2019) clarifies the documentation for this option, which jumped right in with "With add", without explaining that add is a sub-command of "git worktree".

See commit b4583d5 (23 Dec 2018) by Eric Sunshine (sunshineco).
(Merged by Eric Sunshine -- sunshineco -- in commit b4583d5, 28 Dec 2018)

The documentation now reads:

worktree.guessRemote:

If no branch is specified and neither -b nor -B nor --detach is used, then git worktree add defaults to creating a new branch from HEAD.

Unlawful answered 20/12, 2017 at 22:25 Comment(0)
C
3

The command suggested by chb above:

git worktree add -b <new_branch> <path_worktree> <remote>/<existing_branch>

add a worktree from the remote existing branch and tracks it in the local branch <new_branch>. It produces the same result of git worktree add --track -b <branch> <path> <remote>/<branch> for me (git 2.30.2).

While the command git worktree add <path> <remote>/<branch> suggested in torek answer does create a worktree from a remote branch, but without tracking it on any (local) branch. You can always create a local branch afterwards.

Cupule answered 16/8, 2023 at 8:21 Comment(1)
Yes, checkout an existing branch is what I documented below.Unlawful
G
0

For anyone simply wanting to create a worktree from an existing branch.

git worktree add ../PATH-TO-NEW-WORKTREE NAME-OF-REMOTE-BRANCH

Will create a worktree without the need to checkout the target branch.

Handy if you want to amend a commit in another branch without having to stash or commit before.

Gardener answered 17/11, 2023 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.