Re: git switch/restore, still experimental?
- From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- Date
- May 5, 2021, 11:09 UTC
- Message-ID
- <877dkdwgfe.fsf@evledraar.gmail.com>
- In-Reply-To
- <CABPp-BHBcjSQbkotrzwDtVRSC-qqjEyP4m=biY-0+=Jdg9ETQw@mail.gmail.com>
On Tue, May 04 2021, Elijah Newren wrote:
Show 26 quoted lines
> On Tue, May 4, 2021 at 3:36 AM Gábor Farkas <gabor.farkas@gmail.com> wrote: >> >> hi, >> >> the "git switch" and "git restore" commands were released two years >> ago, but the manpage still says "THIS COMMAND IS EXPERIMENTAL. THE >> BEHAVIOR MAY CHANGE.". >> >> i'd love to use them, but this warning gives me pause, perhaps i >> should wait until it stops being experimental, i worry that it might >> change in behavior unexpectedly and cause problems for me. >> >> considering that they were released two years ago, could the >> experimental-warning be removed now? >> >> thanks, >> gabor > > This probably makes sense. The author of switch and restore isn't > involved in the git project anymore. He decided to work on other > things, which was and is a big loss for us. I think others (myself > included) didn't know all the things that might have been in Duy's > head that he wanted to verify were working well before marking this as > good, but these two commands have generally been very well received > and it has been a few years. Personally, I'm not aware of anything > that we'd need or want to change with these commands.
I am.
I think it's quite confusing that "git switch" doesn't switch to a new "doesnotexist" branch on something like:
git switch doesnotexist
But requires:
git switch -c doesnotexist
I mean, I see why. You don't want a typo of "master" as "maaster" to create a new "maaster" branch, so really that's out. But it really should be:
# -n or -N for --new / --new --force (the latter just in case of a
# race, and just for consistency)
git switch -n doesnotexistThe design choice of squatting on "-c" for "create" as opposed to "copy" as implemented in 52d59cc6452 (branch: add a --copy (-c) option to go with --move (-m), 2017-06-18) has the knock-on effect that we can't mirror the "git branch" UI. I.e. to make "switch" be "branch with checkout" for these common cases.
I.e.:
# copies a branch and config from old->new (or -C for --force)
git branch -c old new
# just creates a "new" starting at "old", but no copying!
git switch -c new oldAnd:
# Moves a branch (or -M for --force) git branch -m old new
That last one we can't have either because "switch" squats on "-m" for "--merge", which I daresay is a much more obscure use-case not deserving of a short option than "rename and switch to".
In summary, I think it should be changed to act like this:
|---------------------------+------------------------+---------------------------|
| What | Now | New |
|---------------------------+------------------------+---------------------------|
| Switch | git switch existing | git switch existing |
| Error | git switch nonexisting | <no change (errors)> |
| Switch with --merge | git switch -m branch | git switch --merge branch |
| Create | git switch -c new | git switch -n new |
| Create from existing | N/A | git switch -c new [<old>] |
| Move & switch to existing | N/A | git switch -m new [<old>] |
|---------------------------+------------------------+---------------------------|One thing that sucks about my proposal is that it would be squatting on "-n" for "new" as opposed to "--dry-run".
It would be nice if switch/checkout learned a --dry-run mode, I don't like e.g. "fetch" having a "-n" that isn't "--dry-run", but can't think of a better option in the switch case.
In its current state I find "git switch" to be unusable. That sounds like dramatic hyperbole, but I'm serious.
As much as I applaud the effort to move git's UI forward in this particular case it's doomed to be only skin-deep because of that unfortunate initial design choice of sort-of acting like "git branch with checkout", but squatting on "-c/-C/-m".
I.e. to me the ideal end state would be to deprecate (or at least warn/discourage) the "git branch -m" case where it does its own checkout (but for nothing else), and to make "git switch" a "branch with checkout" with the same -c/-C/-m/-M semantics, just also with a -n/-N for "create first".
So at the end of the day you still have to use "git branch" for these common (at least for me) operations of copy/move, *and* maintain a mental model that "-c" means "xyz" here, but "abc" there.
The "switch" command also solves the very real problem (and I believe this was the main motivation) of not knowing beforehand if "checkout" will interpret your "foo" as a file, a branch or whatever. I find it easier to solve that (I'm aware that it's not a 100% solution) by consistently using "--" to escape path names, rather than needing to mentally model the difference in "-c/-C/-m" behavior.