Thread (1 message) 1 message, 1 author, 2025-09-16

Re: [PATCH 1/3] checkout: provide hint when failing due to another worktree

From: Junio C Hamano <hidden>
Date: 2025-09-16 05:32:17

Gabriel Scherer [off-list ref] writes:
On the other hand for --ignore-other-worktrees there is no
user-friendly documentation of these questions currently (I looked at
the 'worktree' documentation, in particular for the --force option,
and at the --ignore-other-worktrees documentation for 'checkout').
Oh, that's bad and we should improve them, regardless of what we say
in the hints.
restriction, what happens if we ignore this restriction, and what is
the recommended way to respect it.
Sounds good.
quoted
  - 'foo' is already in use and in which worktree.  Your message
    "fatal:" is very clear and is good.
  - if you checkout 'foo' here and start growing or otherwise
    updating the history of 'foo' in this worktree, the index and the
    working tree files of other worktree(s) will go out of sync with
    the tip of 'foo'.  if they 'git commit' from that state, for
    example, it is very likely that they will record a change that
    reverts your changes from the history of 'foo', and you do not
    want that.
(This gets me to wonder if a desirable behavior could be to 'detach'
the other worktrees that had the same branch checked out, instead of
failing on checkout. Users starting to use the other worktree again
would possibly notice more quickly that something is amiss.)
I generally advise against pulling the rug under somebody else's
feet.  You do not know what that other worktree is used for, or if
somebody is using it right now making changes and whatnot.  What
happens in the worktree that the end-user has just issued the
command you are executing is much more controllable.
For me this situation is not a big deal: if they commit the removal of
'foo', presumably they will notice that the diff/changes in their
commit is not what they expect, and they can come back to the previous
state.

I agree that this is surprising and I understand why the project
decided to discourage this by default ('fatal error' is plenty
discouraging), but there is no data loss or anything of the sort, only
recoverable surprises.
The question is how would they, the person who worked on the other
working tree that first checked out 'foo' and perhaps worked for
some time with local modifications, and then left the worktree so
long ago that they forgot that they have a checkout of it (and that
is why they just got told by "git checkout" that there _is_ another
worktree that checks out 'foo' already exists), _find_ where the
previous state is in the first place, once they go back to the other
worktree.  You may be nice and have advanced the branch by only one
or two commits, and they may be able to find where they were by
going back a few entries in "git log" output.  But you may rebase
the branch and the place where they started from in the other
worktree may no longer exist.  Then what?  It does not sounds like a
recoverable surprise to me at all.
quoted
  - if you want to grow history of 'foo' in potentially different
    direction from what the other worktree with 'foo' is working on,
    you are better off creating a separte branch 'foo2', with
    anticipation that you'll eventually merge them together.
Use-case examples:

1. my colleague has a long-lived feature branch called 'super-feature'
2. last year I did a lot of review work on their branch in a separate
worktree which is still somewhere on my filesystem, but which I am not
actively working on anymore (and maybe never will)
3. I am in the middle of a bugfix session in another worktree, and
suddenly I want to check if the bug also occurs in 'super-feature'; I
stash my current stuff, checkout 'super-feature', and run 'git pull'
to update it to match my colleague's remote to get the most recent
version and test it against this bug.

In this scenario, I don't want my current work in (3) to be
interrupted by the fact that an old worktree (2) exists that also
tracks super-feature, and in fact I do want to update my local
'super-feature' branch to the most recent version.
Maybe later on I will come back to my old super-feature worktree (but
maybe in another year), and I will start with a 'git pull' or some
other command, and I will quickly realize that its index is out of
date and fix it.
If #3 involved only "checkout" of super-feature to build and test,
then detached HEAD is the perfect tool that was designed to be used
in such a situation.  But if the goal is you want to have _his_ latest
super-feature expanded in your filesystem so that you can build and
debug, you do not want to checkout super-feature and pull, which WILL
move your super-feature branch and make #1 worktree useless.  They
may have made quite a lot of changes, and your previous state, the
state you were reviewing (and perhaps you had a few of your own
fixup patches there) may not even be reachable from their updated
tip of the super-feature branch.

If I were in that situation in step #3, I'll probably do

 $ git stash save -m 'in the middle of a bugfix session'
 $ git fetch his super-feature
 $ git checkout --detach his/super-feature
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help