On Tue, May 04 2021, Elijah Newren wrote: > On Tue, May 4, 2021 at 3:36 AM Gábor Farkas <gabor.farkas@xxxxxxxxx> 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 doesnotexist The 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 old And: # 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.