Subject: Re: [PATCH v6 6.5/6] fixup! worktree: teach "add" to check out existing branches

From: Thomas Gummerer <[email-masked]>
Date: Mon, 9 Apr 2018 20:44:05 +0100

On 04/08, Eric Sunshine wrote:
> On Sun, Apr 1, 2018 at 9:11 AM, Thomas Gummerer <[email-masked]> wrote:
> > So while playing with it a bit more I found one case where the new UI
> > is not ideal and a bit confusing.  Namely when the new check out dwim
> > kicks in, but there is already a file/directory at the path we're
> > giving to 'git worktree add'.
> >
> > In that case something like the following would be printed:
> >
> >     $ g worktree add ../next
> >     Checking out branch 'next'
> >     fatal: '../next' already exists
> >
> > Instead I think we'd just want the error without the "Checking out
> > branch" message, which is what this fixup here does.
> 
> Doesn't the same UI "problem" exist when it creates a new branch?
> 
>     $ git worktree add ../dwim
>     Creating branch 'dwim'
>     fatal: '../dwim' already exists
> 
> As you mention below, we don't (yet) clean up the newly-created branch
> upon failure, so we can't suppress the "Creating branch" message as
> you suppress the "Checking out branch" message above (since the user
> needs to know that the new branch exists).
> 
> This is making me wonder if "Checking out branch" is perhaps the wrong
> terminology. What if it said something like this instead:
> 
>     $ git worktree add ../next
>     Preparing worktree (branch 'next' <= 'origin/next')
>     fatal: '../next' already exists
> 
>     $ git worktree add ../gobble
>     Preparing worktree (new branch 'gobble')
>     fatal: '../gobble' already exists
> 
> This way, we don't need the special case added by this "fixup!" patch.
> (I'm not wedded to the "Preparing" message but just used it as an
> example; better suggestions welcome.)

Yeah, I think this looks like another improvement of what I currently
have.  I'm not sure about the "(branch 'next' <= 'origin/next')"
message though, as it doesn't cover all the ways the branch could be
set up for tracking the remote branch, e.g. tracking by rebasing, when
'branch.autosetuprebase' is set up.

But how about just "Preparing worktree (new branch 'next')", and then
keeping the message from 'git branch' about setting up the remote
tracking branch?

> > One thing that gets a bit strange is that the "Checking out branch"
> > message and the "Creating branch" messages are printed from different
> > places.  But without doing quite some refactoring I don't think
> > there's a good way to do that, and I think having the UI do the right
> > thing is more important.
> 
> The implementation is getting rather ugly, though, especially with
> these messages being printed by different bits of code like this.
> worktree.c:add_worktree() was supposed to be the low-level worker; it
> wasn't intended for it to take on UI duties like this "fixup!" makes
> it do. UI should be handled by worktree.c:add().
> 
> Taking the abonve "Preparing..." idea into consideration, then it
> should be possible to sidestep this implementation ugliness, I would
> think.
> 
> > One thing I also noticed is that if a branch is created by 'git
> > worktree add', but we fail, we never clean up that branch again, which
> > I'm not sure is ideal.  As a pre-existing problem I'd like to keep
> > fixing that out of the scope of this series though (at least after
> > this series the user would get some output showing that this happened,
> > even when the branch is not set up to track a remote), so I'd like to
> > keep fixing that out of the scope of this series.
> 
> Nice idea, but outside the scope of this series, as you mention.
> 
> > diff --git a/builtin/worktree.c b/builtin/worktree.c
> > @@ -27,6 +27,7 @@ struct add_opts {
> >         int keep_locked;
> > +       int checkout_existing_branch;
> >  };
> > @@ -316,6 +317,8 @@ static int add_worktree(const char *path, const char *refname,
> > +       if (opts->checkout_existing_branch)
> > +                 fprintf_ln(stderr, _("Checking out branch '%s'"), refname);
> >         if (opts->checkout) {
> 
> I'd have expected to see the "if (opts->checkout_existing_branch)
> fprintf_ln(...)" inside the following "if (opts->checkout)"
> conditional, though, as noted above, I'm not entirely happy about
> worktree.c:add_worktree() taking on UI duties.

Fair enough.  I didn't quite like the code either.  I think what you
have above would be much nicer, and I'll implement that in the
re-roll.

> >                 cp.argv = NULL;
> >                 argv_array_clear(&cp.args);