Re: git checkout -B <branch> lets you checkout a branch that is already checked out in another worktree Inbox
- From
- Willem Verstraeten <willem.verstraeten@gmail.com>
- Date
- Nov 23, 2023, 12:12 UTC
- Message-ID
- <CAGX9RpHOOu71LJa_Z_29b6hwy7s_+oxGv0U1kdt+CJ_Ztg1iSw@mail.gmail.com>
- In-Reply-To
- <xmqqjzq9cl70.fsf@gitster.g>
Show 8 quoted lines
> > git checkout -f main origin/main #also reports a fatal error, as expected > > This is expected because origin/main is taken as pathspec, and it is > a request to checkout the paths that match the pathspec out of the > named tree-ish (i.e., "main"), even when these paths have local > changes, but you do not have paths that match "origin/main". The > failure is not because "main" is checked out elsewhere. >
My mistake: I meant to do `git branch -f main origin/main`, as documented for `git checkout -B main origin/main`
So, for completeness' sake, this is my revised reproduction scenario that actually demonstrates the problem I have:
~/temp> git clone https://github.com/servo/pathfinder.git primary
Cloning into 'primary'...
....~/temp> cd primary
~/temp/primary> git worktree add -b metal ../secondary origin/metal
Preparing worktree (new branch 'metal')
branch 'metal' set up to track 'origin/metal'.
HEAD is now at 1cdcc209 wip~/temp/primary> cd ..\secondary\
~/temp/secondary> git checkout main
fatal: 'main' is already used by worktree at ../primary' ~/temp/secondary> git branch -f main origin/main
fatal: cannot force update the branch 'main' used by worktree at
'../primary' ~/temp/secondary> git checkout -B main origin/main
Switched to and reset branch 'main'
branch 'main' set up to track 'origin/main'.
Your branch is up to date with 'origin/main'.I would expect that last `git checkout -B ...` to fail with a similar error as the `git branch -f ...` command right before that, since the documentation for `git checkout -B <branch> <start-point>` states that it is the atomic equivalent of `git branch -f <branch> <start-point> ; git checkout <branch>`
Show 8 quoted lines
> I guess we could change the behaviour so that > > git checkout -B <branch> [<start-point>] > > fails when <branch> is an existing branch that is in use in another > worktree, and allow "-f" to be used to override the safety, i.e., > > git checkout -f -B <branch> [<start-point>]
I would be very much in favor of that, indeed.
However, as you noted in your follow-up mail, the --ignore-other-worktrees option would be better suited than the -f flag.
> It turns out that for some reason "-f" is not how we decided to > override this one---there is "--ignore-other-worktrees" option.
This means it would look like this then, if you decide to tackle this?
~/temp/secondary> git checkout -B metal origin/metal
fatal: cannot force update the branch 'main' used by worktree at
'../primary' ~/temp/secondary> git checkout --ignore-other-worktrees -B metal
origin/metal
Switched to and reset branch 'metal'
branch 'metal' set up to track 'origin/metal'.
Your branch is up to date with 'origin/metal'.My thoughts as an experienced user, though not an experienced contributor, admittedly :)
Kind regards, Willem Verstraeten
On Thu, 23 Nov 2023 at 02:28, Junio C Hamano <gitster@pobox.com> wrote:
Show 62 quoted lines
> > Willem Verstraeten <willem.verstraeten@gmail.com> writes: > > > git checkout -b main #reports a fatal error, as expected > > This is expected because "main" already exists, not because "main" > is checked out elsewhere. > > > git checkout -f main origin/main #also reports a fatal error, as expected > > This is expected because origin/main is taken as pathspec, and it is > a request to checkout the paths that match the pathspec out of the > named tree-ish (i.e., "main"), even when these paths have local > changes, but you do not have paths that match "origin/main". The > failure is not because "main" is checked out elsewhere. > > A slight variant of the command > > git checkout -f -b main origin/main > > still fails for the same reason as the first of your examples above. > > It is a tangent, but I suspect this failure may be a bit unexpected. > In this example, "-f"orce could be overriding the usual failure from > "-b" to switch to a branch that already exists, but that is what > "-B" does, and "-f -b" does not work as a synonym for "-B". > > In any case, these example you marked "fail as expected" do fail as > expected, but they fail for reasons that have nothing to do with the > protection of branches that are used in other worktrees. > > > git checkout -B main origin/main # ----> this succeeds, which is > > unexpected <---- > > I agree this may be undesirable. > > But it makes sort of sense, because "-B" is a forced form of "-b" > (i.e., it tells git: even when "-b" would fail, take necessary > measures to make it work), and we can view that it is part of > "forcing" to override the protection over branches that are used > elsewhere. > > I guess we could change the behaviour so that > > git checkout -B <branch> [<start-point>] > > fails when <branch> is an existing branch that is in use in another > worktree, and allow "-f" to be used to override the safety, i.e., > > git checkout -f -B <branch> [<start-point>] > > would allow the <branch> to be repointed to <start-point> (or HEAD) > even when it is used elsewhere. > > Thoughts, whether they agree or disagree with what I just said, by > other experienced contributors are very much welcome, before I can > say "patches welcome" ;-). > > Willem, thanks for raising the issue. > > >