diff mbox series

PATCH: improve git switch documentation

Message ID c593a699-eaf2-c7ab-b522-bfd224fce829@mfriebe.de (mailing list archive)
State New, archived
Headers show
Series PATCH: improve git switch documentation | expand

Commit Message

Martin June 29, 2021, 3:28 p.m. UTC
Below is a patch, that I believe would improve the documentation of git 
switch.

The exact new wording is of course open for debate.

Reasoning for the change.

The current doc does not explain why the option is a "forceful" option.
Nor does explain the consequences.

Instead it leaves it to the user to lookup the alternate command, and 
find the meaning of
     git branch -f newbranch

Only if the user does that successfully, the user may learn about the 
full consequences of their actions.

I believe this info should be part of the "git switch" doc, itself. 
(Especially due to the severity that the action may have).



 From 46580d07f95a18c94925afd141ba55e52a82c8e1 Mon Sep 17 00:00:00 2001
From: Martin <User4martin@users.noreply.github.com>
Date: Tue, 29 Jun 2021 17:22:25 +0200
Subject: [PATCH] Update git-switch.txt

---
  Documentation/git-switch.txt | 8 ++++++--
  1 file changed, 6 insertions(+), 2 deletions(-)

Comments

Junio C Hamano June 29, 2021, 4:35 p.m. UTC | #1
Martin <git@mfriebe.de> writes:

> Below is a patch, that I believe would improve the documentation of
> git switch.
>
> The exact new wording is of course open for debate.
>
> Reasoning for the change.
>
> The current doc does not explain why the option is a "forceful" option.
> Nor does explain the consequences.
>
> Instead it leaves it to the user to lookup the alternate command, and
> find the meaning of
>     git branch -f newbranch
>
> Only if the user does that successfully, the user may learn about the
> full consequences of their actions.
>
> I believe this info should be part of the "git switch" doc,
> itself. (Especially due to the severity that the action may have).

Please place all of the above below the three-dash line.

> From 46580d07f95a18c94925afd141ba55e52a82c8e1 Mon Sep 17 00:00:00 2001

Lose this line.

> From: Martin <User4martin@users.noreply.github.com>

Get rid of this line, too, as you have your own e-mail address on
the real "From" line of the e-mail.

> Date: Tue, 29 Jun 2021 17:22:25 +0200

This too.

> Subject: [PATCH] Update git-switch.txt

And this one, too.

>

And then justify and describe the change here (see
Documentation/SubmittingPatches::describe-changes)

Immediately before the three-dash line below, have your sign-off
(see Documentation/SubmittingPatches::sign-off).

> ---
>  Documentation/git-switch.txt | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/git-switch.txt b/Documentation/git-switch.txt
> index 5c438cd5058758..80acafad1f4a46 100644
> --- a/Documentation/git-switch.txt
> +++ b/Documentation/git-switch.txt
> @@ -70,8 +70,12 @@ $ git switch <new-branch>
>  -C <new-branch>::
>  --force-create <new-branch>::
>  	Similar to `--create` except that if `<new-branch>` already
> -	exists, it will be reset to `<start-point>`. This is a
> -	convenient shortcut for:
> +	exists, it will be reset to `<start-point>`.
> +	This forces the branch to the new location.

I would have written "This forces the branch to point at a different
commit", as we do not have to use a fuzzy word "location" in this
context (is it a location in the directory structure in the working
tree?  is it a location in the history dag?  is it a location in
some other dimension?).

Up to this point, it makes sense.

> + It also forces
> +	any commit hold by the branch to be dropped, unless the
> +	commit is also part of any other branch too. You may
> +	therefore loose some of your data.

Aside from typo on "lose" (not "loose") and "held" (not "hold"),
this paragraph does not seem to add much value, at least to me, and
I suspect that it makes things even more confusing to new readers.

 * Repointing the branch tip to a different commit is not limited to
   "git switch -C".  Any commands that allow you to move the branch
   tip, like "git branch -f", "git checkout -B", "git push --force",
   "git reset", share the same property and singling "switch -C" out
   gives a false impression that all other commands are OK.

 * "to be dropped" is unnecessarily alarming (and not even correct).
   "gc" will not reclaim while the reflog entries hold onto them.

   "Some commits that used to be reachable from the original branch
   tip may become unreachable." would not be an incorrect
   description per-se (and would be a vast improvement over what is
   in the posted patch), but it is dubious to stress the obvious,
   especially given that the whole point of "branch -f" is to make
   wrong commits disappear by pointing at corrected commits with the
   branch tip.

Because "switch -c <new-branch>", unlike "switch <existing-branch>"
would not have to touch the working tree at all, the only reason why
the user has to force the operation by using "-C" is to override the
safety offered by "-c" that protects existing branches from accidental
overwriting.  Perhaps adding some description on "why" -c prevents
an existing branch from being overwritten would help reduce the
confusion better than an additional warning on "-C"?

Thanks.
Martin June 29, 2021, 7:04 p.m. UTC | #2
I'll redo the patch, when we got a better text....

On 29/06/2021 18:35, Junio C Hamano wrote:
> Martin<git@mfriebe.de>  writes:
>
>>   	Similar to `--create` except that if `<new-branch>` already
>> -	exists, it will be reset to `<start-point>`. This is a
>> -	convenient shortcut for:
>> +	exists, it will be reset to `<start-point>`.
>> +	This forces the branch to the new location.
> I would have written "This forces the branch to point at a different
> commit", as we do not have to use a fuzzy word "location" in this
> context (is it a location in the directory structure in the working
> tree?  is it a location in the history dag?  is it a location in
> some other dimension?).
Ok.

> Up to this point, it makes sense.
>
>> + It also forces
>> +	any commit hold by the branch to be dropped, unless the
>> +	commit is also part of any other branch too. You may
>> +	therefore loose some of your data.
> Aside from typo on "lose" (not "loose") and "held" (not "hold"),
> this paragraph does not seem to add much value, at least to me, and
> I suspect that it makes things even more confusing to new readers.
>
>   * Repointing the branch tip to a different commit is not limited to
>     "git switch -C".  Any commands that allow you to move the branch
>     tip, like "git branch -f", "git checkout -B", "git push --force",
>     "git reset", share the same property and singling "switch -C" out
>     gives a false impression that all other commands are OK.
Well, yes. There may be more doc pages that could be updated. But that 
should not stop us
from starting at some point.
I chose "git switch", because as I understand it, it was made in an 
effort to make git
easier to use (by distinguishing between the clumped together commands 
that were
all done with "git checkout")
In that sense, I see "git switch" as a particular important improvement 
for people new
to git. Hence I felt that its documentation needed the extra bit of 
attention.

>   * "to be dropped" is unnecessarily alarming (and not even correct).
>     "gc" will not reclaim while the reflog entries hold onto them.
>
>     "Some commits that used to be reachable from the original branch
>     tip may become unreachable." would not be an incorrect
>     description per-se (and would be a vast improvement over what is
>     in the posted patch), but it is dubious to stress the obvious,
>     especially given that the whole point of "branch -f" is to make
>     wrong commits disappear by pointing at corrected commits with the
>     branch tip.
My text may indeed have lacked clarity. I was trying to emphasize to 
hard, that this
command's "force" enables 2 actions that may both not be wanted. Usually 
if one applies
"force" to a command only one such action is expected, or at least I 
would only expect the one.
The actions being, giving up the link to the commit that is the tip of 
the branch; and
making commits unreachable.  (for an expert in git tightly linked 
together, but not for everyone)

Because you already need force, just to give up link to the tip, it is 
not clear that there
might be additional unwanted actions that are enabled with the same "force".
(And the "unreachable commits" do not always happen, which makes it even
more dangerous, as a user may misjudge if it applies to his current case 
/ I started
another mail on that too).

In general the direction of your proposed text is ok for me. But I 
highly doubt that a user
who is new to git, will understand "reachable" without further context.
Maybe
    " As a result some commits may be removed from the reachable part
      of the repository and will be scheduled to be purged (see reflog 
documentation)"

or
    " As a result some commits may no longer be in a reachable part
      of the repository and will be scheduled to be purged (see reflog 
documentation)"

It is the same "reachable" that you used (the reflog can be reached, but 
one usually does not
want the reflog to be the only place from where to access data still needed)
. It adds the word "removed" which most people (regardless of their git 
skill,
or English skills) will recognize.

The intend is, that a new user should clearly take the message, those 
commits will
"go away" (even if they "only" go to the reflog)

> Because "switch -c <new-branch>", unlike "switch <existing-branch>"
> would not have to touch the working tree at all, the only reason why
> the user has to force the operation by using "-C" is to override the
> safety offered by "-c" that protects existing branches from accidental
> overwriting.  Perhaps adding some description on "why" -c prevents
> an existing branch from being overwritten would help reduce the
> confusion better than an additional warning on "-C"?
>
Well, I am not convinced. The "danger" lies in the "-C" (which is why it 
is a "force" command).
So it should be explained there.

It could be explained as "Unlike -c this does not protect your existing 
branch".
But the entire point is, that the user must be aware what happens when a 
branch is
removed (before it is recreated).

However the current documentation only mentions "if |<new-branch>| 
already exists, it will be reset to ".
There is no explanation what "reset" means.
The doc does not even mention, the branch is ..."re-created" or "removed 
and re-created".
Nor does it mention that the newly (re-)created  branch is created 
without any of the commits that it contained.

All of this, is very obvious to you and me. But it's not that obvious 
for new users (who relay on the
docs more than anyone else).

Based on that, another approach to create clarity might be

     Force creating a branch, means that an existing branch of the same 
name is removed.
    And that a new branch is created at the specified <start point>. The 
new branch will not
    necessarily have all the commits of that the existing branch used to 
have.
    It therefore also means that commits from the old existing branch 
may be no longer reachable.

Here I think it can be left at "no longer reachable" as it already has 
been indicated, that the commits may no longer be on that branch.
The "also means" underlines that this is a second potentially unwanted 
effect of this command.
Junio C Hamano June 29, 2021, 10:39 p.m. UTC | #3
Martin <git@mfriebe.de> writes:

> My text may indeed have lacked clarity. I was trying to emphasize to
> hard, that this
> command's "force" enables 2 actions that may both not be
> wanted. Usually if one applies
> "force" to a command only one such action is expected, or at least I
> would only expect the one.

Oh, I do agree wholeheartedly if two things are forced at the same
time, things can become confusing.

But the thing is, there are no such "two things are forced at once"
in this case.  That is why I emphasized, in my response to you, that
"switch -C <newbranch>" does not touch working tree, so "ok, the
switch stops because it requires some working tree files with
changes clobbered, and I can force it to make it happen" is not
involved.  If it were, then it becomes fuzzy if --force is allowing
an existing branch getting overwritten, or allowing a modification
in a working tree file getting discarded, or both.

The one and only thing that is forced is to repoint the tip of an
existing branch.

> The actions being, giving up the link to the commit that is the tip of
> the branch; and
> making commits unreachable.  (for an expert in git tightly linked
> together, but not for everyone)

Sorry, I do not quite see how the removing the reference to a commit
(i.e. the commit C that used to be pointed at by the branch would no
longer be pointed at by that branch---that is by definition what
moving the branch to point at a different commit means) and the
commit becoming not reachable from the reference (i.e. such a commit
C may not be reachable from the branch---unless the new commit it
points at happens to be a descendant of C) are not one and the same
thing.  I do not think there is distinction between expert vs
everyone else involved here at all.

Can you give an example where one of the two holds while the other
one does not?

Thanks.
Martin June 30, 2021, 8:50 a.m. UTC | #4
On 30/06/2021 00:39, Junio C Hamano wrote:
> Martin <git@mfriebe.de> writes:
>
>> My text may indeed have lacked clarity. I was trying to emphasize to
>> hard, that this
>> command's "force" enables 2 actions that may both not be
>> wanted. Usually if one applies
>> "force" to a command only one such action is expected, or at least I
>> would only expect the one.
> Oh, I do agree wholeheartedly if two things are forced at the same
> time, things can become confusing.
>
> But the thing is, there are no such "two things are forced at once"
> in this case.  That is why I emphasized, in my response to you, that
> "switch -C <newbranch>" does not touch working tree, so "ok, the
> switch stops because it requires some working tree files with
> changes clobbered, and I can force it to make it happen" is not
> involved.  If it were, then it becomes fuzzy if --force is allowing
> an existing branch getting overwritten, or allowing a modification
> in a working tree file getting discarded, or both.
Well, yes and no. IMHO.

 From what I have seen, there are main 2 cases people use -C.

1) By accident, meaning to do something else. Most often meaning to do a 
rebase.
I.e. some one who is new, desperately to fix "branch has diverged".
For this, those people need to be made aware that -C does not move the 
commits.

2) Intentional, when the branch to be re-created points to a commit, 
which is hold
  by further branches. So no commit becomes unreachable.
In that case it is not a documentation issue. It is a, how can I enable 
the re-create,
but have git warn me, if I somehow misjudged the situation and on other 
branch
has the commit. That is, when I see this as 2 individually actions, out 
of which I want
to allow only one. Anyway that is not documentation, and I did sent 
another mail.

And yes, for the documentation, it *should* be clear that, removing a 
branch, removes the
commits on it.
But then it must be said, that the branch is first removed. That is not 
currently the case.
I proposed an alternate text to that nature in my last mail.

For the rest, it is a matter of opinion.
When I think a new user may read this, I believe such consequential 
implications should
be mention rather explicit.
But, if your view (the view of the git team is) a new user should have 
read up far enough
to be fully aware of those consequence, then so be it.

As per my previous mail, then maybe
       Force creating a branch, means that an existing branch of the 
same name is removed.
      A new branch is created at the specified <start point>. The 
new branch will not
      necessarily have all the commits that the existing branch used to 
have.

But without
      It therefore also means that commits from the old existing branch 
may be no longer reachable.

>> The actions being, giving up the link to the commit that is the tip of
>> the branch; and
>> making commits unreachable.  (for an expert in git tightly linked
>> together, but not for everyone)
> Sorry, I do not quite see how the removing the reference to a commit
> (i.e. the commit C that used to be pointed at by the branch would no
> longer be pointed at by that branch---that is by definition what
> moving the branch to point at a different commit means) and the
> commit becoming not reachable from the reference (i.e. such a commit
> C may not be reachable from the branch---unless the new commit it
> points at happens to be a descendant of C) are not one and the same
> thing.  I do not think there is distinction between expert vs
> everyone else involved here at all.
>
> Can you give an example where one of the two holds while the other
> one does not?
>
Well, if one creates a new feature branch, and instead of forking of 
master, one forks of some
random other branch. Then one can immediately re-create it at the 
original intended
branch point. No commits on the branch, none lost.
But teach that to a newbie, and they may have committed to the branch, 
before they
realize they forked at the wrong point. If the then do -C those commit 
will be gone. (well, yes the reflog).

Personally (that may not be a common pattern), I have used two branches 
for one feature
branch. One that holds the tip, and represents my local work.
One that I move forward and backward on the branch, to run tests, and 
decide what
I already want to push. Forward could be done by ff-merge, but backward 
not (it's reset, or switch -C).

---------
About your comment on changes in the worktree.
In none of my examples do I have any changes in my worktree.

I know that when I just try to switch a branch, git switch will refuse 
to overwrite my changes.
The doc for the -C section does not say if it will.
That is something I actually would still need to check, and if -C in 
addition to forcing the branch,
and consequently but only in some cases "making commits unreachable", 
does also
overwrite working dir changes that would be yet one more "forced" action.
That again not everyone may automatically be aware off.
Junio C Hamano June 30, 2021, 10:59 p.m. UTC | #5
Martin <git@mfriebe.de> writes:

> And yes, for the documentation, it *should* be clear that, removing a
> branch, removes the
> commits on it.
> But then it must be said, that the branch is first removed. That is
> not currently the case.

Sorry, but I still do not see how it makes any difference if the
branch is first removed and then made to point at somewhere else, or
the branch gets just moved without any explicit or impolicit
removal.  A branch cannot point at two different commits at the same
time, so the end result is that the commit at the old tip is no
longer pointed at by the branch after the update.  In other words,

	----o---o---X---Y---Z

if it were possible to move the tip of a branch, that used to point
at commit Z, so that it points at commit X in the above picture,
without making it *not* to point at Z, then I would understand your
explanation, but I do not see how it would be possible.
Matt Rogers July 1, 2021, 12:06 a.m. UTC | #6
On Wed, Jun 30, 2021 at 4:50 AM Martin <git@mfriebe.de> wrote:
>
> On 30/06/2021 00:39, Junio C Hamano wrote:
> > Martin <git@mfriebe.de> writes:
> >
> >> My text may indeed have lacked clarity. I was trying to emphasize to
> >> hard, that this
> >> command's "force" enables 2 actions that may both not be
> >> wanted. Usually if one applies
> >> "force" to a command only one such action is expected, or at least I
> >> would only expect the one.
> > Oh, I do agree wholeheartedly if two things are forced at the same
> > time, things can become confusing.
> >
> > But the thing is, there are no such "two things are forced at once"
> > in this case.  That is why I emphasized, in my response to you, that
> > "switch -C <newbranch>" does not touch working tree, so "ok, the
> > switch stops because it requires some working tree files with
> > changes clobbered, and I can force it to make it happen" is not
> > involved.  If it were, then it becomes fuzzy if --force is allowing
> > an existing branch getting overwritten, or allowing a modification
> > in a working tree file getting discarded, or both.
> Well, yes and no. IMHO.
>
>  From what I have seen, there are main 2 cases people use -C.
>
> 1) By accident, meaning to do something else. Most often meaning to do a
> rebase.
> I.e. some one who is new, desperately to fix "branch has diverged".
> For this, those people need to be made aware that -C does not move the
> commits.
>
> 2) Intentional, when the branch to be re-created points to a commit,
> which is hold
>   by further branches. So no commit becomes unreachable.
> In that case it is not a documentation issue. It is a, how can I enable
> the re-create,
> but have git warn me, if I somehow misjudged the situation and on other
> branch
> has the commit. That is, when I see this as 2 individually actions, out
> of which I want
> to allow only one. Anyway that is not documentation, and I did sent
> another mail.
>

I just want to point out that my usual use-case for using -C (or checkout -f,
but the usage is similar enough for this discussion) is when I want to create
a temporary branch with a generic name (e.g. tmp) and I haven't cleaned
out my unused branches in a while.  If I find myself having branched off the
wrong commit and wanting to move work I already committed, the user should
be looking to use either rebase or merge for that.

I would also consider that using a command literally called "switch
--force-create"
does not seem like the obvious first choice for "My history is
different than that
history".



> And yes, for the documentation, it *should* be clear that, removing a
> branch, removes the
> commits on it.
> But then it must be said, that the branch is first removed. That is not
> currently the case.
> I proposed an alternate text to that nature in my last mail.
>
> For the rest, it is a matter of opinion.
> When I think a new user may read this, I believe such consequential
> implications should
> be mention rather explicit.
> But, if your view (the view of the git team is) a new user should have
> read up far enough
> to be fully aware of those consequence, then so be it.
>
> As per my previous mail, then maybe
>        Force creating a branch, means that an existing branch of the
> same name is removed.
>       A new branch is created at the specified <start point>. The
> new branch will not
>       necessarily have all the commits that the existing branch used to
> have.
>

I think the current documentations usage of "reset" in

    Similar to --create except that if <new-branch> already exists, it
will be reset to <start-point>.

Is pretty clear about what happens, although it does rely on users
being familiar
with the semantics of "resetting" a la git reset.  I think rephrasing
it in terms of
branch removal/creation actually obfuscates the matter.


> Well, if one creates a new feature branch, and instead of forking of
> master, one forks of some
> random other branch. Then one can immediately re-create it at the
> original intended
> branch point. No commits on the branch, none lost.
> But teach that to a newbie, and they may have committed to the branch,
> before they
> realize they forked at the wrong point. If the then do -C those commit
> will be gone. (well, yes the reflog).
>

I don't think that this is a great usage of switch -C.  generally I teach people
to look at the state of their repository via `git log --graph
--oneline --all` and then
decide whether they need to rebase their work or if they can just reset onto the
branch they want to.
Martin July 1, 2021, 10:06 a.m. UTC | #7
On 01/07/2021 00:59, Junio C Hamano wrote:
> Martin <git@mfriebe.de> writes:
>
>> And yes, for the documentation, it *should* be clear that, removing a
>> branch, removes the
>> commits on it.
>> But then it must be said, that the branch is first removed. That is
>> not currently the case.
> Sorry, but I still do not see how it makes any difference if the
> branch is first removed and then made to point at somewhere else, or
> the branch gets just moved without any explicit or impolicit
> removal.  A branch cannot point at two different commits at the same
> time, so the end result is that the commit at the old tip is no
> longer pointed at by the branch after the update.

Well all very obvious, if you know git well.

Let's take a step back. How exactly is the word "branch" actually 
defined? Well it does not matter.
What matters is, how the word is used.
What does a person mean, when they speak of the branch?

And the answer is, it's not always clear.

In the above conversation, we use "branch" to speak of the "pointer to a 
single commit".
We do not include any commits, when speaking of the "branch".
(And this is how it is used in the docs, as far as I can find)

However a lot of people use "branch" to refer to the commits within.
"Push a branch to a remote". That obviously means the objects (e.g. 
commits) in the branch.
The doc says (and yes I am getting a bit picky here)
 >>> Updates remote refs using local refs, while sending objects 
necessary to complete the given refs.
"complete the given ref". The ref is given by the branch, and completing 
means afaik "to make something part of"
Maybe a mistake made, because "branch" is (according to my observation) 
so commonly (mis-)used to include the objects.

Anyway, can we agree, that there are people who  (mistakenly) 
use/understand "branch" as including the objects?
Enough people to call it a "common mistake".
If so, then we should not ignore this.

With this use of "branch" in mind, (re-)creating an existing  branch on 
a new startpoint,
does to the inexperienced user read like a rebase. It recreates all the 
commits.
The fact that as an experienced user, I shake my head in disbelief, does 
not change this.

But true, my attempt on adding "the old branch is removed" does not either.
So not sure which wording will do best.
Probably
        "Creates a new empty branch at <start point>"

Even though "empty" may be a sloppy usage too....


The other problem with the current doc is

> On 01/07/2021 02:06, Matt Rogers wrote:
>> I think the current documentations usage of "reset" in
>>
>>      Similar to --create except that if <new-branch> already exists, it
>> will be reset to <start-point>.
>>
>> Is pretty clear about what happens, although it does rely on users
>> being familiar
>> with the semantics of "resetting" a la git reset.
>
Not everyone is "familiar" with reset.
And if you look up reset, you are left alone if that is a --soft or 
--hard or --mixed.

In any case, while it is ok, to refer to other parts of the doc, it 
should still be possible
to read just the current doc, and get a full understanding of the command.

So a short addition to the current doc, that explains "reset" should be 
added.

I currently am out of ideas how to word it, other than based on my 
previous ideas.

But as in the first part of this mail, maybe just add the "empty" to the 
existing doc?
So the existing
    "it will be reset to |<start-point>|. "
changes to
    "it will be reset to [become] an empty branch at |<start-point>|. "

Happy for any idea, how the reader can be reminded, that "branch" is the 
pointer only, and excludes any objects that it refers to.

I was just about to write "any objects in it (in the branch)". But as 
established the objects are not part, therefore not "in it"...
Just how easy it is to think of branch as more than it is.
Sergey Organov July 1, 2021, 11:27 a.m. UTC | #8
Martin <git@mfriebe.de> writes:

> On 01/07/2021 00:59, Junio C Hamano wrote:
>> Martin <git@mfriebe.de> writes:
>>
>>> And yes, for the documentation, it *should* be clear that, removing a
>>> branch, removes the
>>> commits on it.
>>> But then it must be said, that the branch is first removed. That is
>>> not currently the case.
>> Sorry, but I still do not see how it makes any difference if the
>> branch is first removed and then made to point at somewhere else, or
>> the branch gets just moved without any explicit or impolicit
>> removal.  A branch cannot point at two different commits at the same
>> time, so the end result is that the commit at the old tip is no
>> longer pointed at by the branch after the update.
>
> Well all very obvious, if you know git well.
>
> Let's take a step back. How exactly is the word "branch" actually defined? Well it does not matter.
> What matters is, how the word is used.
> What does a person mean, when they speak of the branch?
>
> And the answer is, it's not always clear.

Yep. The "branch" may mean a "chain of commits" or a "symbolic reference
to the tip of the branch", or even both, depending on the context.

It's somewhat similar to "file" vs "file name" in UNIX. You in fact
don't remove files in UNIX, you remove file names that refer to files
(entities on disk), yet "remove file" and "rename file" are often
used, even though they are not technically correct.

To me it's essential feature of Git that when you, say, "remove branch",
you only delete the symbolic reference, not any chain of commits, and
documentation should not contradict this where it uses the term
"branch".

>
> In the above conversation, we use "branch" to speak of the "pointer to a single commit".
> We do not include any commits, when speaking of the "branch".
> (And this is how it is used in the docs, as far as I can find)
>
> However a lot of people use "branch" to refer to the commits within.
> "Push a branch to a remote". That obviously means the objects (e.g. commits) in the branch.
> The doc says (and yes I am getting a bit picky here)
>>>> Updates remote refs using local refs, while sending objects necessary to complete the given refs.
> "complete the given ref". The ref is given by the branch, and
> completing means afaik "to make something part of"
> Maybe a mistake made, because "branch" is (according to my
> observation) so commonly (mis-)used to include the objects.
>
> Anyway, can we agree, that there are people who  (mistakenly)
> use/understand "branch" as including the objects?
> Enough people to call it a "common mistake".
> If so, then we should not ignore this.

I don't see this as a mistake. A branch is a chain of commits. It's just
using of short term "branch" without further clarification that could
lead to confusion.

>
> With this use of "branch" in mind, (re-)creating an existing  branch
> on a new startpoint, does to the inexperienced user read like a
> rebase. It recreates all the commits. The fact that as an experienced
> user, I shake my head in disbelief, does not change this.

Some understanding of underlying Git model is inevitable here. I'd
suggest to use "branch name" and other means to disambiguate description
instead of trying to describe what happens using wrong underlying model.

>
> But true, my attempt on adding "the old branch is removed" does not either.
> So not sure which wording will do best.
> Probably
>        "Creates a new empty branch at <start point>"
>
> Even though "empty" may be a sloppy usage too....
>

Yes, it's sloppy. There are no empty branches from Git point of view, so
this is not an option for proper documentation. Any branch has at least
one commit, the one the branch name is pointing at. It's entirely user
interpretation how many of the commits from the chain the Git branch has
they consider their branch "contains".

Overall, if we aim at clear documentation, we need to define our
documentation terms as precise as possible, and then use them
consistently.

For example:

"branch": a chain of commits

"branch tip": the most recent commit in a branch

"branch name": specific type of symbolic reference pointing to a branch tip

It's then up to the user to learn a few simple basics required for
proper understanding of documentation and behavior.

Thanks,
Junio C Hamano July 1, 2021, 2:58 p.m. UTC | #9
Martin <git@mfriebe.de> writes:

> Anyway, can we agree, that there are people who (mistakenly)
> use/understand "branch" as including the objects?
> Enough people to call it a "common mistake".
> If so, then we should not ignore this.

I do not think it is a mistake at all.  In a history where the
branch B points at commit Z, we do say the branch contains commits Z
and Y and we do say the branch does not contain commits X or W, for
example.

                 W---X
                /
        ---o---V---Y---Z
                       ^ we're here (branch B)

This is even true if the user is not yet familiar with the
"snapshots" view of the world (which is based on "the objects"), but
has the "changes" view of the world.  The branch has the change that
took Y to Z and the change that took V to Y, but it does not have
the change that took W to X or the change that took V to W.

> With this use of "branch" in mind, (re-)creating an existing
> branch on a new startpoint, does to the inexperienced user read
> like a rebase. It recreates all the commits.

If I understand you correctly, the confusion your hypothetical
newbie would have is caused by the word "start-point" in 

	git branch -f <branch-name> <start-point>

That is, if we repoint the branch that is currently at Z to point at
X with "git branch -f B X", it is possible to imagine that we build
more history on top of "X" simply because "X" is called "start-point",
i.e. we start at X and do something more.

And _your_ particular hypothetical user would imagine that that
something more is to replay Y and Z on top.

But I find two problems with the proposed solution to solve that
confusion.

 * Replaying Y and Z on top of X is not the only possible way to
   build "more" history on top of "start-point" that is X.  It is,
   for example, entirely plausible to look at the remote-tracking
   branch of B and rebuild the history missing from there on top of
   X, just like your version of confusion rebuilt the history
   missing from the tip of old B on top of X.  Saying "Z and Y will
   not be replayed on top of X after resetting the tip of the branch
   to X" may help _your_ version of confusion, but not other
   confusion.

 * In general, when an explanation in the documentation says that
   a command does A, it shouldn't have to say "the command does A
   but does not do B or C on top of that".

I think the source of the confusion is the <start point>.  It does
not change what the explanation wants to say at all if we changed
it to <end point>.  It is where the branch's tip ends up to be after
"git branch -f" (or "git switch -C") finishes, so it might even be
technically more correct.

The only reason why we use <start point> is purely historical.  We
used that phrase from the very beginning.  The explanation did not
consider the use of "gir branch -f" is the *end* of the world.  It
intended the user to use "gir branch [-f]" to start or restart a
branch as the first step of many other things the user will do to
build a history on the branch, and that is the reason why the word
"start" is used.

Perhaps along the lines of the attached patch would be an
improvement without adding "we do not do B, we do not do C, we do
not do anything else we do not say we do in this documentation".

Note that the following is *not* meant to be a full illustration;
there are many leftover <start-point> in these pages after this
patch gets applied that need to be adjusted, if we were to go this
route.

 Documentation/git-branch.txt |  4 ++--
 Documentation/git-switch.txt | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git c/Documentation/git-branch.txt w/Documentation/git-branch.txt
index 94dc9a54f2..5e6a32da04 100644
--- c/Documentation/git-branch.txt
+++ w/Documentation/git-branch.txt
@@ -16,7 +16,7 @@ SYNOPSIS
 	[--points-at <object>] [--format=<format>]
 	[(-r | --remotes) | (-a | --all)]
 	[--list] [<pattern>...]
-'git branch' [--track | --no-track] [-f] <branchname> [<start-point>]
+'git branch' [--track | --no-track] [-f] <branchname> [<commit>]
 'git branch' (--set-upstream-to=<upstream> | -u <upstream>) [<branchname>]
 'git branch' --unset-upstream [<branchname>]
 'git branch' (-m | -M) [<oldbranch>] <newbranch>
@@ -115,7 +115,7 @@ OPTIONS
 
 -f::
 --force::
-	Reset <branchname> to <startpoint>, even if <branchname> exists
+	Reset <branchname> to <commit>, even if <branchname> exists
 	already. Without `-f`, 'git branch' refuses to change an existing branch.
 	In combination with `-d` (or `--delete`), allow deleting the
 	branch irrespective of its merged status. In combination with
diff --git c/Documentation/git-switch.txt w/Documentation/git-switch.txt
index 5c438cd505..c8ea86d385 100644
--- c/Documentation/git-switch.txt
+++ w/Documentation/git-switch.txt
@@ -9,8 +9,8 @@ SYNOPSIS
 --------
 [verse]
 'git switch' [<options>] [--no-guess] <branch>
-'git switch' [<options>] --detach [<start-point>]
-'git switch' [<options>] (-c|-C) <new-branch> [<start-point>]
+'git switch' [<options>] --detach [<commit>]
+'git switch' [<options>] (-c|-C) <new-branch> [<commit>]
 'git switch' [<options>] --orphan <new-branch>
 
 DESCRIPTION
@@ -39,9 +39,9 @@ OPTIONS
 <new-branch>::
 	Name for the new branch.
 
-<start-point>::
-	The starting point for the new branch. Specifying a
-	`<start-point>` allows you to create a branch based on some
+<commit>::
+	The commit pointed at by the new branch. Specifying a
+	`<commit>` allows you to create a branch based on some
 	other point in history than where HEAD currently points. (Or,
 	in the case of `--detach`, allows you to inspect and detach
 	from some other point.)
@@ -59,7 +59,7 @@ out at most one of `A` and `B`, in which case it defaults to `HEAD`.
 -c <new-branch>::
 --create <new-branch>::
 	Create a new branch named `<new-branch>` starting at
-	`<start-point>` before switching to the branch. This is a
+	`<commit>` before switching to the branch. This is a
 	convenient shortcut for:
 +
 ------------
@@ -70,7 +70,7 @@ $ git switch <new-branch>
 -C <new-branch>::
 --force-create <new-branch>::
 	Similar to `--create` except that if `<new-branch>` already
-	exists, it will be reset to `<start-point>`. This is a
+	exists, it will be reset to `<commit>`. This is a
 	convenient shortcut for:
 +
 ------------
Martin July 1, 2021, 5:29 p.m. UTC | #10
On 01/07/2021 16:58, Junio C Hamano wrote:
> If I understand you correctly, the confusion your hypothetical
> newbie would have is caused by the word "start-point" in
>
> 	git branch -f <branch-name> <start-point>
>
> That is, if we repoint the branch that is currently at Z to point at
> X with "git branch -f B X", it is possible to imagine that we build
> more history on top of "X" simply because "X" is called "start-point",
> i.e. we start at X and do something more.
It is probably more the use of the word "branch" than it is "start point"

Sergey made an excellent point:
> On 01/07/2021 13:27, Sergey Organov wrote:
>> For example:
>>
>> "branch": a chain of commits
>>
>> "branch tip": the most recent commit in a branch
>>
>> "branch name": specific type of symbolic reference pointing to a branch tip

A lot of people think of the "chain of commits" when the word "branch" 
is used.

If we take the sentence from the current doc:
    --force-create
     Similar to |--create| except that if |<new-branch>| already exists, 
it will be reset to |<start-point>|
and replace "branch" with "chain of commits"
     Similar to |--create| except that if |<new-||"chain of commits">| 
already exists, it will be reset to |<start-point>|

What would you expect to happen?
I would think the "chain of commits" is created at the new <start-point>

What we want to say is
     The "branch name" will point to a new "branch tip" at <start-point>

However, this still leaves the point, that new users need to understand 
certain concepts and implications.
Such as moving a "branch name" abandons the old "chain of commits" (they 
do not follow).
"branch name" helps to remember that distinction, but it still needs to 
be learned first.
"abandon" => leave them to the reflog until expiry.

The point is, that those concepts (difference between branchname, and 
commits in branch) may all be documented.
But the reader may still be learning all this.
Then it will certainly help new users to learn , if the consequences of 
those are mentioned in places like "switch -C".


> But I find two problems with the proposed solution to solve that
> confusion.
>   * In general, when an explanation in the documentation says that
>     a command does A, it shouldn't have to say "the command does A
>     but does not do B or C on top of that".
Ok, that make sense. In general "negative" statements are not helpful.



> I think the source of the confusion is the <start point>.  It does
> not change what the explanation wants to say at all if we changed
> it to <end point>.
I don't actually see <start point> as the issue. But if it was then <end 
point> would mean
that your existing "chain of commits" would end there (as if it was a 
merge).


>   It is where the branch's tip ends up to be after
> "git branch -f" (or "git switch -C") finishes, so it might even be
> technically more correct.
But it is also where new commits for that branch will start. (they start 
at the current end, but that is confusing...)
Thinking about the name <fork point> would be more meaningful?

IMHO, start is way better than end. But "fork" is good too.

While going through the patch, I just noted

"git branch" uses <branchname>
"git switch" uses <new-branch>

It would be (a tiny) improvement, if "git switch" also used <branchname>
1)  it does help to get away from  "chain of commits"
2)  in case of -C the "new" part is actually wrong.

Using <commit> instead of <start-point> is better too.
Not so much for the above reasons.
<start-point>  described the function. But it did not tell you that you 
need a <commit>
Now you know you need a <commit>, and then you can check the function 
from the doc.


>   ------------
> @@ -70,7 +70,7 @@ $ git switch <new-branch>
>   -C <new-branch>::
>   --force-create <new-branch>::
>   	Similar to `--create` except that if `<new-branch>` already
> -	exists, it will be reset to `<start-point>`. This is a
> +	exists, it will be reset to `<commit>`. This is a
>   	convenient shortcut for:
>   +
>   ------------

Now with <branchname> that would be

  --force-create <new-branch>::
  	Similar to `--create` except that if `<branchname>` already
	exists, it will be reset to [point to] `<commit>`. This is a
  	convenient shortcut for:

At least, there would no longer be a word, that can be read as "chain of 
commits"
So <branchname> would be a definite improvement too.

Not sure if  [point to]  should be inserted?


I would still think, users should be somehow reminded of the implicit 
consequences.
Users reading that part of the doc may still be in the progress of 
learning all the concepts.
If nothing else, then maybe
       The branch previously at [pointed to by] <branchname> will/may no 
longer be reachable.
That is, it is obviously no longer reachable by <branchname>. But it may 
not be reachable by anything else either (reflog excluded).

However, adding any such "reminder" may be part of a more general 
discussion how verbose the documentation should be.
I.e. as you wrote in an earlier email, why for "switch" but not for others.
The argument that "switch" is one of the more essential commands, may 
not be enough.
Sergey Organov July 1, 2021, 5:46 p.m. UTC | #11
Martin <git@mfriebe.de> writes:

> On 01/07/2021 16:58, Junio C Hamano wrote:
>> If I understand you correctly, the confusion your hypothetical
>> newbie would have is caused by the word "start-point" in
>>
>> 	git branch -f <branch-name> <start-point>
>>
>> That is, if we repoint the branch that is currently at Z to point at
>> X with "git branch -f B X", it is possible to imagine that we build
>> more history on top of "X" simply because "X" is called "start-point",
>> i.e. we start at X and do something more.
> It is probably more the use of the word "branch" than it is "start point"
>
> Sergey made an excellent point:
>> On 01/07/2021 13:27, Sergey Organov wrote:
>>> For example:
>>>
>>> "branch": a chain of commits
>>>
>>> "branch tip": the most recent commit in a branch
>>>
>>> "branch name": specific type of symbolic reference pointing to a branch tip
>
> A lot of people think of the "chain of commits" when the word "branch" is used.
>
> If we take the sentence from the current doc:
>    --force-create
>     Similar to |--create| except that if |<new-branch>| already
> exists, it will be reset to |<start-point>|
> and replace "branch" with "chain of commits"
>     Similar to |--create| except that if |<new-||"chain of commits">|
> already exists, it will be reset to |<start-point>|
>
> What would you expect to happen?
> I would think the "chain of commits" is created at the new
> <start-point>

I find current "git switch" documentation utterly confusing, even for
experienced user, let alone for a novice. I'm only afraid that it's not
only documentation, but the design as well.

>
> What we want to say is
>     The "branch name" will point to a new "branch tip" at <start-point>
>
> However, this still leaves the point, that new users need to
> understand certain concepts and implications.
> Such as moving a "branch name" abandons the old "chain of commits" (they do not follow).
> "branch name" helps to remember that distinction, but it still needs to be learned first.
> "abandon" => leave them to the reflog until expiry.

Not necessarily. There could be other references left to this exact
commit. User doesn't need to be aware of reflog at this point at all.

>
> The point is, that those concepts (difference between branchname, and
> commits in branch) may all be documented.
> But the reader may still be learning all this.

There is no way around. Either they are expected to understand basics,
or documentation will lie to them trying to be helpful, that'd only
create even more confusion.

Thanks,
Felipe Contreras July 7, 2021, 6:14 p.m. UTC | #12
Martin wrote:
> Let's take a step back. How exactly is the word "branch" actually 
> defined? Well it does not matter.
> What matters is, how the word is used.
> What does a person mean, when they speak of the branch?

That is a good point.

> And the answer is, it's not always clear.

Indeed.

> In the above conversation, we use "branch" to speak of the "pointer to a 
> single commit".
> We do not include any commits, when speaking of the "branch".
> (And this is how it is used in the docs, as far as I can find)

This is how the term "branch" is used in git lingo.

> However a lot of people use "branch" to refer to the commits within.
> "Push a branch to a remote". That obviously means the objects (e.g. 
> commits) in the branch.
> The doc says (and yes I am getting a bit picky here)
>  >>> Updates remote refs using local refs, while sending objects 
> necessary to complete the given refs.
> "complete the given ref". The ref is given by the branch, and completing 
> means afaik "to make something part of"
> Maybe a mistake made, because "branch" is (according to my observation) 
> so commonly (mis-)used to include the objects.

Yes.

> Anyway, can we agree, that there are people who  (mistakenly) 
> use/understand "branch" as including the objects?
> Enough people to call it a "common mistake".
> If so, then we should not ignore this.

I wouldn't even call it a mistake.

Other SCMs, like Mercrual, do use this second meaning: the branch is the
specific commits that constitute that branch.

Can we really say user thinking that way is a mistake? I'm sure
Mercurial users would say git using the first notion is the a mistake.


It is a bigger mental load to be thinking in the two meanings at the
same time while writing the documentation, but if we really want to
reach the vast majority of users we do need to consider that the user
might be thinking in terms of the second notion.
Felipe Contreras July 7, 2021, 6:34 p.m. UTC | #13
Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
> > On 01/07/2021 00:59, Junio C Hamano wrote:
> >> Martin <git@mfriebe.de> writes:
> >>
> >>> And yes, for the documentation, it *should* be clear that, removing a
> >>> branch, removes the
> >>> commits on it.
> >>> But then it must be said, that the branch is first removed. That is
> >>> not currently the case.
> >> Sorry, but I still do not see how it makes any difference if the
> >> branch is first removed and then made to point at somewhere else, or
> >> the branch gets just moved without any explicit or impolicit
> >> removal.  A branch cannot point at two different commits at the same
> >> time, so the end result is that the commit at the old tip is no
> >> longer pointed at by the branch after the update.
> >
> > Well all very obvious, if you know git well.
> >
> > Let's take a step back. How exactly is the word "branch" actually defined? Well it does not matter.
> > What matters is, how the word is used.
> > What does a person mean, when they speak of the branch?
> >
> > And the answer is, it's not always clear.
> 
> Yep. The "branch" may mean a "chain of commits" or a "symbolic reference
> to the tip of the branch", or even both, depending on the context.
> 
> It's somewhat similar to "file" vs "file name" in UNIX. You in fact
> don't remove files in UNIX, you remove file names that refer to files
> (entities on disk), yet "remove file" and "rename file" are often
> used, even though they are not technically correct.

It's not even specific to computers, it's semantics of identifiers.

You can say John is not a person, "John" is the *name* of a person, the
person is constituted by cells and so on.

Most of the time it's not particularly useful to think on those terms,
but sometimes it useful in the sense that we can confidently say
"master" is not a branch, is the name of a branch.

In Mercurial branches are more like commit labels, so it's easy to see
the difference between a branch (a collection of commits), and a branch
name. In Git it's trickier because the branch is a pointer, and it
doesn't make much sense to think of a pointer without a name, but
strickly speaking they are different.

> > But true, my attempt on adding "the old branch is removed" does not either.
> > So not sure which wording will do best.
> > Probably
> >        "Creates a new empty branch at <start point>"
> >
> > Even though "empty" may be a sloppy usage too....
> >
> 
> Yes, it's sloppy. There are no empty branches from Git point of view, so
> this is not an option for proper documentation. Any branch has at least
> one commit, the one the branch name is pointing at. It's entirely user
> interpretation how many of the commits from the chain the Git branch has
> they consider their branch "contains".
> 
> Overall, if we aim at clear documentation, we need to define our
> documentation terms as precise as possible, and then use them
> consistently.
> 
> For example:
> 
> "branch": a chain of commits
> 
> "branch tip": the most recent commit in a branch
> 
> "branch name": specific type of symbolic reference pointing to a branch tip

Completely agree on all three (although I would call it "branch head",
not "branch tip").

Sometimes we can use a shortcut and say "master" is a branch, as we do
in everyday language when we say "John" is a person, but when we are
strict we have to remember what's behind that shortcut.


Slightly related although a little bit off-topic is the fact the *only*
thing Mercurial can do that Git can't is to find the branching point of
a branch [1] (I have really tried, it's truly not possible).

The *only* way it would be possible is by introducing a new concept:
"branch tail". I did implement patches for that (you could reference to
it with master@{tail}).

It is related to this topic because if we had a branch head, and a
branch tail, then you could not automatically assume the branch is the
branch head.

So even though most of the documentation currently conflates the two
concept, that doesn't mean the user does as well.

[1] https://stackoverflow.com/questions/1527234/finding-a-branch-point-with-git
Felipe Contreras July 7, 2021, 6:47 p.m. UTC | #14
Junio C Hamano wrote:
> Martin <git@mfriebe.de> writes:
> 
> > Anyway, can we agree, that there are people who (mistakenly)
> > use/understand "branch" as including the objects?
> > Enough people to call it a "common mistake".
> > If so, then we should not ignore this.
> 
> I do not think it is a mistake at all.  In a history where the
> branch B points at commit Z, we do say the branch contains commits Z
> and Y and we do say the branch does not contain commits X or W, for
> example.
> 
>                  W---X
>                 /
>         ---o---V---Y---Z
>                        ^ we're here (branch B)
> 

There's a difference between saying the branch *is* commits A, B, ... Y,
Z, and the branch *contains* commits ...

In Git only the latter is true, because technically the branch is a
pointer. But in Mercurial both are true.

> I think the source of the confusion is the <start point>.  It does
> not change what the explanation wants to say at all if we changed
> it to <end point>.  It is where the branch's tip ends up to be after
> "git branch -f" (or "git switch -C") finishes, so it might even be
> technically more correct.

Indeed.

However, there's a better alternative than "end point": head. Sure, the
unfortunate naming of the current branch as HEAD makes this slightly
confusing, but that's really what it is.

If you change the branch head *everyone* understands the the branch
itself is changed, and the commits that are part of the branch are
different.
Felipe Contreras July 7, 2021, 6:54 p.m. UTC | #15
Martin wrote:
> Sergey made an excellent point:
> > On 01/07/2021 13:27, Sergey Organov wrote:
> >> For example:
> >>
> >> "branch": a chain of commits
> >>
> >> "branch tip": the most recent commit in a branch
> >>
> >> "branch name": specific type of symbolic reference pointing to a branch tip
> 
> A lot of people think of the "chain of commits" when the word "branch" 
> is used.
> 
> If we take the sentence from the current doc:
>     --force-create
>      Similar to |--create| except that if |<new-branch>| already exists, 
> it will be reset to |<start-point>|
> and replace "branch" with "chain of commits"
>      Similar to |--create| except that if |<new-||"chain of commits">| 
> already exists, it will be reset to |<start-point>|
> 
> What would you expect to happen?
> I would think the "chain of commits" is created at the new <start-point>
> 
> What we want to say is
>      The "branch name" will point to a new "branch tip" at <start-point>

Wouldn't this achieve everything we want?

  The branch head will now point the new <head>
Sergey Organov July 7, 2021, 8:46 p.m. UTC | #16
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Martin <git@mfriebe.de> writes:
>> > On 01/07/2021 00:59, Junio C Hamano wrote:
>> >> Martin <git@mfriebe.de> writes:
>> >>
>> >>> And yes, for the documentation, it *should* be clear that, removing a
>> >>> branch, removes the
>> >>> commits on it.
>> >>> But then it must be said, that the branch is first removed. That is
>> >>> not currently the case.
>> >> Sorry, but I still do not see how it makes any difference if the
>> >> branch is first removed and then made to point at somewhere else, or
>> >> the branch gets just moved without any explicit or impolicit
>> >> removal.  A branch cannot point at two different commits at the same
>> >> time, so the end result is that the commit at the old tip is no
>> >> longer pointed at by the branch after the update.
>> >
>> > Well all very obvious, if you know git well.
>> >
>> > Let's take a step back. How exactly is the word "branch" actually
>> > defined? Well it does not matter.
>> > What matters is, how the word is used.
>> > What does a person mean, when they speak of the branch?
>> >
>> > And the answer is, it's not always clear.
>> 
>> Yep. The "branch" may mean a "chain of commits" or a "symbolic reference
>> to the tip of the branch", or even both, depending on the context.
>> 
>> It's somewhat similar to "file" vs "file name" in UNIX. You in fact
>> don't remove files in UNIX, you remove file names that refer to files
>> (entities on disk), yet "remove file" and "rename file" are often
>> used, even though they are not technically correct.
>
> It's not even specific to computers, it's semantics of identifiers.
>
> You can say John is not a person, "John" is the *name* of a person, the
> person is constituted by cells and so on.
>
> Most of the time it's not particularly useful to think on those terms,
> but sometimes it useful in the sense that we can confidently say
> "master" is not a branch, is the name of a branch.
>
> In Mercurial branches are more like commit labels, so it's easy to see
> the difference between a branch (a collection of commits), and a branch
> name. In Git it's trickier because the branch is a pointer, and it
> doesn't make much sense to think of a pointer without a name, but
> strickly speaking they are different.
>
>> > But true, my attempt on adding "the old branch is removed" does not either.
>> > So not sure which wording will do best.
>> > Probably
>> >        "Creates a new empty branch at <start point>"
>> >
>> > Even though "empty" may be a sloppy usage too....
>> >
>> 
>> Yes, it's sloppy. There are no empty branches from Git point of view, so
>> this is not an option for proper documentation. Any branch has at least
>> one commit, the one the branch name is pointing at. It's entirely user
>> interpretation how many of the commits from the chain the Git branch has
>> they consider their branch "contains".
>> 
>> Overall, if we aim at clear documentation, we need to define our
>> documentation terms as precise as possible, and then use them
>> consistently.
>> 
>> For example:
>> 
>> "branch": a chain of commits
>> 
>> "branch tip": the most recent commit in a branch
>> 
>> "branch name": specific type of symbolic reference pointing to a branch tip
>
> Completely agree on all three (although I would call it "branch head",
> not "branch tip").

I see why "branch head", as you later introduce "branch tail", but a
branch (of a plant) has no "head" (nor "tail"), right? BTW, how the base
of a plant branch is called in English, and how one finds "branch tail"
on a real tree anyway? I mean, there are probably a few of them, at
every fork. In Git it's even more vague, as a branch could logically
begin at any place, not necessarily at a fork point.

OTOH, "head" and "tail" are obviously taken from CS "list" concept, and,
provided "chain" == "list", it does make sense. And then we have 'HEAD'
that points to the current branch tip anyway.

Dunno, in fact I don't have any preference among "tip" and "head".

As for branch tail, I do have convention of marking start of a
long-standing branch with corresponding tag, where branch "foo" has
corresponding "foo-bp" tag marking its "branch point". Recently I
started to mark start of feature branch with yet another branch "foo-bp"
rather than tag, "foo" being set to track "foo-bp", that allows to
automate rebasing of "foo" against correct base.

Thanks,
Felipe Contreras July 7, 2021, 9:25 p.m. UTC | #17
Since this is not strictly related to the topic of `git switch` I
renamed the thread.

Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> > Sergey Organov wrote:

> >> Overall, if we aim at clear documentation, we need to define our
> >> documentation terms as precise as possible, and then use them
> >> consistently.
> >> 
> >> For example:
> >> 
> >> "branch": a chain of commits
> >> 
> >> "branch tip": the most recent commit in a branch
> >> 
> >> "branch name": specific type of symbolic reference pointing to a branch tip
> >
> > Completely agree on all three (although I would call it "branch head",
> > not "branch tip").
> 
> I see why "branch head", as you later introduce "branch tail", but a
> branch (of a plant) has no "head" (nor "tail"), right? BTW, how the base
> of a plant branch is called in English, and how one finds "branch tail"
> on a real tree anyway? I mean, there are probably a few of them, at
> every fork. In Git it's even more vague, as a branch could logically
> begin at any place, not necessarily at a fork point.

We don't necessarily need a 1-to-1 mapping with common English (although
that would be nice). Anoher option could be "base" and "tip".

> OTOH, "head" and "tail" are obviously taken from CS "list" concept, and,
> provided "chain" == "list", it does make sense.

I took it from Mercurial, where the tip of a branch is called "head",
and in fact a branch can have multiple heads.

> And then we have 'HEAD' that points to the current branch tip anyway.

It actually points to a branch, or rather references a branch, since it
uses the branch name.

> Dunno, in fact I don't have any preference among "tip" and "head".

I don't either, but from different sources (non-git-specific) I've heard
"head" more often.

> As for branch tail, I do have convention of marking start of a
> long-standing branch with corresponding tag, where branch "foo" has
> corresponding "foo-bp" tag marking its "branch point". Recently I
> started to mark start of feature branch with yet another branch "foo-bp"
> rather than tag, "foo" being set to track "foo-bp", that allows to
> automate rebasing of "foo" against correct base.

So foo-bp is the upstream of foo, and you do basically:

  git rebase foo@{upstream}

This is works if your base (or tail, or whatever) is static, but many
branches jump around, and that's where @{tail} comes in handy.

You can do this:

  git rebase --onto foo@{upstream} foo@{tail}

This will always rebase the right commits (no need to look into the
reflog). So you can say that the branch is foo@{tail}..foo.

Another advantage of having this notion is that `git rebase`
automatically updates the tail (in this case to foo@{upstream}).

Cheers.
Sergey Organov July 7, 2021, 10:07 p.m. UTC | #18
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Since this is not strictly related to the topic of `git switch` I
> renamed the thread.
>
> Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> > Sergey Organov wrote:
>
>> >> Overall, if we aim at clear documentation, we need to define our
>> >> documentation terms as precise as possible, and then use them
>> >> consistently.
>> >> 
>> >> For example:
>> >> 
>> >> "branch": a chain of commits
>> >> 
>> >> "branch tip": the most recent commit in a branch
>> >> 
>> >> "branch name": specific type of symbolic reference pointing to a
>> >> branch tip
>> >
>> > Completely agree on all three (although I would call it "branch head",
>> > not "branch tip").
>> 
>> I see why "branch head", as you later introduce "branch tail", but a
>> branch (of a plant) has no "head" (nor "tail"), right? BTW, how the base
>> of a plant branch is called in English, and how one finds "branch tail"
>> on a real tree anyway? I mean, there are probably a few of them, at
>> every fork. In Git it's even more vague, as a branch could logically
>> begin at any place, not necessarily at a fork point.
>
> We don't necessarily need a 1-to-1 mapping with common English (although
> that would be nice). Anoher option could be "base" and "tip".
>
>> OTOH, "head" and "tail" are obviously taken from CS "list" concept, and,
>> provided "chain" == "list", it does make sense.
>
> I took it from Mercurial, where the tip of a branch is called "head",
> and in fact a branch can have multiple heads.
>
>> And then we have 'HEAD' that points to the current branch tip anyway.
>
> It actually points to a branch, or rather references a branch, since it
> uses the branch name.

Yes, but it still points to the branch tip, indirectly, or even
directly, when in "detached head" state, that, by the way, I'd vote to
abandon, replacing it with more user-friendly "unnamed branch" or
something like that.

>
>> Dunno, in fact I don't have any preference among "tip" and "head".
>
> I don't either, but from different sources (non-git-specific) I've heard
> "head" more often.
>
>> As for branch tail, I do have convention of marking start of a
>> long-standing branch with corresponding tag, where branch "foo" has
>> corresponding "foo-bp" tag marking its "branch point". Recently I
>> started to mark start of feature branch with yet another branch "foo-bp"
>> rather than tag, "foo" being set to track "foo-bp", that allows to
>> automate rebasing of "foo" against correct base.
>
> So foo-bp is the upstream of foo, and you do basically:
>
>   git rebase foo@{upstream}

Yep, but essential feature to me is that I in fact use tools that simply
run bare

   git rebase

and that "just works" (tm).

>
> This is works if your base (or tail, or whatever) is static, but many
> branches jump around, and that's where @{tail} comes in handy.

Yeah, I see. When I need to make a branch jump around, I do need to
manually move my references, but that's fortunately very rare use-case
for me. Having direct support for that is still a win.

>
> You can do this:
>
>   git rebase --onto foo@{upstream} foo@{tail}
>
> This will always rebase the right commits (no need to look into the
> reflog). So you can say that the branch is foo@{tail}..foo.

I see where and when it's useful, but for a feature branch 99% of times
I don't want to rebase it onto some true upstream. I rather want to just
fiddle with the branch in place, and I prefer to setup things the way
that ensures that bare "git rebase" does "the right thing".

Probably that could be solved by a branch-local configuration that makes
"git rebase" become "git rebase @{tail}" for the branch instead of "git
rebase @{upstream}"

>
> Another advantage of having this notion is that `git rebase`
> automatically updates the tail (in this case to foo@{upstream}).

Yep, looks useful. Is it all local to given repo, or else?

Thanks,
Martin July 7, 2021, 10:35 p.m. UTC | #19
On 08/07/2021 00:07, Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
>>
>> This is works if your base (or tail, or whatever) is static, but many
>> branches jump around, and that's where @{tail} comes in handy.
> 
> Yeah, I see. When I need to make a branch jump around, I do need to
> manually move my references, but that's fortunately very rare use-case
> for me. Having direct support for that is still a win.
> 
>>
>> You can do this:
>>
>>    git rebase --onto foo@{upstream} foo@{tail}
>>
>> This will always rebase the right commits (no need to look into the
>> reflog). So you can say that the branch is foo@{tail}..foo.
> 

Maybe I am missing something, is tail for tracking branches only, or for 
just any branch?

If for any branch, looking at

   A => B => C => D  master
        |
         \          / => G => H  branch_1
          => E => F
                    \ => I => J  branch_2

Where is the base of branch_1 and branch_2?
(and does it matter if they have an upstream)

Maybe branch_1 diverged from Master, and then branch_2 from branch_1?

Maybe the other way round.

Maybe there was a branch_0 (that got removed),
and branch_0 diverged from master, and branch_1 and branch_2 both from 
branch_0?

---
Also base may be misleading.

If head is the one end of the commit chains, then base should be the other.
But all branches contain commits A (and B). So the base would be A.

"fork" would be more descriptive IMHO?

Also, if that is to save the user from looking up fork points, maybe 
extend the syntax
   branch_1@{fork:branch_2}
   branch_1@{fork:master}

Depending on some of the answers to the above
   branch_1@{fork}
nearest fork, or upstream fork?
Felipe Contreras July 8, 2021, 3:12 a.m. UTC | #20
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Since this is not strictly related to the topic of `git switch` I
> > renamed the thread.
> >
> > Sergey Organov wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
> >> > Sergey Organov wrote:
> >
> >> >> Overall, if we aim at clear documentation, we need to define our
> >> >> documentation terms as precise as possible, and then use them
> >> >> consistently.
> >> >> 
> >> >> For example:
> >> >> 
> >> >> "branch": a chain of commits
> >> >> 
> >> >> "branch tip": the most recent commit in a branch
> >> >> 
> >> >> "branch name": specific type of symbolic reference pointing to a
> >> >> branch tip
> >> >
> >> > Completely agree on all three (although I would call it "branch head",
> >> > not "branch tip").
> >> 
> >> I see why "branch head", as you later introduce "branch tail", but a
> >> branch (of a plant) has no "head" (nor "tail"), right? BTW, how the base
> >> of a plant branch is called in English, and how one finds "branch tail"
> >> on a real tree anyway? I mean, there are probably a few of them, at
> >> every fork. In Git it's even more vague, as a branch could logically
> >> begin at any place, not necessarily at a fork point.
> >
> > We don't necessarily need a 1-to-1 mapping with common English (although
> > that would be nice). Anoher option could be "base" and "tip".
> >
> >> OTOH, "head" and "tail" are obviously taken from CS "list" concept, and,
> >> provided "chain" == "list", it does make sense.
> >
> > I took it from Mercurial, where the tip of a branch is called "head",
> > and in fact a branch can have multiple heads.
> >
> >> And then we have 'HEAD' that points to the current branch tip anyway.
> >
> > It actually points to a branch, or rather references a branch, since it
> > uses the branch name.
> 
> Yes, but it still points to the branch tip, indirectly, or even
> directly, when in "detached head" state, that, by the way, I'd vote to
> abandon, replacing it with more user-friendly "unnamed branch" or
> something like that.

Yes, but most of the time it's indirectly.

> >> Dunno, in fact I don't have any preference among "tip" and "head".
> >
> > I don't either, but from different sources (non-git-specific) I've heard
> > "head" more often.
> >
> >> As for branch tail, I do have convention of marking start of a
> >> long-standing branch with corresponding tag, where branch "foo" has
> >> corresponding "foo-bp" tag marking its "branch point". Recently I
> >> started to mark start of feature branch with yet another branch "foo-bp"
> >> rather than tag, "foo" being set to track "foo-bp", that allows to
> >> automate rebasing of "foo" against correct base.
> >
> > So foo-bp is the upstream of foo, and you do basically:
> >
> >   git rebase foo@{upstream}
> 
> Yep, but essential feature to me is that I in fact use tools that simply
> run bare
> 
>    git rebase
> 
> and that "just works" (tm).

I typed the revision explicitly, but `git rebase` would work just fine.

> > This is works if your base (or tail, or whatever) is static, but many
> > branches jump around, and that's where @{tail} comes in handy.
> 
> Yeah, I see. When I need to make a branch jump around, I do need to
> manually move my references, but that's fortunately very rare use-case
> for me. Having direct support for that is still a win.
> 
> >
> > You can do this:
> >
> >   git rebase --onto foo@{upstream} foo@{tail}
> >
> > This will always rebase the right commits (no need to look into the
> > reflog). So you can say that the branch is foo@{tail}..foo.
> 
> I see where and when it's useful, but for a feature branch 99% of times
> I don't want to rebase it onto some true upstream. I rather want to just
> fiddle with the branch in place, and I prefer to setup things the way
> that ensures that bare "git rebase" does "the right thing".

But that's precisely the point: when you do `git rebase` you don't have
to type the base or --onto anymore. It's done automatically.

Not just for your long-standing branches, but for *any* branch.

> Probably that could be solved by a branch-local configuration that makes
> "git rebase" become "git rebase @{tail}" for the branch instead of "git
> rebase @{upstream}"

No. @{upstream} is where you want to rebase *to*, @{tail} is where you
want to rebase *from*.

When you do:

  git rebase foo@{upstream}

This is basically the same as:

  git checkout foo@{upstream}^0
  git cherry-pick --right-only foo@{upstream}...foo

git is smart enough to figure out what commits are already part of
foo@{upstream}, and those are skipped, but at no point was any "base"
calculated (at least not from `git rebase`).

Most of the time `git rebase` works fine, because there aren't too many
commits to figure out where they should go, but it's definitely not
efficient, and there's many corner-cases (see a Linux kernel maintaner
baffled by what the hell `git rebase` is doing [1]).

> > Another advantage of having this notion is that `git rebase`
> > automatically updates the tail (in this case to foo@{upstream}).
> 
> Yep, looks useful. Is it all local to given repo, or else?

I implented it as 'refs/tails' (as opposed to 'refs/heads'), so it's
local to a given repo, but could easily be exported.

[1] https://lore.kernel.org/git/60b272ff6bfa4_265861208d6@natae.notmuch/
Felipe Contreras July 8, 2021, 3:39 a.m. UTC | #21
Martin wrote:
> On 08/07/2021 00:07, Sergey Organov wrote:
> > Felipe Contreras <felipe.contreras@gmail.com> writes:
> >>
> >> This is works if your base (or tail, or whatever) is static, but many
> >> branches jump around, and that's where @{tail} comes in handy.
> > 
> > Yeah, I see. When I need to make a branch jump around, I do need to
> > manually move my references, but that's fortunately very rare use-case
> > for me. Having direct support for that is still a win.
> > 
> >>
> >> You can do this:
> >>
> >>    git rebase --onto foo@{upstream} foo@{tail}
> >>
> >> This will always rebase the right commits (no need to look into the
> >> reflog). So you can say that the branch is foo@{tail}..foo.
> > 
> 
> Maybe I am missing something, is tail for tracking branches only, or for 
> just any branch?

Any branch.

> If for any branch, looking at
> 
>    A => B => C => D  master
>         |
>          \          / => G => H  branch_1
>           => E => F
>                     \ => I => J  branch_2
> 
> Where is the base of branch_1 and branch_2?

It depends where the corresponding `git switch --create` command was
issued.

If you did `git switch --create branch_1 B`, then @{tail} is B.
If you did `git switch --create branch_1 F`, then @{tail} is F.

> (and does it matter if they have an upstream)

No. That's completely independent.

> Maybe branch_1 diverged from Master, and then branch_2 from branch_1?
> 
> Maybe the other way round.
> 
> Maybe there was a branch_0 (that got removed),
> and branch_0 diverged from master, and branch_1 and branch_2 both from 
> branch_0?

Yeap, the tails of branch_1 and branch_2 could be literally anywhere.

That information is not recoverable from the current data structures of
git, thus the proposal to add a new one.

> ---
> Also base may be misleading.
> 
> If head is the one end of the commit chains, then base should be the other.
> But all branches contain commits A (and B). So the base would be A.

All branches contain A, but only one branch could have A as a
base/tail (under normal operations), and likely none do.

Suppose branch_2 was created this way:

  git switch --create branch_2 A

Then commit B was created under branch_2. Then master was fast-forwarded
to branch_2, so you have:

                 A => B master
                 ^    ^
  tail/branch_2 -+    +- head/branch_2

Both branches have A, but only branch_2 has A as tail.

As both branches move forward they diverge, and the "fork-point" is B,
but B is not the tail of *any* branch.

Naturally then branch_1 would be created with F as a starting point, so
that would be the tail of branch_1.

And once again, even though F is part of both branch_1 and branch_2,
it's the tail of branch_1 *only*.


This is a convoluted way of saying: the tail of a branch is the point
where that branch was created.

> "fork" would be more descriptive IMHO?

As you can see from the example above, the tail doesn't necessarily have
to be a fork-point.

Not to mention that there can be multiple forks after the tail (e.g. B
and F).

> Also, if that is to save the user from looking up fork points, maybe 
> extend the syntax
>    branch_1@{fork:branch_2}
>    branch_1@{fork:master}
> 
> Depending on some of the answers to the above
>    branch_1@{fork}
> nearest fork, or upstream fork?

Except it's not necessarily a fork, nor the nearest, nor related to
upstream...

So it's not a fork.

It can be literally any commit.

Cheers.
Martin July 8, 2021, 10:15 a.m. UTC | #22
On 08/07/2021 05:39, Felipe Contreras wrote:
> 
> Yeap, the tails of branch_1 and branch_2 could be literally anywhere.
> 
> That information is not recoverable from the current data structures of
> git, thus the proposal to add a new one.

Ok, thanks for the all the explanation.

A word on the name "tail". IMHO really confusing. I get where it is 
coming from.
But a lot of people will know head and tail utilities from their shell. 
And "tail" is the one that shows lines on the end of the file to which 
new data is added. Which is "head" in git.

Also a tail is something that follows, but (except for rebase), the base 
point is fixed.


I think (despite my earlier comment) "base" is a better word.
It also goes along with "git rebase" which acts on the "base".


However wording around that topic probably still needs to be very careful.
"base" must be clearly distinguished from "start". Because "start" might 
imply that only commits from here on forward are contained, but that 
contradicts --contains which reports root to head.



 > Suppose branch_2 was created this way:
 >
 >   git switch --create branch_2 A
 >
 > Then commit B was created under branch_2. Then master was fast-forwarded
 > to branch_2, so you have:
 >
 >                  A => B master
 >                  ^    ^
 >   tail/branch_2 -+    +- head/branch_2
 >
 > Both branches have A, but only branch_2 has A as tail.


So base (tail) is the shared commit "A" on which branch_2 was created. 
(rather than the first commit made in branch_2 which is "B")

I can see how that is needed for "git rebase" so @{base} can be used for 
<upstream>.



What happens if branch_2 is rebased?
Will the base be set to the commit onto which the branch was rebased?

A => B => C => D => E master
            \ => F => G  foo (base = B)

foo was created on B, then fast forwarded to C, then diverged.


    git rebase --onto A  foo@{base}  foo

Now that foo diverges before B, having B as base for foo seems odd. 
(Also A will have C' as child, So the base really is A now)

    git rebase --onto E  foo@{base}  foo

In this case C is already contained in master, so it will be skipped.
If the base is moved, then foo@{base}..foo will no longer contain C. 
IMHO that is correct, because rebase skipped it.

The alternative if base = C would be kept, then foo@{base}..foo would 
contain D and E. And that seems wrong?




Will there be a way to manually repoint the base?

A => B => C => D master
       \ => E => F  foo
                 \ => G => H  bar (base = F)


If I do

   git rebase --onto master  bar@{base} bar

then the commits E and F will not be part of the rebase.
That is fine. I must handle them before.

But if I deleted foo (or for other reasons decide E and F should be 
handled if I rebase bar) can I make them to be included?
Something like

   git base --repoint B  bar
Sergey Organov July 8, 2021, 11:16 a.m. UTC | #23
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>> > Since this is not strictly related to the topic of `git switch` I
>> > renamed the thread.
>> >
>> > Sergey Organov wrote:
>> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> >> > Sergey Organov wrote:

[...]

>> >> As for branch tail, I do have convention of marking start of a
>> >> long-standing branch with corresponding tag, where branch "foo" has
>> >> corresponding "foo-bp" tag marking its "branch point". Recently I
>> >> started to mark start of feature branch with yet another branch "foo-bp"
>> >> rather than tag, "foo" being set to track "foo-bp", that allows to
>> >> automate rebasing of "foo" against correct base.
>> >
>> > So foo-bp is the upstream of foo, and you do basically:
>> >
>> >   git rebase foo@{upstream}
>> 
>> Yep, but essential feature to me is that I in fact use tools that simply
>> run bare
>> 
>>    git rebase
>> 
>> and that "just works" (tm).
>
> I typed the revision explicitly, but `git rebase` would work just
> fine.

Sorry, I don't follow. Did you change semantic of `git rebase`? With
current mainstream Git, as far as I can tell,

  git rebase

essentially is:

  git rebase --fork-point @{upstream}

How introduction of @{tail} changes this, exactly?

>
>> > This is works if your base (or tail, or whatever) is static, but many
>> > branches jump around, and that's where @{tail} comes in handy.
>> 
>> Yeah, I see. When I need to make a branch jump around, I do need to
>> manually move my references, but that's fortunately very rare use-case
>> for me. Having direct support for that is still a win.
>> 
>> >
>> > You can do this:
>> >
>> >   git rebase --onto foo@{upstream} foo@{tail}
>> >
>> > This will always rebase the right commits (no need to look into the
>> > reflog). So you can say that the branch is foo@{tail}..foo.
>> 
>> I see where and when it's useful, but for a feature branch 99% of times
>> I don't want to rebase it onto some true upstream. I rather want to just
>> fiddle with the branch in place, and I prefer to setup things the way
>> that ensures that bare "git rebase" does "the right thing".
>
> But that's precisely the point: when you do `git rebase` you don't have
> to type the base or --onto anymore. It's done automatically.
>
> Not just for your long-standing branches, but for *any* branch.
>
>> Probably that could be solved by a branch-local configuration that makes
>> "git rebase" become "git rebase @{tail}" for the branch instead of "git
>> rebase @{upstream}"
>
> No. @{upstream} is where you want to rebase *to*, @{tail} is where you
> want to rebase *from*.

My point is that for feature branch I rather want to rebase from @{tail}
to @{tail} 99% of times.

>
> When you do:
>
>   git rebase foo@{upstream}
>
> This is basically the same as:
>
>   git checkout foo@{upstream}^0
>   git cherry-pick --right-only foo@{upstream}...foo

Yes, but you probably meant foo@{upstream}..foo (2 dots, not 3) here.

> git is smart enough to figure out what commits are already part of
> foo@{upstream}, and those are skipped, but at no point was any "base"
> calculated (at least not from `git rebase`).
>
> Most of the time `git rebase` works fine, because there aren't too many
> commits to figure out where they should go, but it's definitely not
> efficient, and there's many corner-cases (see a Linux kernel maintaner
> baffled by what the hell `git rebase` is doing [1]).

Once again, how exactly the foo@{tail} fits in this picture?

>
>> > Another advantage of having this notion is that `git rebase`
>> > automatically updates the tail (in this case to foo@{upstream}).
>> 
>> Yep, looks useful. Is it all local to given repo, or else?
>
> I implented it as 'refs/tails' (as opposed to 'refs/heads'), so it's
> local to a given repo, but could easily be exported.

Do I get it right that now `git switch br1; git rebase --onto br2` will
likely have different outcome in the repository where "br1" has been
created compared to any other repository, as "br1@{tail}" will only
exist in that exact repo?

Thanks,
Felipe Contreras July 8, 2021, 5:33 p.m. UTC | #24
Martin wrote:
> On 08/07/2021 05:39, Felipe Contreras wrote:
> > 
> > Yeap, the tails of branch_1 and branch_2 could be literally anywhere.
> > 
> > That information is not recoverable from the current data structures of
> > git, thus the proposal to add a new one.
> 
> Ok, thanks for the all the explanation.
> 
> A word on the name "tail". IMHO really confusing. I get where it is 
> coming from.
> But a lot of people will know head and tail utilities from their shell. 
> And "tail" is the one that shows lines on the end of the file to which 
> new data is added. Which is "head" in git.
> 
> Also a tail is something that follows, but (except for rebase), the base 
> point is fixed.
> 
> 
> I think (despite my earlier comment) "base" is a better word.
> It also goes along with "git rebase" which acts on the "base".
> 
> 
> However wording around that topic probably still needs to be very careful.
> "base" must be clearly distinguished from "start". Because "start" might 
> imply that only commits from here on forward are contained, but that 
> contradicts --contains which reports root to head.

I'm not really proposing such feature at this point. I did it on 2013
just to have a solution to this problem, but I didn't push for it back
then.

If I ever work on that feature again I will consider the name "base",
sure, but the only reason I mentioned this @{tail} concept is to try to
define in a more accurate way what a branch actually is.

>  > Suppose branch_2 was created this way:
>  >
>  >   git switch --create branch_2 A
>  >
>  > Then commit B was created under branch_2. Then master was fast-forwarded
>  > to branch_2, so you have:
>  >
>  >                  A => B master
>  >                  ^    ^
>  >   tail/branch_2 -+    +- head/branch_2
>  >
>  > Both branches have A, but only branch_2 has A as tail.
> 
> 
> So base (tail) is the shared commit "A" on which branch_2 was created. 
> (rather than the first commit made in branch_2 which is "B")
> 
> I can see how that is needed for "git rebase" so @{base} can be used for 
> <upstream>.

Yes and no. <upstream> is where branch is rebased *to*, not where it's
rebased *from*:

  git rebase --onto foo@{upstream} foo@{base} foo

This command rebases all the commits foo@{base}..foo on top of
foo@{upstream}.

Another way to think of it is that you'll cherry-pick foo@{base}..foo on
top of foo@{upstream}.

> What happens if branch_2 is rebased?
> Will the base be set to the commit onto which the branch was rebased?
> 
> A => B => C => D => E master
>             \ => F => G  foo (base = B)
> 
> foo was created on B, then fast forwarded to C, then diverged.
> 
> 
>     git rebase --onto A  foo@{base}  foo
> 
> Now that foo diverges before B, having B as base for foo seems odd. 
> (Also A will have C' as child, So the base really is A now)

Yes, A is the new base.

>     git rebase --onto E  foo@{base}  foo
> 
> In this case C is already contained in master, so it will be skipped.
> If the base is moved, then foo@{base}..foo will no longer contain C. 
> IMHO that is correct, because rebase skipped it.

The new base is E.

It's not complicated, the base is whatever --onto is.

> Will there be a way to manually repoint the base?
> 
> A => B => C => D master
>        \ => E => F  foo
>                  \ => G => H  bar (base = F)
> 
> 
> If I do
> 
>    git rebase --onto master  bar@{base} bar
> 
> then the commits E and F will not be part of the rebase.
> That is fine. I must handle them before.
> 
> But if I deleted foo (or for other reasons decide E and F should be 
> handled if I rebase bar) can I make them to be included?
> Something like
> 
>    git base --repoint B  bar
> 

I did not code that, but it's something people probably would need at
some point. I would do `git branch --set-base` though.


Anyway, it seems I wasn't very clear, I'm not really proposing this
feature. Although I think it's something that git is missing, it would
be a pain in the ass to attempt to get it merged, I have much more
important features I want to get done, and those don't have much chance
of being merged either.

The only reason I mentioned @{tail} (or @{base}) is to have a better
mental model of what a branch is.

 1. A branch is whatever is inside `branch@{base}..branch`
 2. `branch` is the branch head (`branch@{head}`), but it's not the
    branch itself

For all intents and purposes on the git documentation the branch, the
branch name, and the branch head are used interchangeably, but
semantically speaking they are not the same thing.

When you change the branch head you are effectively changing the branch.
If @{base} existed, then changing the base would also change the branch
(although that would be a much less dangerous operation).

Does that make sense?
Felipe Contreras July 8, 2021, 6:05 p.m. UTC | #25
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Sergey Organov wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
> >> 
> >> > Since this is not strictly related to the topic of `git switch` I
> >> > renamed the thread.
> >> >
> >> > Sergey Organov wrote:
> >> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
> >> >> > Sergey Organov wrote:
> 
> [...]
> 
> >> >> As for branch tail, I do have convention of marking start of a
> >> >> long-standing branch with corresponding tag, where branch "foo" has
> >> >> corresponding "foo-bp" tag marking its "branch point". Recently I
> >> >> started to mark start of feature branch with yet another branch "foo-bp"
> >> >> rather than tag, "foo" being set to track "foo-bp", that allows to
> >> >> automate rebasing of "foo" against correct base.
> >> >
> >> > So foo-bp is the upstream of foo, and you do basically:
> >> >
> >> >   git rebase foo@{upstream}
> >> 
> >> Yep, but essential feature to me is that I in fact use tools that simply
> >> run bare
> >> 
> >>    git rebase
> >> 
> >> and that "just works" (tm).
> >
> > I typed the revision explicitly, but `git rebase` would work just
> > fine.
> 
> Sorry, I don't follow. Did you change semantic of `git rebase`? With
> current mainstream Git, as far as I can tell,
> 
>   git rebase
> 
> essentially is:
> 
>   git rebase --fork-point @{upstream}

More explicitly, it's

  git rebase --onto @{upstream} --fork-point @{upstream}

> How introduction of @{tail} changes this, exactly?

Now --fork-point is not necessary:

  git rebase --onto @{upstream} @{tail}

> >> > This is works if your base (or tail, or whatever) is static, but many
> >> > branches jump around, and that's where @{tail} comes in handy.
> >> 
> >> Yeah, I see. When I need to make a branch jump around, I do need to
> >> manually move my references, but that's fortunately very rare use-case
> >> for me. Having direct support for that is still a win.
> >> 
> >> >
> >> > You can do this:
> >> >
> >> >   git rebase --onto foo@{upstream} foo@{tail}
> >> >
> >> > This will always rebase the right commits (no need to look into the
> >> > reflog). So you can say that the branch is foo@{tail}..foo.
> >> 
> >> I see where and when it's useful, but for a feature branch 99% of times
> >> I don't want to rebase it onto some true upstream. I rather want to just
> >> fiddle with the branch in place, and I prefer to setup things the way
> >> that ensures that bare "git rebase" does "the right thing".
> >
> > But that's precisely the point: when you do `git rebase` you don't have
> > to type the base or --onto anymore. It's done automatically.
> >
> > Not just for your long-standing branches, but for *any* branch.
> >
> >> Probably that could be solved by a branch-local configuration that makes
> >> "git rebase" become "git rebase @{tail}" for the branch instead of "git
> >> rebase @{upstream}"
> >
> > No. @{upstream} is where you want to rebase *to*, @{tail} is where you
> > want to rebase *from*.
> 
> My point is that for feature branch I rather want to rebase from @{tail}
> to @{tail} 99% of times.

Just make @{upstream} = @{tail}, then you get your desired result.

> > When you do:
> >
> >   git rebase foo@{upstream}
> >
> > This is basically the same as:
> >
> >   git checkout foo@{upstream}^0
> >   git cherry-pick --right-only foo@{upstream}...foo
> 
> Yes, but you probably meant foo@{upstream}..foo (2 dots, not 3) here.

I think if you do foo@{upstream}..foo then that --right-only doesn't do
the same thing.

`--right-only foo@{upstream}...foo` will drop commits that already part of
upstream. Another way you can find commits already part of upstream is
with `git cherry foo@{upstream}`.

> > git is smart enough to figure out what commits are already part of
> > foo@{upstream}, and those are skipped, but at no point was any "base"
> > calculated (at least not from `git rebase`).
> >
> > Most of the time `git rebase` works fine, because there aren't too many
> > commits to figure out where they should go, but it's definitely not
> > efficient, and there's many corner-cases (see a Linux kernel maintaner
> > baffled by what the hell `git rebase` is doing [1]).
> 
> Once again, how exactly the foo@{tail} fits in this picture?

It sets <upstream> so no --fork-point is necessary.

> >> > Another advantage of having this notion is that `git rebase`
> >> > automatically updates the tail (in this case to foo@{upstream}).
> >> 
> >> Yep, looks useful. Is it all local to given repo, or else?
> >
> > I implented it as 'refs/tails' (as opposed to 'refs/heads'), so it's
> > local to a given repo, but could easily be exported.
> 
> Do I get it right that now `git switch br1; git rebase --onto br2` will
> likely have different outcome in the repository where "br1" has been
> created compared to any other repository, as "br1@{tail}" will only
> exist in that exact repo?

It very well could, if `--fork-point @{upstream}` finds a different base
than `@{tail}`.

Cheers.
Martin July 8, 2021, 7:21 p.m. UTC | #26
On 08/07/2021 19:33, Felipe Contreras wrote:
> The only reason I mentioned @{tail} (or @{base}) is to have a better
> mental model of what a branch is.
> 
>   1. A branch is whatever is inside `branch@{base}..branch`

For this part "branch" = some series of commits.

Then this is what I would say is a common misunderstanding.

Yet that may be the difference between what people want the branch to 
be, and what it (afaik) technically is.

People indeed tend to thing, I branched at X, so anything before is not 
part of the branch.
"--contains" says otherwise.


Thinking of it.

If I look at a feature branch, then my feature starts where I created 
the branch. I want my feature branch to represent this.

But if I look at my local master branch (or any tracking branch), I like 
to believe that it contains the same as the remote branch.
And well, if we just set the base for the local tracking branch to be 
the same as the base for the remote branch that would be fine.
But if (after diverging, due to changes pulled from remote) then, I run
    git rebase @{base} @{remote}
then rebase has to skip all the shared commits.

And since rebase also repoints the "base", my local branch then no 
longer contains the same as the remote.

So limiting the branch to branch@{base}..branch only works for feature 
branches.


So yes, what is a branch? More exactly what does it contain.
Two examples, that to me suggest two answers.


Also if branch@{base}..branch  then there is a problem.
- branch@{base} is then correctly not part of the branch
- So immediately after "git switch -c branch" the branch is empty => ok
But if so, then what is the branch head at that time?
The Pointer would point the @{base}, but @base is outside the branch. So 
the pointer of the branch points outside the branch?



>   2. `branch` is the branch head (`branch@{head}`), but it's not the
>      branch itself
Well technically "branch" is the "pointer" to the head.
Assuming we want "head" to be a commit?
Or do we want head, to be the "branch end" after the last commit? But 
then still "branch is the pointer"

The only problem is:
branch is too often used for "the commits contained in the branch". That 
is way to common to even try to stop it.

Yet, if branch is used for the content, then we do not have a good term 
for the pointer.




> 
> For all intents and purposes on the git documentation the branch, the
> branch name, and the branch head are used interchangeably, but
> semantically speaking they are not the same thing.

I have not proof read all the docs for this....
But I think that "branch name" and "branch head" should or could be used 
in a clear single meaning fashion each...

> 
> When you change the branch head you are effectively changing the branch.
Well if branch is the pointer, then you change the branch, and head is 
being changed.
If branch is the content, then you change the head, and yes the content 
changes.
Felipe Contreras July 8, 2021, 8:37 p.m. UTC | #27
Martin wrote:
> On 08/07/2021 19:33, Felipe Contreras wrote:
> > The only reason I mentioned @{tail} (or @{base}) is to have a better
> > mental model of what a branch is.
> > 
> >   1. A branch is whatever is inside `branch@{base}..branch`
> 
> For this part "branch" = some series of commits.
> 
> Then this is what I would say is a common misunderstanding.
> 
> Yet that may be the difference between what people want the branch to 
> be, and what it (afaik) technically is.

I'm not talking about what a branch technically is, I'm talking about
what it is semantically.

Technically a branch is a file with an object id in it. That doesn't
give the user any useful information.

What is important is the *meaning* of that file.

> People indeed tend to thing, I branched at X, so anything before is not 
> part of the branch.
> "--contains" says otherwise.

Yes, that is the status quo, but the fact that X is the case doesn't
mean it *should* be the case.

The ideal user interface doesn't need to be explained. The more you need
to explain a concept the less intuitive it is, and the more you should
look for another concept that is perhaps more intuitive.

A branch that you hold, or point to, is a concete concept easy to
underand. When I say: "me, my sister, and my father are one tiny branch
of the Contreras family", people understand what that means inuitively.

On the other hand saying "Felipe contains his great-great-grandfather"
would stop anyone on their tracks.

> Thinking of it.
> 
> If I look at a feature branch, then my feature starts where I created 
> the branch. I want my feature branch to represent this.
> 
> But if I look at my local master branch (or any tracking branch), I like 
> to believe that it contains the same as the remote branch.
> And well, if we just set the base for the local tracking branch to be 
> the same as the base for the remote branch that would be fine.
> But if (after diverging, due to changes pulled from remote) then, I run
>     git rebase @{base} @{remote}
> then rebase has to skip all the shared commits.
> 
> And since rebase also repoints the "base", my local branch then no 
> longer contains the same as the remote.

That is a *very* interesting case that exemplifies the lack of our
current semantic arsenal.

Every time you do a rebase you are in effect creating a new branch with
new commits, a new head, and a new base. The only thing that remains
the same is the name.

It is no longer the same as the remote branch, or an outgrowth; it's
a new branch.

If you send a pull request for your 'master' branch, which then gets
merged to 'origin/master', then you can do `git merge --ff-only` to
advance the head pointer of the 'master' branch to the remote branch so
both are in sync... Except the base won't be the same.

With the current semantics this recreated 'master' is now exactly the
same as the remote 'origin/master'. But not with the @{base} semantics;
since both branches have a different base, they are strictly speaking
different branchs.

But if you do `git reset --hard origin/master`, you are saying: drop
everything about this branch, and make it the same 'origin/master'.
*Now* we have a reason to distinguish `git merge --ff-only` from `git
reset --hard`.

> So limiting the branch to branch@{base}..branch only works for feature 
> branches.
> 
> 
> So yes, what is a branch? More exactly what does it contain.
> Two examples, that to me suggest two answers.

Not necessarily. See above.

> Also if branch@{base}..branch  then there is a problem.
> - branch@{base} is then correctly not part of the branch
> - So immediately after "git switch -c branch" the branch is empty => ok
> But if so, then what is the branch head at that time?
> The Pointer would point the @{base}, but @base is outside the branch. So 
> the pointer of the branch points outside the branch?

Yes, the base pointer doesn't include the branch. When you do
`branch@{base}..branch` that's the same as `^branch@{base} branch` so that
excludes all the commits rechable from branch@{base} *including* that
commit iself.

> >   2. `branch` is the branch head (`branch@{head}`), but it's not the
> >      branch itself
> Well technically "branch" is the "pointer" to the head.
> Assuming we want "head" to be a commit?

No, the branch head is a reference: 'refs/heads/master'. The reference
points to a commit, but it's not the commit itself.

So it's a pointer to a pointer.

> The only problem is:
> branch is too often used for "the commits contained in the branch". That 
> is way to common to even try to stop it.

We don't need to stop it, we can sidestep it.

Instead of talking about the branch, talk about the branch head:
"the brach head is moved to X".

Or if you want to use the branch, don't assume any specifics:
"the branch is recreated to be the same as X".

> > When you change the branch head you are effectively changing the branch.
> Well if branch is the pointer, then you change the branch, and head is 
> being changed.
> If branch is the content, then you change the head, and yes the content 
> changes.

Exactly, so regardless of which semantics you choose, everyone
understands that the branch is not the same anymore.
Martin July 8, 2021, 11:11 p.m. UTC | #28
On 08/07/2021 22:37, Felipe Contreras wrote:
> Technically a branch is a file with an object id in it. That doesn't
> give the user any useful information.
> 
> What is important is the *meaning* of that file.
> 
>> People indeed tend to thing, I branched at X, so anything before is not
>> part of the branch.
>> "--contains" says otherwise.
> 
> Yes, that is the status quo, but the fact that X is the case doesn't
> mean it *should* be the case.

Well yes. So lets start over.

A branch is a container for commits. Those commits have a start (root or 
base / not sure), and an end (head).
The commits are continuous, in that they have no gaps.

The big question is the start point of the branch.

And there is a further consequence:
If a branch "starts" at "base" then
  --contains  needs to be changed
  --reachable needs to be added (for what contains does now)

This also complicates it, because now there are 3 types of relation 
between commits and a branch
- unrelated (outside / not reachable)
- inside (base..head)
- reachable (base and all its parents) // better word needed

The last is important:

A => B => C master
      \ => D  foo

If I delete master, without the concept of reachable, I would expect 
commit A to be dropped. Technically B should drop too, but it takes some 
insight to expect that.
So then with only the branch foo left, I would also have only the commit 
D (well maybe B too, if the system is lenient)

One might even go an say if master is deleted, then the base of foo is 
deleted. since foo must have a base, and it no longer has, foo can not 
exist any longer.

The problem here is that git permits to change history.
If branches could not be rewritten or deleted, then the "base" would be 
a simple concept.
No branch would ever have to look what was before its base.
But as it stands, branches must reach to what was before their base.


> 
> A branch that you hold, or point to, is a concete concept easy to
> underand. When I say: "me, my sister, and my father are one tiny branch
> of the Contreras family", people understand what that means inuitively.
> 
> On the other hand saying "Felipe contains his great-great-grandfather"
> would stop anyone on their tracks.

The Chicago branch of your family contains Al Capone.
That works.

Contains is also nice, because we have 2 boundaries (base/head) to 
enclose the selection.


> But if you do `git reset --hard origin/master`, you are saying: drop
> everything about this branch, and make it the same 'origin/master'.
> *Now* we have a reason to distinguish `git merge --ff-only` from `git
> reset --hard`.

No you don't. IMHO not.
"reset --hard" resets the branch to a commit. You can specify that 
commit by giving a branch-name (that then will be resolved). But it 
could be any commit, even a detached one.

So "reset --hard" has to set the base and the head to the same commit. 
Effectively creating an empty branch based at that commit.

But local tracking branches still are counter intuitive.

IMHO local tracking branches should follow one of the following 
scenarios. (And ideally that should be the same for all local tracking 
branches, for any user.)

1) Always have the same base as their remote branch.
Therefore always have the same content as the remote branch, up to where 
they diverge, if they diverge.

2) Not include the remote branches content. Just hold my local commits, 
until they will be pushed to the remote.

But neither works:

Say I have a local commit, and you pushed new changes to the remote.
    git pull --rebase
My branch is rebased.
So my local tracking branch has its base at the head of the remote. It 
has only local commits => case 1.

Say I have no local commits, and you pushed new changes to the remote.
    git pull --ff-only
If I understand correct the --ff-only move the head of my local branch, 
but leaves the base where it is.
Now I have some shared commits with the remote branch.
=> either case 2, or worse none of the 2 cases.

So, how should local tracking branches behave?


> If you send a pull request for your 'master' branch, which then gets
> merged to 'origin/master', then you can do `git merge --ff-only` to
> advance the head pointer of the 'master' branch to the remote branch so
> both are in sync... Except the base won't be the same.

There may be something I missed. ff should not touch the base?
So the 2 base will still be the same or not the same, depending on if 
they were equal before the ff?


>>
>> So yes, what is a branch? More exactly what does it contain.
>> Two examples, that to me suggest two answers.
> 
> Not necessarily. See above.

I feel we must have some understandingly on the part how base and local 
branches would interact.

You agree: rebase changes the base (it creates a new branch on to --onto)

You pointed out there also is fast-forward. But see my above example.
I am not even doing a pull request. I simply go for you and I both can 
push to the same remote. So we both commit to master and pull/push it.



> 
>> Also if branch@{base}..branch  then there is a problem.
>> - branch@{base} is then correctly not part of the branch
>> - So immediately after "git switch -c branch" the branch is empty => ok
>> But if so, then what is the branch head at that time?
>> The Pointer would point the @{base}, but @base is outside the branch. So
>> the pointer of the branch points outside the branch?
> 
> Yes, the base pointer doesn't include the branch. When you do
> `branch@{base}..branch` that's the same as `^branch@{base} branch` so that
> excludes all the commits rechable from branch@{base} *including* that
> commit iself.

My question is, where you see the branch head pointing to?
If the branch is empty, i.e. if it has no commit at all, then to what 
commit does the branch head point?



>> The only problem is:
>> branch is too often used for "the commits contained in the branch". That
>> is way to common to even try to stop it.
> 
> We don't need to stop it, we can sidestep it.
> 
> Instead of talking about the branch, talk about the branch head:
> "the brach head is moved to X".

Yes well, we need to be very concise, if we speak about anything that is 
not the "commits in the branch".


>>> When you change the branch head you are effectively changing the branch.
>> Well if branch is the pointer, then you change the branch, and head is
>> being changed.
>> If branch is the content, then you change the head, and yes the content
>> changes.
> 
> Exactly, so regardless of which semantics you choose, everyone
> understands that the branch is not the same anymore.
> 

Your original text was
> When you change the branch head you are effectively changing the branch.
> If @{base} existed, then changing the base would also change the branch
> (although that would be a much less dangerous operation).
> 
> Does that make sense?

And yes, if either boundary changes, the branch changed.
Felipe Contreras July 9, 2021, 12:45 a.m. UTC | #29
Martin wrote:
> On 08/07/2021 22:37, Felipe Contreras wrote:
> > Technically a branch is a file with an object id in it. That doesn't
> > give the user any useful information.
> > 
> > What is important is the *meaning* of that file.
> > 
> >> People indeed tend to thing, I branched at X, so anything before is not
> >> part of the branch.
> >> "--contains" says otherwise.
> > 
> > Yes, that is the status quo, but the fact that X is the case doesn't
> > mean it *should* be the case.
> 
> Well yes. So lets start over.
> 
> A branch is a container for commits. Those commits have a start (root or 
> base / not sure), and an end (head).
> The commits are continuous, in that they have no gaps.
> 
> The big question is the start point of the branch.
> 
> And there is a further consequence:
> If a branch "starts" at "base" then
>   --contains  needs to be changed
>   --reachable needs to be added (for what contains does now)

Indeed, but as of this moment @{base} is not being considered, it's just
a mental model tool.

> This also complicates it, because now there are 3 types of relation 
> between commits and a branch
> - unrelated (outside / not reachable)
> - inside (base..head)
> - reachable (base and all its parents) // better word needed

I think that has always been the case. The fact that the git
documentation doesn't talk about that doesn't mean the concept doesn't
exist.

> The last is important:
> 
> A => B => C master
>       \ => D  foo
> 
> If I delete master, without the concept of reachable, I would expect 
> commit A to be dropped. Technically B should drop too, but it takes some 
> insight to expect that.
> So then with only the branch foo left, I would also have only the commit 
> D (well maybe B too, if the system is lenient)

Commits don't need a branch to exist. B could have a tag 0.3.7 and no
branch pointing to it. There could be other refs pointing to that
commit.

> One might even go an say if master is deleted, then the base of foo is 
> deleted. since foo must have a base, and it no longer has, foo can not 
> exist any longer.

Of course it can. The base of a branch doesn't necessarily need to be
part of any other branch.

Or another way to think of it is that B is part of an unnamed branch.

> > A branch that you hold, or point to, is a concete concept easy to
> > underand. When I say: "me, my sister, and my father are one tiny branch
> > of the Contreras family", people understand what that means inuitively.
> > 
> > On the other hand saying "Felipe contains his great-great-grandfather"
> > would stop anyone on their tracks.
> 
> The Chicago branch of your family contains Al Capone.
> That works.

Sure, if you start from a certain grandparent, not if you start from my
grandfather.

Most humans have issue with more than 7 items. A branch containing
millions of members reaching as far back as a fish is a notion an
evolutionary biologist might not have any problem with, but most people
would struggle.

For most people a branch must start from somewhere.

> > But if you do `git reset --hard origin/master`, you are saying: drop
> > everything about this branch, and make it the same 'origin/master'.
> > *Now* we have a reason to distinguish `git merge --ff-only` from `git
> > reset --hard`.
> 
> No you don't. IMHO not.
> "reset --hard" resets the branch to a commit. You can specify that 
> commit by giving a branch-name (that then will be resolved). But it 
> could be any commit, even a detached one.

OK. Sure. It could be repurposed to say what I explained, but we might
be overloading that command in that case.

How about `gt branch --reset <otherbranch>`?

> So "reset --hard" has to set the base and the head to the same commit. 
> Effectively creating an empty branch based at that commit.

Maybe. Or maybe the base remains the same. Fortunately that's not
something we need concern ourselves with at this moment.

> But local tracking branches still are counter intuitive.
> 
> IMHO local tracking branches should follow one of the following 
> scenarios. (And ideally that should be the same for all local tracking 
> branches, for any user.)
> 
> 1) Always have the same base as their remote branch.
> Therefore always have the same content as the remote branch, up to where 
> they diverge, if they diverge.
> 
> 2) Not include the remote branches content. Just hold my local commits, 
> until they will be pushed to the remote.
> 
> But neither works:
> 
> Say I have a local commit, and you pushed new changes to the remote.
>     git pull --rebase
> My branch is rebased.
> So my local tracking branch has its base at the head of the remote. It 
> has only local commits => case 1.
> 
> Say I have no local commits, and you pushed new changes to the remote.
>     git pull --ff-only
> If I understand correct the --ff-only move the head of my local branch, 
> but leaves the base where it is.
> Now I have some shared commits with the remote branch.
> => either case 2, or worse none of the 2 cases.

There's no need for --ff-only, do `git pull --rebase` on both cases, and
the base will constantly be reset to the remote head.

However, at least I never do this. My 'master' branch doesn't contain
any commits and I always do the equivalent of `git pull --ff-only`, so
the base would never change.

> > If you send a pull request for your 'master' branch, which then gets
> > merged to 'origin/master', then you can do `git merge --ff-only` to
> > advance the head pointer of the 'master' branch to the remote branch so
> > both are in sync... Except the base won't be the same.
> 
> There may be something I missed. ff should not touch the base?
> So the 2 base will still be the same or not the same, depending on if 
> they were equal before the ff?

That's right. Before the fast-forward the base was different (because of
the rebase), so after the fast-forward the base remains different.

> >> So yes, what is a branch? More exactly what does it contain.
> >> Two examples, that to me suggest two answers.
> > 
> > Not necessarily. See above.
> 
> I feel we must have some understandingly on the part how base and local 
> branches would interact.
> 
> You agree: rebase changes the base (it creates a new branch on to --onto)
> 
> You pointed out there also is fast-forward. But see my above example.
> I am not even doing a pull request. I simply go for you and I both can 
> push to the same remote. So we both commit to master and pull/push it.

It doesn't matter who does the merge:

  git merge origin/master
  git push

It would be the same as a pull request followed by a fast-forward
(except with the parents reversed).

The base remains unmoved.

> >> Also if branch@{base}..branch  then there is a problem.
> >> - branch@{base} is then correctly not part of the branch
> >> - So immediately after "git switch -c branch" the branch is empty => ok
> >> But if so, then what is the branch head at that time?
> >> The Pointer would point the @{base}, but @base is outside the branch. So
> >> the pointer of the branch points outside the branch?
> > 
> > Yes, the base pointer doesn't include the branch. When you do
> > `branch@{base}..branch` that's the same as `^branch@{base} branch` so that
> > excludes all the commits rechable from branch@{base} *including* that
> > commit iself.
> 
> My question is, where you see the branch head pointing to?
> If the branch is empty, i.e. if it has no commit at all, then to what 
> commit does the branch head point?

To the same commit as the base: master..master contains zero commits.

> >> The only problem is:
> >> branch is too often used for "the commits contained in the branch". That
> >> is way to common to even try to stop it.
> > 
> > We don't need to stop it, we can sidestep it.
> > 
> > Instead of talking about the branch, talk about the branch head:
> > "the brach head is moved to X".
> 
> Yes well, we need to be very concise, if we speak about anything that is 
> not the "commits in the branch".
> 
> 
> >>> When you change the branch head you are effectively changing the branch.
> >> Well if branch is the pointer, then you change the branch, and head is
> >> being changed.
> >> If branch is the content, then you change the head, and yes the content
> >> changes.
> > 
> > Exactly, so regardless of which semantics you choose, everyone
> > understands that the branch is not the same anymore.
> > 
> 
> Your original text was
> > When you change the branch head you are effectively changing the branch.
> > If @{base} existed, then changing the base would also change the branch
> > (although that would be a much less dangerous operation).
> > 
> > Does that make sense?
> 
> And yes, if either boundary changes, the branch changed.

But our immediate concern is to improve the documentation of
`git switch -C`, and perhaps improve the interface while we are at it.

I believe we have all the semantic tools needed to write something that
is understandable by most people regardless of their conception of what a
branch is.

No?
Martin July 9, 2021, 1:24 p.m. UTC | #30
On 09/07/2021 02:45, Felipe Contreras wrote:
> I believe we have all the semantic tools needed to write something that
> is understandable by most people regardless of their conception of what a
> branch is.



While writing a mail on the origin topic (improve docs), I noticed that 
the word "branch-ish" is still free.

Which would be anything that resolves to a "branch reference".

Currently this only is
- branch name.
- branchname@{upstream}

Btw, if branch-foo is tracking a local branch then
    git checkout branch-foo@{upstream}
will switch the the tracked local branch.


* "branch-ish" could be defined as:
Anything that can be resolved to a branch-name.
A branch-name is a reference to the boundary that marks the end of a 
branch.
A branch-ish can be given where a commit-ish is expected. In that case 
it can be resolved to the last commit in the branch.


There may be further need to distinguish between local and remote.

For example
   git checkout [<branch>]
> When the <commit> argument is a branch name, the --detach option can be used to detach HEAD at the tip of the branch (git checkout <branch> would check out that branch without detaching HEAD).

Does not mention that it will also detach, if <branch> is the a remote 
branch name
   git checkout origin/master
Martin July 9, 2021, 2:29 p.m. UTC | #31
On 09/07/2021 02:45, Felipe Contreras wrote:
> I believe we have all the semantic tools needed to write something that
> is understandable by most people regardless of their conception of what a
> branch is.
> 

So returning to the original topic.


While writing this, I thought maybe there is a need for a
"Guideline on writing documentation" ?



On 01/07/2021 16:58, Junio C Hamano proposed a patch that had an 
interesting point.
The patch was for the docs of "git switch" and "git branch"

1)

      <start-point> versus <commit[-ish]>

I am not sure that this will help much with the original issue, which is 
my concern that a (new) user will be aware of why "switch -C" is a force 
(i.e. what the dangers are).
But it is an interesting point.

 From the synopsis of various commands (just a sample, I did not check all).
   git switch (-c|-C) <new-branch> [<start-point>]
   git branch <branchname> [<start-point>]
   git checkout [--detach] <commit>
   git checkout [[-b|-B|--orphan] <new_branch>] [<start_point>]
   git reset [--soft | --mixed | --hard ] [<commit>]

With the exception for "git reset" they all use <start-point> when it 
comes to branches.

The general question here is, should the synopsis say
a) this parameter should be a "commit".
And then the doc explains the commit will be used as startpoint
b) this parameter should be a "start point"
And then the doc explains the startpoint has to be given as commit.

In terms of checkout, this is especially interesting.
The 2nd form does create a new branch.
But both forms check-out the commit.
IMHO it is somewhat strange that you "check out a start-point to your 
worktree".

So probably <commit> (or even <commit-ish>) may indeed be the better option.
This is however an issue that goes well beyond "git switch".

This may also affect other words used in synopsises. So this is a 
general rule that needs to be decided for all of the documentation.
The issue is, that some commands take several commits.
    git rebase [--onto <newbase>] [<upstream> [<branch>]]
In that case some distinguishing is needed.

There also is the option of "<base-commit[-ish]>".
This tells the user that a commit-ish is needed. But distinguishes it 
from other <commit> that may be given as argument.
This may lead to rather long names (e.g. in rebase).
Though in checkout, I would use only <commit[-ish]> in both variants, as 
the main action is to check out that commit.


2)

      <branch> versus <branch-name>

    git switch [--no-guess] <branch>
    git switch (-c|-C) <new-branch> [<start-point>]
    git branch <branchname> [<start-point>]
    git checkout [[-b|-B|--orphan] <new_branch>] [<start_point>]
    git rebase [--onto <newbase>] [<upstream> [<branch>]]

First of all "git rebase" is simply wrong. I can give a commit for all 3 
arguments. So the last one does not have to be a branch. (or <branch-name>)

Then I think <branch-name> (or <branch-ish> /see other mail) should be 
preferred over <branch>.

As for "git switch -C"
This should IMHO change to (the 2nd arg, actually depends on the point 
"1" above)
    git switch (-c|-C) <branch-name> [<base-commit>]

I suggest to not call it "new-branch-name" because, it might be an 
existing name.


3)

    newbbranch  versus new-branch  versus  new_branch

That is something that just needs to be decided.
"new_branch" is in git checkout.


4)

    Extend of explanation for why a command is classified as "force".

This one is the one I still lobby for support.
This is also on issue across all docs. (or most)

Currently "git switch -C" is simply stated to be --force-create.

- There is no mention what is "forced". All it says is:
>  if <new-branch> already exists, it will be reset to <start-point>.
I guess this is the English verb reset. Because, if the user goes to 
"git reset" then the user would not know what kind of reset.
So the term "reset" is ambiguous, as it could be the verb, or the command.

Of course the "git branch" doc has the same
> Reset <branchname> to <startpoint>, even if <branchname> exists already. 


There is also no word, that this does not include overwriting a dirty 
work tree.

   git switch --force -c unused-name origin/branch
means "forcefully overwrite a dirty work tree"

   git switch --force-create unused-name origin/branch
fails on the dirty work tree.


Btw similar on "git checkout"
   git checkout -B unused-name origin/branch
Only difference, -B has no misleading long option.


But my point is less, the not applying danger.
My point is what danger is there, so that this was made a force command?

Look at
   git checkout --force
> --force
>     When switching branches, proceed even if the index or the working tree differs from HEAD. This is used to throw away local changes.

   git switch --force
> --force
>     An alias for --discard-changes.
and then eventually
> This is used to throw away local changes.

So --force clearly says: You will loose local changes (if you have any).

The same clarity is missing for "force create branch".

Yes, sure any commits that where in the branch, may be hold by other 
branches or the ref-log.
But neither is guaranteed. A branch does not need to have a reflog.

Even if we say a user must know about certain concepts (such as a 
branchname is a reference, and non referenced objects may be lost), even 
then the user is left to connect the dots themself.

I think it should be included in the docs (git switch/checkout/branch 
and reset)

The current wording
    Reset <branchname> to <startpoint>, even if
    <branchname> exists already.

should be amended
Avoid "reset"
    Create a new branch at <startpoint> with the name
    <branchname>, even if <branchname> is already used.

Add clarity
    Create a new branch at <startpoint> with the name
    <branchname>.
    If <branchname> already existed, then the old branch
    will be removed.

If the user perceives "the old branch" as container for a "chain of 
commits", then it is still up to the user to know, that any of those 
commits can be part of other branches. And that "removing the branch", 
may or may not include removing the commits.

However, a user not yet knowing what exactly "removing a branch" means, 
does at least have the word "remove" to make him wary that they should 
look up more details.
Felipe Contreras July 9, 2021, 3:08 p.m. UTC | #32
Martin wrote:

> While writing a mail on the origin topic (improve docs), I noticed that 
> the word "branch-ish" is still free.
> 
> Which would be anything that resolves to a "branch reference".
> 
> Currently this only is
> - branch name.
> - branchname@{upstream}

Actually @ and HEAD too.

I don't particularly see much value in that definition since I always
use a committish when I write a branch name, and the fact that
`git switch` expects branches is one of the things that bothers me about
it.

Either way I don't think it makes much sense to do
`git switch branchnae@{upstream}`, and even less `git switch @`.
Martin July 9, 2021, 3:23 p.m. UTC | #33
On 09/07/2021 17:08, Felipe Contreras wrote:
> and the fact that
> `git switch` expects branches is one of the things that bothers me about
> it.

Ah, good point.

I would word it differently though.
"git switch forces the use of --detach if switching to a non branch"

Bit of a twist.
It's a nice safety for beginners. I remember when I started, I kept 
ending up detached. And I had no idea what to do next.


But once you are a bit more experienced the need to add that option can 
be bothersome.
It's not common in my workflow, but I can see that it can be an issue.

So how to remedy?

- Drop the option / Make it default?
- add --allow-detach  and git config switch.detach allow ?

I don't really have a preference.

I think its a nice protection, but even without it, the warning on 
entering detached HEAD state is pretty good.


There is also a curious side effect.

If you went into detached, you can go back to attached using
   git switch -

but not back to detached by again doing
   git switch -

Even though you had been there, and that means you had used --detached, 
and therefore known what you did.
Felipe Contreras July 9, 2021, 4:10 p.m. UTC | #34
Martin wrote:
> On 09/07/2021 02:45, Felipe Contreras wrote:
> > I believe we have all the semantic tools needed to write something that
> > is understandable by most people regardless of their conception of what a
> > branch is.

> On 01/07/2021 16:58, Junio C Hamano proposed a patch that had an 
> interesting point.
> The patch was for the docs of "git switch" and "git branch"
> 
> 1)
> 
>       <start-point> versus <commit[-ish]>
> 
> I am not sure that this will help much with the original issue, which is 
> my concern that a (new) user will be aware of why "switch -C" is a force 
> (i.e. what the dangers are).
> But it is an interesting point.

I don't think it's an improvement. What is that <commitish> used for?
That's what the user wants to know, not to mention that not any commit
works.

>  From the synopsis of various commands (just a sample, I did not check all).
>    git switch (-c|-C) <new-branch> [<start-point>]
>    git branch <branchname> [<start-point>]
>    git checkout [--detach] <commit>
>    git checkout [[-b|-B|--orphan] <new_branch>] [<start_point>]
>    git reset [--soft | --mixed | --hard ] [<commit>]
> 
> With the exception for "git reset" they all use <start-point> when it 
> comes to branches.
> 
> The general question here is, should the synopsis say
> a) this parameter should be a "commit".
> And then the doc explains the commit will be used as startpoint

I'd say no. I think it's pretty obvious what these commands accept as
input, what isn't clear is what that input is for.

> b) this parameter should be a "start point"
> And then the doc explains the startpoint has to be given as commit.

I don't see much value in explaining that has to be given as a commit.
How else would it be given as?

> In terms of checkout, this is especially interesting.
> The 2nd form does create a new branch.

You could say both forms create a new branch, except in the first form
the branch doesn't have a name.

> But both forms check-out the commit.
> IMHO it is somewhat strange that you "check out a start-point to your 
> worktree".
> 
> So probably <commit> (or even <commit-ish>) may indeed be the better option.

But we don't need all the commands to say the same thing, what we need
is something that's easy for the user to understand, and it's accurate.

> This is however an issue that goes well beyond "git switch".

Indeed, but if history is an indication nothing will change (changes in
git's UI rarely do happen), so its better to minimize the possibility
that the patch will be ignored, or straight up rejected.

So it's better to stick with the experimental command and fix that
first.

> This may also affect other words used in synopsises. So this is a 
> general rule that needs to be decided for all of the documentation.
> The issue is, that some commands take several commits.
>     git rebase [--onto <newbase>] [<upstream> [<branch>]]
> In that case some distinguishing is needed.

I'd say it shouldn't matter if it recevies one or several, what that
commit is used for is what matters.

> 2)
> 
>       <branch> versus <branch-name>
> 
>     git switch [--no-guess] <branch>
>     git switch (-c|-C) <new-branch> [<start-point>]
>     git branch <branchname> [<start-point>]
>     git checkout [[-b|-B|--orphan] <new_branch>] [<start_point>]
>     git rebase [--onto <newbase>] [<upstream> [<branch>]]
> 
> First of all "git rebase" is simply wrong. I can give a commit for all 3 
> arguments. So the last one does not have to be a branch. (or <branch-name>)

True. Although in most cases the last one would be a branch.

> Then I think <branch-name> (or <branch-ish> /see other mail) should be 
> preferred over <branch>.

I don't think it makes a difference. A branch name is how you refer to a
branch (what else would be there?).

Differentiating the difference between a branch and a branch name was
done to write better sentences in the description of what the commands
do, but in the synopsis I don't see what we gain.

> As for "git switch -C"
> This should IMHO change to (the 2nd arg, actually depends on the point 
> "1" above)
>     git switch (-c|-C) <branch-name> [<base-commit>]
> 
> I suggest to not call it "new-branch-name" because, it might be an 
> existing name.

I think the name is all wrong. As Ævar pointed out --new (-n) is much
better. Also it doesn't make much sense to use "create" or "new" for
something that already exists.

I think you saw a correct issue: `git switch -C` might be used
incorrectly, but changing to the documentation would have limited value
(and only for the ones that read it).

I think if the branch already exists, the user has to be explicit to
what he wants to do and use `git switch --reset <branch> <commit>`

> 3)
> 
>     newbbranch  versus new-branch  versus  new_branch
> 
> That is something that just needs to be decided.
> "new_branch" is in git checkout.

I'd rather have <branch>, but as I already said, the more ground you try
to cover the more impossible it will be to actually land the changes.

> 4)
> 
>     Extend of explanation for why a command is classified as "force".
> 
> This one is the one I still lobby for support.
> This is also on issue across all docs. (or most)
> 
> Currently "git switch -C" is simply stated to be --force-create.
> 
> - There is no mention what is "forced". All it says is:
> >  if <new-branch> already exists, it will be reset to <start-point>.
> I guess this is the English verb reset. Because, if the user goes to 
> "git reset" then the user would not know what kind of reset.
> So the term "reset" is ambiguous, as it could be the verb, or the command.
> 
> Of course the "git branch" doc has the same
> > Reset <branchname> to <startpoint>, even if <branchname> exists already. 
> 
> 
> There is also no word, that this does not include overwriting a dirty 
> work tree.
> 
>    git switch --force -c unused-name origin/branch
> means "forcefully overwrite a dirty work tree"
> 
>    git switch --force-create unused-name origin/branch
> fails on the dirty work tree.
> 
> 
> Btw similar on "git checkout"
>    git checkout -B unused-name origin/branch
> Only difference, -B has no misleading long option.
> 
> 
> But my point is less, the not applying danger.
> My point is what danger is there, so that this was made a force command?
> 
> Look at
>    git checkout --force
> > --force
> >     When switching branches, proceed even if the index or the working tree differs from HEAD. This is used to throw away local changes.
> 
>    git switch --force
> > --force
> >     An alias for --discard-changes.
> and then eventually
> > This is used to throw away local changes.
> 
> So --force clearly says: You will loose local changes (if you have any).
> 
> The same clarity is missing for "force create branch".
> 
> Yes, sure any commits that where in the branch, may be hold by other 
> branches or the ref-log.
> But neither is guaranteed. A branch does not need to have a reflog.
> 
> Even if we say a user must know about certain concepts (such as a 
> branchname is a reference, and non referenced objects may be lost), even 
> then the user is left to connect the dots themself.
> 
> I think it should be included in the docs (git switch/checkout/branch 
> and reset)
> 
> The current wording
>     Reset <branchname> to <startpoint>, even if
>     <branchname> exists already.
> 
> should be amended
> Avoid "reset"
>     Create a new branch at <startpoint> with the name
>     <branchname>, even if <branchname> is already used.
> 
> Add clarity
>     Create a new branch at <startpoint> with the name
>     <branchname>.
>     If <branchname> already existed, then the old branch
>     will be removed.
> 
> If the user perceives "the old branch" as container for a "chain of 
> commits", then it is still up to the user to know, that any of those 
> commits can be part of other branches. And that "removing the branch", 
> may or may not include removing the commits.
> 
> However, a user not yet knowing what exactly "removing a branch" means, 
> does at least have the word "remove" to make him wary that they should 
> look up more details.

All these issues go away if we have:

  git switch --reset <branch> <commit>

And instead of -C, we have:

  git switch --new --reset <branch> <commit>

This creates a new branch if it doesn't exist, or if it exists resets
it.

Now the documentation writes itself.

Cheers.
Felipe Contreras July 9, 2021, 4:21 p.m. UTC | #35
Martin wrote:
> 
> On 09/07/2021 17:08, Felipe Contreras wrote:
> > and the fact that
> > `git switch` expects branches is one of the things that bothers me about
> > it.
> 
> Ah, good point.
> 
> I would word it differently though.
> "git switch forces the use of --detach if switching to a non branch"
> 
> Bit of a twist.
> It's a nice safety for beginners. I remember when I started, I kept 
> ending up detached. And I had no idea what to do next.

Yes, and that's a good thing, but there's no need to cripple advaned
users.

> But once you are a bit more experienced the need to add that option can 
> be bothersome.
> It's not common in my workflow, but I can see that it can be an issue.
> 
> So how to remedy?
> 
> - Drop the option / Make it default?

No. As you noted it has value for beginners.

> - add --allow-detach  and git config switch.detach allow ?

That's a good option, but another one would be to have a core.advanced
mode, you turn it on if you are an advanced user.

> I don't really have a preference.
> 
> I think its a nice protection, but even without it, the warning on 
> entering detached HEAD state is pretty good.

That warning olny appears with `git checkout`, not with
`git switch --detach`.

> There is also a curious side effect.
> 
> If you went into detached, you can go back to attached using
>    git switch -
> 
> but not back to detached by again doing
>    git switch -
> 
> Even though you had been there, and that means you had used --detached, 
> and therefore known what you did.

That's definitely a bug.
Randall S. Becker July 9, 2021, 4:38 p.m. UTC | #36
On July 9, 2021 12:21 PM, Felipe Contreras wrote:
>Martin wrote:
>>
>> On 09/07/2021 17:08, Felipe Contreras wrote:
>> > and the fact that
>> > `git switch` expects branches is one of the things that bothers me
>> > about it.
>>
>> Ah, good point.
>>
>> I would word it differently though.
>> "git switch forces the use of --detach if switching to a non branch"
>>
>> Bit of a twist.
>> It's a nice safety for beginners. I remember when I started, I kept
>> ending up detached. And I had no idea what to do next.
>
>Yes, and that's a good thing, but there's no need to cripple advaned users.
>
>> But once you are a bit more experienced the need to add that option
>> can be bothersome.
>> It's not common in my workflow, but I can see that it can be an issue.
>>
>> So how to remedy?
>>
>> - Drop the option / Make it default?
>
>No. As you noted it has value for beginners.
>
>> - add --allow-detach  and git config switch.detach allow ?
>
>That's a good option, but another one would be to have a core.advanced mode, you turn it on if you are an advanced user.
>
>> I don't really have a preference.
>>
>> I think its a nice protection, but even without it, the warning on
>> entering detached HEAD state is pretty good.
>
>That warning olny appears with `git checkout`, not with `git switch --detach`.
>
>> There is also a curious side effect.
>>
>> If you went into detached, you can go back to attached using
>>    git switch -
>>
>> but not back to detached by again doing
>>    git switch -
>>
>> Even though you had been there, and that means you had used
>> --detached, and therefore known what you did.
>
>That's definitely a bug.

In all of this discussion, please be aware that many CI/CD systems use sparse checkout and detached heads as a matter of efficiency and certainty. Please ensure that you are not changing the semantics of existing capabilities when restricting what `git switch` will do. I am concerned about the 280,342 (as of this minute) current Jenkins users who depend on this.

Thanks,
Randall
Martin July 9, 2021, 4:51 p.m. UTC | #37
On 09/07/2021 18:10, Felipe Contreras wrote:
> Martin wrote:
>> As for "git switch -C"
>> This should IMHO change to (the 2nd arg, actually depends on the point
>> "1" above)
>>      git switch (-c|-C) <branch-name> [<base-commit>]
>>
>> I suggest to not call it "new-branch-name" because, it might be an
>> existing name.
> 
> I think the name is all wrong. As Ævar pointed out --new (-n) is much
> better. Also it doesn't make much sense to use "create" or "new" for
> something that already exists.

The n versus c issue is IMHO separate. Maybe tiny overlaps.

I see it mostly in the light of -c should be for "copy".

On "git checkout" it is "-b" for branch. That works, if you perceive 
"branch" as a verb. "The action of branching creates a new branch".

If needs must, that would work as "git switch -b" to.

Actually, "new" or "create" would make sense in "git branch". But in git 
switch, they actually raise the question "create what?" / "new what?".


> 
> I think you saw a correct issue: `git switch -C` might be used
> incorrectly, but changing to the documentation would have limited value
> (and only for the ones that read it).
> 
> I think if the branch already exists, the user has to be explicit to
> what he wants to do and use `git switch --reset <branch> <commit>`

Well, that is the question as what the action is perceived.
I think the example is wrong, rather than the command.

-c / -C /-n / -N always *c*reate an *n*ew branch. (create and new really 
are the same thing here)

But if the branch name Foo, is already used?
Well, it will still be a *new* branch being *created*.
To do that it has to remove the name from the old branch. (effectively 
removing the old branch).


>> 3)
>>
>>      newbbranch  versus new-branch  versus  new_branch
>>
>> That is something that just needs to be decided.
>> "new_branch" is in git checkout.
> 
> I'd rather have <branch>, but as I already said, the more ground you try
> to cover the more impossible it will be to actually land the changes.

Well ok, if you shorten it to one word that solves it too.
But for anything that for some reason needs two words, IMHO there should 
be one style. "one word", "-" or "_".
Currently different styles are mixed.


>>
>> Look at
>>     git checkout --force
>>> --force
>>>      When switching branches, proceed even if the index or the working tree differs from HEAD. This is used to throw away local changes.
>>
> 
> All these issues go away if we have:
> 
>    git switch --reset <branch> <commit>
> 
> And instead of -C, we have:
> 
>    git switch --new --reset <branch> <commit>
> 
> This creates a new branch if it doesn't exist, or if it exists resets
> it.

Nope it does not go away.

All this has done, is that it no longer is a "force" command.
So the last bit of warning has just gone.

And it still needs to be documented inside the "git switch" doc, rather 
than forwarding the user do yet another doc.

Also making the user read the "git reset" doc does not help, unless we 
point out that this is a --hard reset, rather than "modifying the index".

I would on that account argue that "git reset --hard/mixed/soft" should 
be "force" commands.

And the "git reset" documentation, as well as "git branch -f" / git 
checkout -B", also miss the information why they are "force".
It is true, this information can be derived, if one
- knows the concepts (which one should do)
- and actually connects the dots (humans do have a tendency to overlook 
things, especially if they are only indirectly referred to)

So, I still ask:
- If "--force" to overwrite the work tree can clearly state that change 
to files will be "thrown away".
- Then why can "force" re-using an existing branch name not do the same?

And that is the same, never mind if we call it -C, -B or --reset.
Martin July 9, 2021, 4:54 p.m. UTC | #38
On 09/07/2021 18:21, Felipe Contreras wrote:
> Martin wrote:
>> - add --allow-detach  and git config switch.detach allow ?
> 
> That's a good option, but another one would be to have a core.advanced
> mode, you turn it on if you are an advanced user.

+1
Felipe Contreras July 9, 2021, 5:10 p.m. UTC | #39
Randall S. Becker wrote:
> In all of this discussion, please be aware that many CI/CD systems use
> sparse checkout and detached heads as a matter of efficiency and
> certainty. Please ensure that you are not changing the semantics of
> existing capabilities when restricting what `git switch` will do. I am
> concerned about the 280,342 (as of this minute) current Jenkins users
> who depend on this.

I doubt 280,342 Jenkins users depend on `git switch`.

And `git help switch`:

  THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
Felipe Contreras July 9, 2021, 5:41 p.m. UTC | #40
Martin wrote:
> On 09/07/2021 18:10, Felipe Contreras wrote:
> > Martin wrote:
> >> As for "git switch -C"
> >> This should IMHO change to (the 2nd arg, actually depends on the point
> >> "1" above)
> >>      git switch (-c|-C) <branch-name> [<base-commit>]
> >>
> >> I suggest to not call it "new-branch-name" because, it might be an
> >> existing name.
> > 
> > I think the name is all wrong. As Ævar pointed out --new (-n) is much
> > better. Also it doesn't make much sense to use "create" or "new" for
> > something that already exists.
> 
> The n versus c issue is IMHO separate. Maybe tiny overlaps.
> 
> I see it mostly in the light of -c should be for "copy".
> 
> On "git checkout" it is "-b" for branch. That works, if you perceive 
> "branch" as a verb. "The action of branching creates a new branch".

I generally view git commands as verbs. In this case "checkout" is the
verb, and "branch" is the direct object.

> Actually, "new" or "create" would make sense in "git branch". But in git 
> switch, they actually raise the question "create what?" / "new what?".

`git switch` doesn't switch anything other branches. I don't think
`git switch-branch` would make the command somehow more understendale.

> > I think you saw a correct issue: `git switch -C` might be used
> > incorrectly, but changing to the documentation would have limited value
> > (and only for the ones that read it).
> > 
> > I think if the branch already exists, the user has to be explicit to
> > what he wants to do and use `git switch --reset <branch> <commit>`
> 
> Well, that is the question as what the action is perceived.
> I think the example is wrong, rather than the command.
> 
> -c / -C /-n / -N always *c*reate an *n*ew branch. (create and new really 
> are the same thing here)
> 
> But if the branch name Foo, is already used?
> Well, it will still be a *new* branch being *created*.
> To do that it has to remove the name from the old branch. (effectively 
> removing the old branch).

But it's not removing the name, it's merely changing the head.

I don't particularly mind having -C or -N, I just would not use them
because I like to be explicit. I don't use --new for something that
already exists.

> >> 3)
> >>
> >>      newbbranch  versus new-branch  versus  new_branch
> >>
> >> That is something that just needs to be decided.
> >> "new_branch" is in git checkout.
> > 
> > I'd rather have <branch>, but as I already said, the more ground you try
> > to cover the more impossible it will be to actually land the changes.
> 
> Well ok, if you shorten it to one word that solves it too.
> But for anything that for some reason needs two words, IMHO there should 
> be one style. "one word", "-" or "_".
> Currently different styles are mixed.

I don't see the need for that, <new branch> would do the trick, no need
for hyphens or underscores.

> >> Look at
> >>     git checkout --force
> >>> --force
> >>>      When switching branches, proceed even if the index or the working tree differs from HEAD. This is used to throw away local changes.
> >>
> > 
> > All these issues go away if we have:
> > 
> >    git switch --reset <branch> <commit>
> > 
> > And instead of -C, we have:
> > 
> >    git switch --new --reset <branch> <commit>
> > 
> > This creates a new branch if it doesn't exist, or if it exists resets
> > it.
> 
> Nope it does not go away.
> 
> All this has done, is that it no longer is a "force" command.
> So the last bit of warning has just gone.
> 
> And it still needs to be documented inside the "git switch" doc, rather 
> than forwarding the user do yet another doc.

Yes, but as I said: the documentation writes itself.

  -n <branch>, --new <branch>

    Creates a new branch.

  --reset <branch>

    Resets the branch to <head>.

> Also making the user read the "git reset" doc does not help, unless we 
> point out that this is a --hard reset, rather than "modifying the index".

Nobody is suggesting that. --reset refers to the English word "reset",
not `get reset`.

> So, I still ask:
> - If "--force" to overwrite the work tree can clearly state that change 
> to files will be "thrown away".
> - Then why can "force" re-using an existing branch name not do the same?

Because we would be forcing two things now. I'd rather not overload
concepts.

Cheers.
Martin July 9, 2021, 6:23 p.m. UTC | #41
On 09/07/2021 19:41, Felipe Contreras wrote:
> Martin wrote:
>> Well, that is the question as what the action is perceived.
>> I think the example is wrong, rather than the command.
>>
>> -c / -C /-n / -N always *c*reate an *n*ew branch. (create and new really
>> are the same thing here)
>>
>> But if the branch name Foo, is already used?
>> Well, it will still be a *new* branch being *created*.
>> To do that it has to remove the name from the old branch. (effectively
>> removing the old branch).
> 
> But it's not removing the name, it's merely changing the head.
> 
> I don't particularly mind having -C or -N, I just would not use them
> because I like to be explicit. I don't use --new for something that
> already exists.

But that comes down to the "what is a branch" discussion.

It is not creating a new branchname. But it is creating a new branch. 
And then the branchname refers to that new branch.

It changes head, base, and the entire content. That effectively makes it 
new.

If you have a 10 year old car that you nicknamed "speedy", and I come 
along and I replace every part (every screw, every whatever...) with a 
brand new part, would you still call the result a 10 year old car (even 
if (or just because) you still use the nickname) ?


Using "reset", it's similar. Except that human language is slopy.
If I play WOW, and I reset the game. Actually that is already wrong. I 
do not reset the game. It is still the same code, the same images.... I 
do reset my session or status. And after that, I will be in a new 
session, or have a new status.

- "creating" the branch is "setting (up) the branch"
- "re-setting" is doing doing this (creation) again.


>> Nope it does not go away.
>>
>> All this has done, is that it no longer is a "force" command.
>> So the last bit of warning has just gone.
>>
>> And it still needs to be documented inside the "git switch" doc, rather
>> than forwarding the user do yet another doc.
> 
> Yes, but as I said: the documentation writes itself.
> 
>    -n <branch>, --new <branch>
> 
>      Creates a new branch.
> 
>    --reset <branch>
> 
>      Resets the branch to <head>.

And that still leaves it to the user to connect the dots, and come to 
the conclusion that the old branch is no longer holding his valued commits.

We don't ask the user to go make this sort of "connecting the dots", 
when he uses force to override changes in his worktree.

Why?



>> So, I still ask:
>> - If "--force" to overwrite the work tree can clearly state that change
>> to files will be "thrown away".
>> - Then why can "force" re-using an existing branch name not do the same?
> 
> Because we would be forcing two things now. 

Which 2 things?

The worktree overwriting is *not* forced by -C

   git switch -C b1 b2
   git checkout -B b1 b2

both give an error if the worktree has changed files.

This is only about what happens to the branch.

I.e we force the branchname to point to our new branch.
And that means the branchname no longe points to the old branch, and the 
old branch therefore is removed.



> I'd rather not overload
> concepts.
> 
Sorry the concepts are there by whatever the implementation does.

Documenting them does not overload concepts. If they indeed already are 
overloaded, then documentation does not change that.

Btw, not sure what is overloaded here?
Sergey Organov July 10, 2021, 10:08 a.m. UTC | #42
Martin <git@mfriebe.de> writes:

> On 09/07/2021 17:08, Felipe Contreras wrote:
>> and the fact that
>> `git switch` expects branches is one of the things that bothers me about
>> it.
>
> Ah, good point.
>
> I would word it differently though.
> "git switch forces the use of --detach if switching to a non branch"
>
> Bit of a twist.
> It's a nice safety for beginners. I remember when I started, I kept
> ending up detached. And I had no idea what to do next.

I think it's more because of too technical and thus confusing name for
it rather than the state itself. In fact this could be described as
"being on unnamed branch", as if HEAD points to a branch with empty
name, and is not detached in any sense.

It's nice that once you are on unnamed branch, nothing actually changes,
so no any mental shift is needed to get out of this "state". BTW,
unnamed branch could probably even start to have entries in the reflog.

Overall, I think Git needs to move into direction of getting rid of
"detached head" in favor of "unnamed branch" at least at the UI level.

Getting back to "git switch", if the above sounds reasonable, "--detach"
is a bad choice for the option name in the first place.

Thanks,
Sergey Organov July 10, 2021, 10:24 a.m. UTC | #43
Martin <git@mfriebe.de> writes:

> On 09/07/2021 18:10, Felipe Contreras wrote:
>> Martin wrote:
>>> As for "git switch -C"
>>> This should IMHO change to (the 2nd arg, actually depends on the point
>>> "1" above)
>>>      git switch (-c|-C) <branch-name> [<base-commit>]
>>>
>>> I suggest to not call it "new-branch-name" because, it might be an
>>> existing name.
>> I think the name is all wrong. As Ævar pointed out --new (-n) is much
>> better. Also it doesn't make much sense to use "create" or "new" for
>> something that already exists.
>
> The n versus c issue is IMHO separate. Maybe tiny overlaps.
>
> I see it mostly in the light of -c should be for "copy".
>
> On "git checkout" it is "-b" for branch. That works, if you perceive
> "branch" as a verb. "The action of branching creates a new branch".
>
> If needs must, that would work as "git switch -b" to.
>
> Actually, "new" or "create" would make sense in "git branch". But in
> git switch, they actually raise the question "create what?" / "new
> what?".

I believe that's because "git switch" tries to do too much. "git switch"
should rather switch between existing branches, and do nothing else. As
I said once in this discussion already: trouble writing good
documentation is often indication of some flaws in the design.

Creating (a branch) is fundamentally different operation than switching
to (a branch), and that's why the former doesn't fit into "git switch".

Thanks,
Bagas Sanjaya July 10, 2021, 10:37 a.m. UTC | #44
On 10/07/21 17.24, Sergey Organov wrote:
> I believe that's because "git switch" tries to do too much. "git switch"
> should rather switch between existing branches, and do nothing else. As
> I said once in this discussion already: trouble writing good
> documentation is often indication of some flaws in the design.
> 
> Creating (a branch) is fundamentally different operation than switching
> to (a branch), and that's why the former doesn't fit into "git switch".
> 

So I prefer your suggestion. Also make `git switch` also switches tags 
or random commits (like `git checkout <tag>` and `git checkout <commit>`).
Martin July 10, 2021, 11:05 a.m. UTC | #45
On 10/07/2021 12:24, Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
>> Actually, "new" or "create" would make sense in "git branch". But in
>> git switch, they actually raise the question "create what?" / "new
>> what?".
> 
> I believe that's because "git switch" tries to do too much. "git switch"
> should rather switch between existing branches, and do nothing else. As
> I said once in this discussion already: trouble writing good
> documentation is often indication of some flaws in the design.
> 
> Creating (a branch) is fundamentally different operation than switching
> to (a branch), and that's why the former doesn't fit into "git switch".
> 

Right, yes. But creating a branch is often followed by switching to it.

So this is A shortcuts, that I actually think to be fine.
It does add value, as it does speed up a common operation.

Of course you could have
    git create-switch
or
    git branch-switch

I am not sure, that is really an improvement.



There is even discussion to add "-c" for  "copy branch + switch" to git 
switch.
Which I have no personal objection. Only find it regrettable that it 
means an incompatible change to -c. (Never mind that git switch is still 
"experimental". It has been so for a long time, for many people out 
there long enough to forget the "experimental")

And there is even discussion to add "-m" move/rename, to git switch.
Only that for the latter, most people would not even perceive a rename 
as doing a switch/checkout (technically the branchname in HEAD is 
updated, I guess).
So technically
    git branch -m newname
should change the branchname, but NOT update HEAD (detach)?
(Not sure what it does / not tested)
If git branch actually updates HEAD in that case, then "git switch -m" 
would be an identical copy, adding no value, therefore not required.
Sergey Organov July 10, 2021, 4:32 p.m. UTC | #46
Martin <git@mfriebe.de> writes:

> On 10/07/2021 12:24, Sergey Organov wrote:
>> Martin <git@mfriebe.de> writes:
>>> Actually, "new" or "create" would make sense in "git branch". But in
>>> git switch, they actually raise the question "create what?" / "new
>>> what?".
>> I believe that's because "git switch" tries to do too much. "git switch"
>> should rather switch between existing branches, and do nothing else. As
>> I said once in this discussion already: trouble writing good
>> documentation is often indication of some flaws in the design.
>> Creating (a branch) is fundamentally different operation than switching
>> to (a branch), and that's why the former doesn't fit into "git switch".
>> 
>
> Right, yes. But creating a branch is often followed by switching to it.

Yep, but here the creation is the primary operation, not switching, so
putting this into "git switch" looks like design flaw. These 2 actions
are fine to co-exist in "git branch" = "whatever you want to do to
branches", but not in "git switch" == "wherever you want to switch".

Logically, there could be something like "git new" that does create a
branch and then switches there by default, or something like that, say:

   git new feature3 --at origin/rc-2 --track
 
And while we are at it, do you guys notice how 2 concepts are mixed in
Git commands? I mean, the interface seems to mix object-oriented and
action-oriented commands, most of commands being action-oriented with
only a few unfortunate exceptions.

Let me try a short survey:

1. In

  git branch ...

is "branch" a noun or a verb?

2. In

  git merge ...

is "merge" a noun or a verb?

To me, while the latter is obvious, it's verb and specifies the action
to be performed, the former looks more like "whatever you want to do
with branches", and thus the "branch" is a noun there and the command
thus is object-oriented.

From this POV, to me specifically these 3 commands:

  git branch
  git tag
  git sparse-checkout

look like exceptions which should be eventually obsoleted after their
features are moved elsewhere, provided Git community is interested in
regularizing Git interfaces.

Thanks,
Felipe Contreras July 10, 2021, 7:18 p.m. UTC | #47
Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
> 
> > On 09/07/2021 17:08, Felipe Contreras wrote:
> >> and the fact that
> >> `git switch` expects branches is one of the things that bothers me about
> >> it.
> >
> > Ah, good point.
> >
> > I would word it differently though.
> > "git switch forces the use of --detach if switching to a non branch"
> >
> > Bit of a twist.
> > It's a nice safety for beginners. I remember when I started, I kept
> > ending up detached. And I had no idea what to do next.
> 
> I think it's more because of too technical and thus confusing name for
> it rather than the state itself. In fact this could be described as
> "being on unnamed branch", as if HEAD points to a branch with empty
> name, and is not detached in any sense.
> 
> It's nice that once you are on unnamed branch, nothing actually changes,
> so no any mental shift is needed to get out of this "state". BTW,
> unnamed branch could probably even start to have entries in the reflog.
> 
> Overall, I think Git needs to move into direction of getting rid of
> "detached head" in favor of "unnamed branch" at least at the UI level.

I agree. But UI changes in git are pretty much impossible (although not
100%).

> Getting back to "git switch", if the above sounds reasonable, "--detach"
> is a bad choice for the option name in the first place.

True. Maybe --unamed.
Felipe Contreras July 10, 2021, 7:45 p.m. UTC | #48
Martin wrote:
> On 09/07/2021 19:41, Felipe Contreras wrote:
> > Martin wrote:
> >> Well, that is the question as what the action is perceived.
> >> I think the example is wrong, rather than the command.
> >>
> >> -c / -C /-n / -N always *c*reate an *n*ew branch. (create and new really
> >> are the same thing here)
> >>
> >> But if the branch name Foo, is already used?
> >> Well, it will still be a *new* branch being *created*.
> >> To do that it has to remove the name from the old branch. (effectively
> >> removing the old branch).
> > 
> > But it's not removing the name, it's merely changing the head.
> > 
> > I don't particularly mind having -C or -N, I just would not use them
> > because I like to be explicit. I don't use --new for something that
> > already exists.
> 
> But that comes down to the "what is a branch" discussion.
> 
> It is not creating a new branchname. But it is creating a new branch. 
> And then the branchname refers to that new branch.
> 
> It changes head, base, and the entire content. That effectively makes it 
> new.

Yes, it is a new branch, but the name doesn't change.

> If you have a 10 year old car that you nicknamed "speedy", and I come 
> along and I replace every part (every screw, every whatever...) with a 
> brand new part, would you still call the result a 10 year old car (even 
> if (or just because) you still use the nickname) ?

Yeah but you are entering into metaphysics of identity, see the Ship of
Theseus [1]. By that same logic why are you still called Martin if every
cell in your body wasn't there when you were originally born?

These thought experiments are interesting, but philosphers have discused
about this for thousands of years and the conclussion is still
undecided, so I don't think we'll come to a conclussion here.

Moreover, I don't even think it's relevant. We agree that the branch is
a different branch, we agree that the name doesn't change, and we agree
that the user doesn't want the name to change. We don't need to enter
into a philosophical discussion to see if the name *should* change.

> Using "reset", it's similar. Except that human language is slopy.
> If I play WOW, and I reset the game. Actually that is already wrong. I 
> do not reset the game. It is still the same code, the same images.... I 
> do reset my session or status. And after that, I will be in a new 
> session, or have a new status.

Words mean whatever humans using those words intend them to mean. If
most people use the word "reset" in a certin way, that's what the word
means. Even if you have a good ontological reason why reset shouldn't be
used like that, it's used like that.

> - "creating" the branch is "setting (up) the branch"
> - "re-setting" is doing doing this (creation) again.

Resetting is not necesarilly creating again, it can mean setting up
again.

> >> Nope it does not go away.
> >>
> >> All this has done, is that it no longer is a "force" command.
> >> So the last bit of warning has just gone.
> >>
> >> And it still needs to be documented inside the "git switch" doc, rather
> >> than forwarding the user do yet another doc.
> > 
> > Yes, but as I said: the documentation writes itself.
> > 
> >    -n <branch>, --new <branch>
> > 
> >      Creates a new branch.
> > 
> >    --reset <branch>
> > 
> >      Resets the branch to <head>.
> 
> And that still leaves it to the user to connect the dots, and come to 
> the conclusion that the old branch is no longer holding his valued commits.

No. You can add all the explanation you want after "Resets the branch to
<head>.", but most of that explanation would be redundant, because as we
already agreed, there's no way to reset the head of a branch without
changing the branch.

> >> So, I still ask:
> >> - If "--force" to overwrite the work tree can clearly state that change
> >> to files will be "thrown away".
> >> - Then why can "force" re-using an existing branch name not do the same?
> > 
> > Because we would be forcing two things now. 
> 
> Which 2 things?
> 
> The worktree overwriting is *not* forced by -C
> 
>    git switch -C b1 b2
>    git checkout -B b1 b2
> 
> both give an error if the worktree has changed files.
> 
> This is only about what happens to the branch.
> 
> I.e we force the branchname to point to our new branch.
> And that means the branchname no longe points to the old branch, and the 
> old branch therefore is removed.

It seems your proposal is to make `git switch -c --force b1 b2` be the same as
`git switch -C b1 b2`, but that would also make it the same as
`git switch -C --force b1 b2`. Therefore it would be forcing two things.

Or is your proposal something else?

[1] https://en.wikipedia.org/wiki/Ship_of_Theseus
Felipe Contreras July 10, 2021, 7:51 p.m. UTC | #49
Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
> 
> > On 09/07/2021 18:10, Felipe Contreras wrote:
> >> Martin wrote:
> >>> As for "git switch -C"
> >>> This should IMHO change to (the 2nd arg, actually depends on the point
> >>> "1" above)
> >>>      git switch (-c|-C) <branch-name> [<base-commit>]
> >>>
> >>> I suggest to not call it "new-branch-name" because, it might be an
> >>> existing name.
> >> I think the name is all wrong. As Ævar pointed out --new (-n) is much
> >> better. Also it doesn't make much sense to use "create" or "new" for
> >> something that already exists.
> >
> > The n versus c issue is IMHO separate. Maybe tiny overlaps.
> >
> > I see it mostly in the light of -c should be for "copy".
> >
> > On "git checkout" it is "-b" for branch. That works, if you perceive
> > "branch" as a verb. "The action of branching creates a new branch".
> >
> > If needs must, that would work as "git switch -b" to.
> >
> > Actually, "new" or "create" would make sense in "git branch". But in
> > git switch, they actually raise the question "create what?" / "new
> > what?".
> 
> I believe that's because "git switch" tries to do too much. "git switch"
> should rather switch between existing branches, and do nothing else.

I don't know if it's trying to do too much. I know `git checkout` is
trying to do too much, and I've been trying to use `git switch` instead
for a while. I often create branches and switch to them using
`git switch -c` (which I think should be `git switch -n`).

In my mind it's "switch to a new branch".

So, how would I do this operation (create a new branch and switch to
it), without using `git checkout` or `git switch -c`?

> As I said once in this discussion already: trouble writing good
> documentation is often indication of some flaws in the design.

Completely agree. But I believe the difficulty is in the semantics of
what a branch means in git, not anything to do with `git switch` per se.

> Creating (a branch) is fundamentally different operation than switching
> to (a branch), and that's why the former doesn't fit into "git switch".

Not in my mind. Instead of switching to an existing branch, I'm switching
to a new branch, which is easily understood by
`git switch --new branch`.
Felipe Contreras July 10, 2021, 8 p.m. UTC | #50
Martin wrote:
> There is even discussion to add "-c" for  "copy branch + switch" to git 
> switch.
> Which I have no personal objection. Only find it regrettable that it 
> means an incompatible change to -c. (Never mind that git switch is still 
> "experimental". It has been so for a long time, for many people out 
> there long enough to forget the "experimental")

This is relative.

`git switch` has existed for 1.9 years. I've been using git for about 15
years, so that's 13% of the time (although I've been using it even less
time than that). I understand that for more recent users this might seem
like a long time, but it isn't.

Git UI development is dead slow.
Martin July 10, 2021, 8:07 p.m. UTC | #51
On 10/07/2021 21:45, Felipe Contreras wrote:
> Martin wrote:
> No. You can add all the explanation you want after "Resets the branch to
> <head>.", but most of that explanation would be redundant, because as we
> already agreed, there's no way to reset the head of a branch without
> changing the branch.

By that logic a lot of explanations are redundant, because on some 
lever, if every user thinks far enough lots of things can be concluded.

 From the docs (and similar on git checkout)
> --force
> 
>     An alias for --discard-changes.
> --discard-changes
> 
>     Proceed even if the index or the working tree differs from HEAD.
> Both the index and working tree are restored to match the switching 
> target. If --recurse-submodules is specified, submodule content is 
> also restored to match the switching target. This is used to throw
> away local changes.

If the working tree is made to match the target, then it can not retain 
local changes. That can be concluded.
Yet, it is explicitly mentioned.

Does it really hurt to mention it?
People overlook details that to others are blaring obvious.
I agree, we can not mention every potential possibility. But as a 
general rule, if data could be lost, then a mention (an explicit 
mention) should be made.

Yes, commits may be hold by the reflog. Except the reflog is optional. 
And more to the point, the reflog is unknown to plenty of people (never 
mind if they should know it, they do not) So the possibility of loss is 
rather real.

But anyway.
I brought forward my idea. I explained my reasoning.
If it (this part) is downvoted/rejected then that it how it is.


There still is the idea to replace the word "branch" by "branch name" in 
some parts of the git switch documentation.



>>>> So, I still ask:
>>>> - If "--force" to overwrite the work tree can clearly state that change
>>>> to files will be "thrown away".
>>>> - Then why can "force" re-using an existing branch name not do the same?
>>>
>>> Because we would be forcing two things now.
>>
>> Which 2 things?
>>
>> The worktree overwriting is *not* forced by -C
>>
>>     git switch -C b1 b2
>>     git checkout -B b1 b2
>>
>> both give an error if the worktree has changed files.
>>
>> This is only about what happens to the branch.
>>
>> I.e we force the branchname to point to our new branch.
>> And that means the branchname no longe points to the old branch, and the
>> old branch therefore is removed.
> 
> It seems your proposal is to make `git switch -c --force b1 b2` be the same as
> `git switch -C b1 b2`, but that would also make it the same as
> `git switch -C --force b1 b2`. Therefore it would be forcing two things.
> 
> Or is your proposal something else?
> 

No. I definitely want to keep those 2 apart from each other.

For each force-needing action, you should have to specify it's own force 
flag.

I do not want to change the behaviour on that part.

I only compared the
- doc of "-f" for worktree overwrites
with the
- doc -C for branch overwrites.

And I found that the former makes explicit mention of what can be lost, 
the latter leaves it to be concluded.
Felipe Contreras July 10, 2021, 8:12 p.m. UTC | #52
Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
> 
> > On 10/07/2021 12:24, Sergey Organov wrote:
> >> Martin <git@mfriebe.de> writes:
> >>> Actually, "new" or "create" would make sense in "git branch". But in
> >>> git switch, they actually raise the question "create what?" / "new
> >>> what?".
> >> I believe that's because "git switch" tries to do too much. "git switch"
> >> should rather switch between existing branches, and do nothing else. As
> >> I said once in this discussion already: trouble writing good
> >> documentation is often indication of some flaws in the design.
> >> Creating (a branch) is fundamentally different operation than switching
> >> to (a branch), and that's why the former doesn't fit into "git switch".
> >> 
> >
> > Right, yes. But creating a branch is often followed by switching to it.
> 
> Yep, but here the creation is the primary operation, not switching, so
> putting this into "git switch" looks like design flaw. These 2 actions
> are fine to co-exist in "git branch" = "whatever you want to do to
> branches", but not in "git switch" == "wherever you want to switch".

I don't see the logic in here.

  git branch topic # here 'branch' is the verb
  git switch topic # here 'switch' is the verb

Now, if you want to do both at the same time the logical options are:

  git branch --switch topic # here '--switch' is an adverb
  git switch --new topic # here '--new' is an adverb

The former reads like gibberish to me: "git, branch off in a 'switch'
way".

The latter makes perfect sense: "git, switch to a branch in a 'new' way".

> Logically, there could be something like "git new" that does create a
> branch and then switches there by default, or something like that, say:
> 
>    git new feature3 --at origin/rc-2 --track

Here the the verb is clear, but not the direct object, a "new" what?
Couldn't it be a tag? Or a commit? Or a remote? Or a worktree? Or a
bisect? Or a submodule?

It's too ambigous.

> And while we are at it, do you guys notice how 2 concepts are mixed in
> Git commands? I mean, the interface seems to mix object-oriented and
> action-oriented commands, most of commands being action-oriented with
> only a few unfortunate exceptions.
> 
> Let me try a short survey:
> 
> 1. In
> 
>   git branch ...
> 
> is "branch" a noun or a verb?

Both.

> 2. In
> 
>   git merge ...
> 
> is "merge" a noun or a verb?

Verb.

> To me, while the latter is obvious, it's verb and specifies the action
> to be performed, the former looks more like "whatever you want to do
> with branches", and thus the "branch" is a noun there and the command
> thus is object-oriented.

I agree, and I did have indeed noticed the inconsistency. But there's
another category of commands that receive subcommands, like:

  git remote $subcommand
  git worktree $subcommand
  git bisect $subcommand

In my opinion `git branch` fits more these subcommand commands, and it
was a mistake to make the subcommands options, it should be:

  git branch list
  git branch new
  git branch set-upstream
  git branch move
  ...

Now the verb is crystal-clear.
Felipe Contreras July 10, 2021, 8:49 p.m. UTC | #53
Martin wrote:
> On 10/07/2021 21:45, Felipe Contreras wrote:
> > Martin wrote:
> > No. You can add all the explanation you want after "Resets the branch to
> > <head>.", but most of that explanation would be redundant, because as we
> > already agreed, there's no way to reset the head of a branch without
> > changing the branch.
> 
> By that logic a lot of explanations are redundant, because on some 
> lever, if every user thinks far enough lots of things can be concluded.

Yes. And that's what a good writer aims for: to minimize the number of
words needed for the vast majority of readers to understand the point.

The more work you as a writer put into a sentence, the less work
hundreds or thousands of readers have to do while reading that sentence.

Rendundancy is only good when you are trying to reach a certain
word count for a university essay.

>  From the docs (and similar on git checkout)
> > --force
> > 
> >     An alias for --discard-changes.
> > --discard-changes
> > 
> >     Proceed even if the index or the working tree differs from HEAD.
> > Both the index and working tree are restored to match the switching 
> > target. If --recurse-submodules is specified, submodule content is 
> > also restored to match the switching target. This is used to throw
> > away local changes.

There's no adjective I can use for the official git documentation that
isn't crass, so let's just say that I find it extremelly lacking.

That paragraph above is a great example: it's a) hard to read, b)
unecessarily verbose, c) is wrongly ordered, d) redundant, and e) not
even correct.

> If the working tree is made to match the target, then it can not retain 
> local changes. That can be concluded.
> Yet, it is explicitly mentioned.
> 
> Does it really hurt to mention it?

Yes it does.

Time is the most precious resource we all have. We should not waste the
most precious resource of our readers.

  Throw away local changes.

That does a much better job.

If you want to be more explicit, you can add a bit more information:

  Throw away local changes either in the staging area or the working
  tree.

Why does the user have to know what HEAD is? And why does it matter that
the staging area is held in a file called "index"?

The current explanation is just bad.


But as I said, if you want to replicate the current style of the
documentation, go ahead, but it would be pretty much a bloated version
of "resets the branch to <head>".

> But anyway.
> I brought forward my idea. I explained my reasoning.
> If it (this part) is downvoted/rejected then that it how it is.

It's not a matter of consensus. There are proposals where literally
everyone is in favor, and yet they are never merged.

There's only one person you need to convince.

So, what I suggest you to do is take into consideration all we have
discussed and send another patch, because that's ultimately all that
matters. Moreover, it usually happens to me that while I write the patch
is when finally the previously-discussed ideas start to click.

> >>>> So, I still ask:
> >>>> - If "--force" to overwrite the work tree can clearly state that change
> >>>> to files will be "thrown away".
> >>>> - Then why can "force" re-using an existing branch name not do the same?
> >>>
> >>> Because we would be forcing two things now.
> >>
> >> Which 2 things?
> >>
> >> The worktree overwriting is *not* forced by -C
> >>
> >>     git switch -C b1 b2
> >>     git checkout -B b1 b2
> >>
> >> both give an error if the worktree has changed files.
> >>
> >> This is only about what happens to the branch.
> >>
> >> I.e we force the branchname to point to our new branch.
> >> And that means the branchname no longe points to the old branch, and the
> >> old branch therefore is removed.
> > 
> > It seems your proposal is to make `git switch -c --force b1 b2` be the same as
> > `git switch -C b1 b2`, but that would also make it the same as
> > `git switch -C --force b1 b2`. Therefore it would be forcing two things.
> > 
> > Or is your proposal something else?
> > 
> 
> No. I definitely want to keep those 2 apart from each other.
> 
> For each force-needing action, you should have to specify it's own force 
> flag.

OK, but I don't see the concrete proposal. What would be the flag that
makes -c "forceful"?

Cheers.
Martin July 10, 2021, 10:13 p.m. UTC | #54
On 10/07/2021 22:49, Felipe Contreras wrote:
> Martin wrote:
>>   From the docs (and similar on git checkout)
>>> --force
>>>
>>>      An alias for --discard-changes.
>>> --discard-changes
>>>
>>>      Proceed even if the index or the working tree differs from HEAD.
>>> Both the index and working tree are restored to match the switching
>>> target. If --recurse-submodules is specified, submodule content is
>>> also restored to match the switching target. This is used to throw
>>> away local changes.
....

>> If the working tree is made to match the target, then it can not retain
>> local changes. That can be concluded.
>> Yet, it is explicitly mentioned.
>>
>> Does it really hurt to mention it?
> 
> Yes it does.
> 
> Time is the most precious resource we all have. We should not waste the
> most precious resource of our readers.
> 
>    Throw away local changes.
> 
> That does a much better job.
> 
> If you want to be more explicit, you can add a bit more information:
> 
>    Throw away local changes either in the staging area or the working
>    tree.
> 
> Why does the user have to know what HEAD is? And why does it matter that
> the staging area is held in a file called "index"?
> 
> The current explanation is just bad.

Time is precious, but to really save on it, you have to invest some of it.

About the HEAD/index stuff => that was not at all related to the point I 
was making.
But I agree that bit can be shortened

The thing that I was pointing out, is the last sentence only.
 >    This is used to throw away local changes.

But even that can be reduced to your proposal
 >    Throw away local changes.

It still supports my point. It does state explicitly that data is (or 
can be) thrown away.


Now, if that can be stated on this option, then all I ask is to add a 
similar statement (as short as possible) to "-C".
It should indicate that *commit* may be *dropped".
Find a better word for dropped: lost, unreachable, removed.....

Currently only the branch is mentioned.
Currently nothing does explicitly say that *commits* can be affected.

At the end of the current or rewritten "-C" doc, add:
 >     This can drop commits

4 words. All that is needed.



> There's only one person you need to convince.
> 
> So, what I suggest you to do is take into consideration all we have
> discussed and send another patch, because that's ultimately all that
> matters. Moreover, it usually happens to me that while I write the patch
> is when finally the previously-discussed ideas start to click.

Well, I will see to make some time and put something together.
Might be a bit before I get to it, but that gives some time to think about.
Martin July 10, 2021, 10:13 p.m. UTC | #55
On 10/07/2021 22:49, Felipe Contreras wrote:
> Martin wrote:
>> For each force-needing action, you should have to specify it's own force 
>> flag. >
 > OK, but I don't see the concrete proposal. What would be the
 > flag that
 > makes -c "forceful"?
 >

Well that starts yet another topic.

At the moment, it is
    --force-create which is absorbing the flag into the option.

And by (apparent) convention it also is the uppercasing of the option
    -C
same as the uppercasing of the -B in checkout.

I am not really sure if the uppercasing is the best idea.
If your suggestion "core.advanced " were to come, I would vote that 
uppercase single letter force options should be restricted to advanced.


If -n is introduced, we can think about what to do about -N.
Should the  --force-*  style be kept?
    --force-new
    -N

Or the (unfortunate? / see below ) "--discard-changes" style:
    --discard-existing-branch -n <branchname>

I am against using --reset instead of --force-new.
At least I can say, if I use "-N", I want a *new* branch. I don't care 
about any old branch under that name.

Also "--reset" does not have the same alerting properties to me, as 
"force" or "discard" have.
This may be my English, but to me "reset" does not have the same 
alerting property.




The general problem is, if there is more than one force-needing action, 
then which one does -f  act on?

Any force-needing action, that only applies with another option (such as 
-N) can have a --force-*. So the plain -f is not used for it.

But, what if more than one force-needing event can happen (not just 
switch, but any command), even without any extra options? (May not yet 
be the case / not checked).

git switch has attempted to solve that.
The result IMHO is a disaster.
"-f" / "--force" is made an alias in favour for
    --discard-changes
What changes?
Felipe Contreras July 10, 2021, 11:18 p.m. UTC | #56
Martin wrote:
> On 10/07/2021 22:49, Felipe Contreras wrote:
> > Martin wrote:
> >> For each force-needing action, you should have to specify it's own force 
> >> flag. >
>  > OK, but I don't see the concrete proposal. What would be the
>  > flag that
>  > makes -c "forceful"?
>  >
> 
> Well that starts yet another topic.
> 
> At the moment, it is
>     --force-create which is absorbing the flag into the option.
> 
> And by (apparent) convention it also is the uppercasing of the option
>     -C
> same as the uppercasing of the -B in checkout.
> 
> I am not really sure if the uppercasing is the best idea.

Me neither, and it's not something I generally use.

> If your suggestion "core.advanced " were to come, I would vote that 
> uppercase single letter force options should be restricted to advanced.

I would not count on it. I suggested core.mode back in 2013 [1], so...

> If -n is introduced, we can think about what to do about -N.
> Should the  --force-*  style be kept?
>     --force-new
>     -N
> 
> Or the (unfortunate? / see below ) "--discard-changes" style:
>     --discard-existing-branch -n <branchname>
> 
> I am against using --reset instead of --force-new.

That's OK, and in fact I can see how '--reset --new' is clunky, I'm just
saying it is a possibility. But the main point is that something like
`git switch --reset` is missing, although `git switch --move` would
probably do the trick.

> At least I can say, if I use "-N", I want a *new* branch. I don't care 
> about any old branch under that name.

Right, I would as well, but in fact I would expect the same from -n
(although I can see how a newbie might not).

> Also "--reset" does not have the same alerting properties to me, as 
> "force" or "discard" have.
> This may be my English, but to me "reset" does not have the same 
> alerting property.

OK, maybe it's a language issue. I'm not a native English speaker, my
mother tongue is Spanish, but I'm pretty sure my understanding of
"reset" is what most people understand: set again.

Using Merriam Webster [2]:

  1: to set again or anew
  2: to change the reading of often to zero

And there's plenty of corroboration; reorder: order again (whatever
order you had is lost), reassign: assign again (whatever assignment you
had is gone), replay: play again (whatever you were playing is gone),
and so on.

> The general problem is, if there is more than one force-needing action, 
> then which one does -f  act on?
> 
> Any force-needing action, that only applies with another option (such as 
> -N) can have a --force-*. So the plain -f is not used for it.
> 
> But, what if more than one force-needing event can happen (not just 
> switch, but any command), even without any extra options? (May not yet 
> be the case / not checked).
> 
> git switch has attempted to solve that.
> The result IMHO is a disaster.
> "-f" / "--force" is made an alias in favour for
>     --discard-changes
> What changes?

I see.

So *if* --force was not an alias for --discard-changes, then this would
make sense:

  git switch --new --force topic

It would _force_ the creation of a _new_ branch called "topic".

Is this close to what you are thinking?

[1] https://lore.kernel.org/git/1379426871-6823-1-git-send-email-felipe.contreras@gmail.com/
[2] https://www.merriam-webster.com/dictionary/reset
Felipe Contreras July 10, 2021, 11:35 p.m. UTC | #57
Martin wrote:
> On 10/07/2021 22:49, Felipe Contreras wrote:
> > Martin wrote:
> >>   From the docs (and similar on git checkout)
> >>> --force
> >>>
> >>>      An alias for --discard-changes.
> >>> --discard-changes
> >>>
> >>>      Proceed even if the index or the working tree differs from HEAD.
> >>> Both the index and working tree are restored to match the switching
> >>> target. If --recurse-submodules is specified, submodule content is
> >>> also restored to match the switching target. This is used to throw
> >>> away local changes.
> ....
> 
> >> If the working tree is made to match the target, then it can not retain
> >> local changes. That can be concluded.
> >> Yet, it is explicitly mentioned.
> >>
> >> Does it really hurt to mention it?
> > 
> > Yes it does.
> > 
> > Time is the most precious resource we all have. We should not waste the
> > most precious resource of our readers.
> > 
> >    Throw away local changes.
> > 
> > That does a much better job.
> > 
> > If you want to be more explicit, you can add a bit more information:
> > 
> >    Throw away local changes either in the staging area or the working
> >    tree.
> > 
> > Why does the user have to know what HEAD is? And why does it matter that
> > the staging area is held in a file called "index"?
> > 
> > The current explanation is just bad.
> 
> Time is precious, but to really save on it, you have to invest some of it.

Sure.

> About the HEAD/index stuff => that was not at all related to the point I 
> was making.
> But I agree that bit can be shortened
> 
> The thing that I was pointing out, is the last sentence only.
>  >    This is used to throw away local changes.
> 
> But even that can be reduced to your proposal
>  >    Throw away local changes.
> 
> It still supports my point. It does state explicitly that data is (or 
> can be) thrown away.

OK, yeah, it does state explicitly that data is thrown away, but it's
the *last* sentence, when it should be the first, and everything else is
redundant.

> Now, if that can be stated on this option, then all I ask is to add a 
> similar statement (as short as possible) to "-C".
> It should indicate that *commit* may be *dropped".
> Find a better word for dropped: lost, unreachable, removed.....
> 
> Currently only the branch is mentioned.
> Currently nothing does explicitly say that *commits* can be affected.
> 
> At the end of the current or rewritten "-C" doc, add:
>  >     This can drop commits
> 
> 4 words. All that is needed.

OK. I'm not opposed to that, that would definitely be an improvement
from the current text.

What I'm saying is that if we are trying to improve the text, it would
behoove us to consider all other options, and instead if adding a note
at the end (which is correct), reconsider the whole thing to *start*
with what's important:

Instead of this:

  -C <new-branch>::
  --force-create <new-branch>::
    Similar to `--create` except that if `<new-branch>` already
    exists, it will be reset to `<start-point>`. This is a
    convenient shortcut for:
  +
  ------------
  $ git branch -f <new-branch>
  $ git switch <new-branch>
  ------------

Do this:

  -N <branch>::
    Create a new branch like '--new', but if it already exists reset it
    like '--reset'.

I don't know how is that unclear in any way.

> > There's only one person you need to convince.
> > 
> > So, what I suggest you to do is take into consideration all we have
> > discussed and send another patch, because that's ultimately all that
> > matters. Moreover, it usually happens to me that while I write the patch
> > is when finally the previously-discussed ideas start to click.
> 
> Well, I will see to make some time and put something together.
> Might be a bit before I get to it, but that gives some time to think about.

Take your time. One of the good things about open source is that there's
no rush.

Cheers.
Martin July 11, 2021, 12:39 a.m. UTC | #58
On 11/07/2021 01:18, Felipe Contreras wrote:

> That's OK, and in fact I can see how '--reset --new' is clunky, I'm just
> saying it is a possibility. But the main point is that something like
> `git switch --reset` is missing, although `git switch --move` would
> probably do the trick.

How would "git switch --reset" be different from "git switch -N" ?

"--move" is problematic.
- it reminds me of moving the commits. I.e. rebase.
- it actually stands for "rename" (in git branch -m).

The apparent idea:  "move the branch under a new name"
But the branch (base..head) itself stays where it is.
"rename" would be so much more intuitive to me.



>> At least I can say, if I use "-N", I want a *new* branch. I don't care
>> about any old branch under that name.
> 
> Right, I would as well, but in fact I would expect the same from -n
> (although I can see how a newbie might not).
> 
That's why we have to keep in mind that -N is really --force-new.

     A non-force option should not lead to data loss.

Or if something can be lost, then "force" needs to be used.
If the branch-name already points to a branch then of that branch, you 
stand to loose:
- the branch boundaries (base..head)
- in some cases, (some of) the commits hold by it.

So by convention a simple "-n" is protecting me from that.
IMHO that should be expected.


>> Also "--reset" does not have the same alerting properties to me, as
>> "force" or "discard" have.
>> This may be my English, but to me "reset" does not have the same
>> alerting property.
> 
> OK, maybe it's a language issue. I'm not a native English speaker, my
> mother tongue is Spanish, but I'm pretty sure my understanding of
> "reset" is what most people understand: set again.

I am German. And yes "set again" (sometimes "restart", but that does not 
matter here)

If a branch is set, as base and head. Then "reset" means to set those 
two again.

      "set again" => They will still be there.
      (changed indeed, but there)

The commits hold by that branch, are not "set again".
They may become unreachable.

The word "reset" gives no indication on knock on effects.
However, I prefer if those effects are made clear.

 > meriam webster
Quite some of the examples are "put back into working order"
(broken leg / circuit breaker => reset does not loose anything)

Others are restart (at zero) "reset an odometer".
To me personally the emphasis is the "start again", the loss of the 
previous value is a side effect.

Maybe others will take see "loss" part as more prominent.
The question then is, how many might not be that wary of the potential loss?


> 
> So *if* --force was not an alias for --discard-changes, then this would
> make sense:
> 
>    git switch --new --force topic
> 
> It would _force_ the creation of a _new_ branch called "topic".
> 
> Is this close to what you are thinking?

No, again no. I said "I want them to be separate force flags"

As long as we have the unspecific "--force" this must be limited to 
event *not* triggered by added options.

That is
    git switch foo

is not forceful, therefore not allowed to destroy data.
Hence it can not overwrite local changes.
So --force applies to that.

Now if you were currently detached, and made new commits while detached, 
then
    git switch foo
would loose those commits.
Hypothetical, that could require force.

And like the first example it is part of the default behaviour. No 
options are given.

But then using the same --force to force something else would be bad.
So then we need --force-discard-local-changed and 
--force-unlink-detached-commit


git -n newbranch commit
is not default behaviour. It is triggered by the -n option.
If this endangers any data (other than what is covered by default 
cases), then this always needs its own force.
And it has --force-new


It is possible, but I dislike it very much to define that
--force affects the next option that follows.

So that, thin is -N
  git switch --force --new

But those are not
  git switch --new --force
  git switch --force - --new   // the single dash separates the force

I do not like that idea...
Sergey Organov July 11, 2021, 7:57 a.m. UTC | #59
Martin <git@mfriebe.de> writes:


[...]

> Currently only the branch is mentioned.
> Currently nothing does explicitly say that *commits* can be affected.

Commits cannot be immediately affected. One of the most essential
features of Git is that commits could only be affected (deleted) by
garbage collection. That's what makes Git so nicely safe in operation.

It'd be unfortunate to have statements in the manual pages that
contradict this.

Thanks,
Sergey Organov July 11, 2021, 9:04 a.m. UTC | #60
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Martin <git@mfriebe.de> writes:
>> 
>> > On 10/07/2021 12:24, Sergey Organov wrote:
>> >> Martin <git@mfriebe.de> writes:
>> >>> Actually, "new" or "create" would make sense in "git branch". But in
>> >>> git switch, they actually raise the question "create what?" / "new
>> >>> what?".
>> >> I believe that's because "git switch" tries to do too much. "git switch"
>> >> should rather switch between existing branches, and do nothing else. As
>> >> I said once in this discussion already: trouble writing good
>> >> documentation is often indication of some flaws in the design.
>> >> Creating (a branch) is fundamentally different operation than switching
>> >> to (a branch), and that's why the former doesn't fit into "git switch".
>> >> 
>> >
>> > Right, yes. But creating a branch is often followed by switching to it.
>> 
>> Yep, but here the creation is the primary operation, not switching, so
>> putting this into "git switch" looks like design flaw. These 2 actions
>> are fine to co-exist in "git branch" = "whatever you want to do to
>> branches", but not in "git switch" == "wherever you want to switch".
>
> I don't see the logic in here.
>
>   git branch topic # here 'branch' is the verb

Not to me. I assumed the "branch" is always a noun in "git branch", and
the actual meaning of this command is:

   git branch [create|new] topic

I.e., creation just being the default action taken on the branch.

>   git switch topic # here 'switch' is the verb

Yep.

>
> Now, if you want to do both at the same time the logical options are:
>
>   git branch --switch topic # here '--switch' is an adverb
>   git switch --new topic # here '--new' is an adverb

Yes, we can (and do) shove it into the "git switch", but "git new" would
be better design.

>
> The former reads like gibberish to me: "git, branch off in a 'switch'
> way".
>
> The latter makes perfect sense: "git, switch to a branch in a 'new' way".
>
>> Logically, there could be something like "git new" that does create a
>> branch and then switches there by default, or something like that, say:
>> 
>>    git new feature3 --at origin/rc-2 --track
>
> Here the the verb is clear, but not the direct object, a "new" what?
> Couldn't it be a tag? Or a commit? Or a remote? Or a worktree? Or a
> bisect? Or a submodule?

Yes, it could be anything. The above is written in an assumption that
default object for "git new" is branch.

>
> It's too ambigous.

Yep. The explicit mode should have been:

  git new branch feature3 --at origin/rc-2 --track


>
>> And while we are at it, do you guys notice how 2 concepts are mixed in
>> Git commands? I mean, the interface seems to mix object-oriented and
>> action-oriented commands, most of commands being action-oriented with
>> only a few unfortunate exceptions.
>> 
>> Let me try a short survey:
>> 
>> 1. In
>> 
>>   git branch ...
>> 
>> is "branch" a noun or a verb?
>
> Both.

No, it's rather noun plus lacking subcommand, sometimes making it look
like verb :)

>
>> 2. In
>> 
>>   git merge ...
>> 
>> is "merge" a noun or a verb?
>
> Verb.
>
>> To me, while the latter is obvious, it's verb and specifies the action
>> to be performed, the former looks more like "whatever you want to do
>> with branches", and thus the "branch" is a noun there and the command
>> thus is object-oriented.
>
> I agree, and I did have indeed noticed the inconsistency. But there's
> another category of commands that receive subcommands, like:
>
>   git remote $subcommand
>   git worktree $subcommand
>   git bisect $subcommand
>
> In my opinion `git branch` fits more these subcommand commands, and it
> was a mistake to make the subcommands options, it should be:
>
>   git branch list
>   git branch new
>   git branch set-upstream
>   git branch move
>   ...
>
> Now the verb is crystal-clear.

Yes, lacking (assumed) subcommands is yet another dimension of
inconsistencies.

I mean what I'm after is inconsistency of the first argument to "git".
It's being the verb more often is where we currently are, at least when
considering "primary" commands that "git help" outputs. 

I mean, consider:

   git branch new nice-feature

vs

   git new branch nice-feature

It should have been the latter, when in fact it's currently the
[reduced] former.

I.e., I'm in favor of universal:

   git <command> ...

syntax to Git commands where <command> specifies an action. [Why things
tend to drift to Lisp all the time, I wonder?]

From that POV, for the commands you mentioned, "git bisect" is probably
fine, whereas "git worktree", and "git remote" should better be split to
operations on them, e.g.:

   git new remote
   git new worktree

Once that is regularized, we may as well consider allowing for inverse
order of the first 2 arguments, by making

  git new remote
  git remote new

the synonyms.

It doesn't mean we need to rewrite everything. Having an end-goal
specified though, we may design new features accordingly, and add
commands in preferred syntax for existing features, so that they
eventually obsolete the current status quo.

Thanks,
Martin July 11, 2021, 9:10 a.m. UTC | #61
On 11/07/2021 01:35, Felipe Contreras wrote:
> Martin wrote:
>> At the end of the current or rewritten "-C" doc, add:
>>   >     This can drop commits
>>
>> 4 words. All that is needed.
> 
> OK. I'm not opposed to that, that would definitely be an improvement
> from the current text.
> 
> What I'm saying is that if we are trying to improve the text, it would
> behoove us to consider all other options, and instead if adding a note
> at the end (which is correct), reconsider the whole thing to *start*
> with what's important:

Ah, ok. So we have been missing each others point.


> Instead of this:
> 
>    -C <new-branch>::
>    --force-create <new-branch>::
>      Similar to `--create` except that if `<new-branch>` already
>      exists, it will be reset to `<start-point>`. This is a
>      convenient shortcut for:
>    +
>    ------------
>    $ git branch -f <new-branch>
>    $ git switch <new-branch>
>    ------------
> 
> Do this:
> 
>    -N <branch>::
>      Create a new branch like '--new', but if it already exists reset it
>      like '--reset'.

As I said, I try to avoid reset, and also there is no "--reset" to 
match. Only a "reset" command, and it does a wide range of diff things

     -force-new <branch-name> <commit>
     -N <branch-name> <commit>
       See the --new option.
       Allows to [re-]use the name of an existing branch.
       This may drop commits of that branch.

Or
       See the --new option.
       Can use the name of an existing branch.
       Removing that branch may drop commits.
If needs must
       "Removing" => "Resetting"


Or even shorter
       See the --new option.
       Allows to re-use a branch-name and may drop commits
       [resetting it].
Martin July 11, 2021, 9:27 a.m. UTC | #62
On 11/07/2021 09:57, Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
> 
> 
> [...]
> 
>> Currently only the branch is mentioned.
>> Currently nothing does explicitly say that *commits* can be affected.
> 
> Commits cannot be immediately affected. One of the most essential
> features of Git is that commits could only be affected (deleted) by
> garbage collection. That's what makes Git so nicely safe in operation.
> 
> It'd be unfortunate to have statements in the manual pages that
> contradict this.
> 

Tell that a new user, who never heard of "dangling commits" or the reflog.

For ages, I wondered what git fsck meant by "dangling commits" and why 
my repro always had "that problem".
And what I might do with that hash it gave me.

For a new user, a commit that is not in any branch listed by
"git branch --all" or "git stash"
is effectively not existent.

For a new user, it is also "no help" (and the doc should help) to avoid 
saying it, and instead refer to something else from which it could be 
concluded.
"reset the branch" talks about the branch, and not the commit.
A new user, even if he read about it before, may very well not make the 
conclusion.
So "reset the branch" does nothing for a new user. And an expert already 
knows it. So for whom should that be there?

We can use the term unreachable. But it is no better than say "drop"

Technically they are not "unreachable". If I have the hash, I (as 
expert) can reach them.
If I do not, I can get it from "fsck". (And spend a good amount of time, 
going through a few dozen hashes. (That is, if the reflog was disabled)

"Drop" does not mean "deleted". More like "dropped from view", "given up"
But a new user reading "dropped" will take it as a hint to be careful.

We can add "dropped commit" to the glossary. Then there is no ambiguity. 
(I don't think its needed, but...)

We can say "may no longer have a reference" instead of "dropped"
But it is long, and again obscure (to a new user).
Sergey Organov July 11, 2021, 9:30 a.m. UTC | #63
Martin <git@mfriebe.de> writes:

>
> As I said, I try to avoid reset, and also there is no "--reset" to match. Only a "reset" command, and it does a wide range of diff things
>
>     -force-new <branch-name> <commit>
>     -N <branch-name> <commit>
>       See the --new option.
>       Allows to [re-]use the name of an existing branch.
>       This may drop commits of that branch.
>
> Or
>       See the --new option.
>       Can use the name of an existing branch.
>       Removing that branch may drop commits.
> If needs must
>       "Removing" => "Resetting"
>
>
> Or even shorter
>       See the --new option.
>       Allows to re-use a branch-name and may drop commits
>       [resetting it].

I'm strongly against "may drop commits". I see what you mean, but "drop"
sounds wrong to me, and we should not be plain wrong in the manuals.

Maybe:

"Allows to reuse <branch-name>. Commits from the former branch may
become unreferenced."

At least this it technically correct and doesn't sound that utterly
fatal.

Thanks,
Sergey Organov July 11, 2021, 9:37 a.m. UTC | #64
Martin <git@mfriebe.de> writes:

> On 11/07/2021 09:57, Sergey Organov wrote:
>> Martin <git@mfriebe.de> writes:
>> 
>> [...]
>> 
>>> Currently only the branch is mentioned.
>>> Currently nothing does explicitly say that *commits* can be affected.
>> Commits cannot be immediately affected. One of the most essential
>> features of Git is that commits could only be affected (deleted) by
>> garbage collection. That's what makes Git so nicely safe in operation.
>> It'd be unfortunate to have statements in the manual pages that
>> contradict this.
>> 
>
> Tell that a new user, who never heard of "dangling commits" or the reflog.
>
> For ages, I wondered what git fsck meant by "dangling commits" and why
> my repro always had "that problem".
> And what I might do with that hash it gave me.
>
> For a new user, a commit that is not in any branch listed by
> "git branch --all" or "git stash"
> is effectively not existent.
>
> For a new user, it is also "no help" (and the doc should help) to
> avoid saying it, and instead refer to something else from which it
> could be
> concluded.
> "reset the branch" talks about the branch, and not the commit.
> A new user, even if he read about it before, may very well not make
> the conclusion.
> So "reset the branch" does nothing for a new user. And an expert
> already knows it. So for whom should that be there?
>
> We can use the term unreachable. But it is no better than say "drop"
>
> Technically they are not "unreachable". If I have the hash, I (as
> expert) can reach them.
> If I do not, I can get it from "fsck". (And spend a good amount of
> time, going through a few dozen hashes. (That is, if the reflog was
> disabled)
>
> "Drop" does not mean "deleted". More like "dropped from view", "given up"
> But a new user reading "dropped" will take it as a hint to be careful.
>
> We can add "dropped commit" to the glossary. Then there is no
> ambiguity. (I don't think its needed, but...)
>
> We can say "may no longer have a reference" instead of "dropped"
> But it is long, and again obscure (to a new user).

As I just stated in anther answer, which see, I see what you mean. I'm
still against "dropped" though.

I did suggest a wording in that post:

"Allows to reuse <branch-name>. Commits from the former branch may
become unreferenced."

Another one could be:

"Allows to reuse <branch-name>. Commits from the former branch could be
lost."

Thanks,
Sergey Organov July 11, 2021, 9:52 a.m. UTC | #65
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:

[...]

>> Creating (a branch) is fundamentally different operation than switching
>> to (a branch), and that's why the former doesn't fit into "git switch".
>
> Not in my mind. Instead of switching to an existing branch, I'm switching
> to a new branch, which is easily understood by
> `git switch --new branch`.

To me:

"create a new branch" is basic operation.

"switch to another branch" is basic operation.

"create a new branch and then switch to it" is compound operation.

The latter could be implemented as either new-then-switch or
switch-to-new indeed, but the "new" part is the first action to be made,
so

  git new branch <branch-name>

that switches to the <branch-name> by default still sounds more logical
to me than current:

  git switch -c <branch-name>

Thanks,
Martin July 11, 2021, 10:05 a.m. UTC | #66
On 11/07/2021 11:04, Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
>>
>> I don't see the logic in here.
>>
>>    git branch topic # here 'branch' is the verb
> 
> Not to me. I assumed the "branch" is always a noun in "git branch", and
> the actual meaning of this command is:

Well, it is easy to see it as a noun. But for "branching" creation of a 
branch, it can be seen as verb.

Yet in
    git branch --list
it definitely is a noun.

But then how would/should those work?
The action/verb is "list" or "show"

    git show branches
    git show tags
    git show ...

That completely tears apart related topics.

Or is it enough if the subcommand is a verb?
     git branch create
     git branch list
That be ok for me.


>>> is "branch" a noun or a verb?
>>
>> Both.
> 
> No, it's rather noun plus lacking subcommand, sometimes making it look
> like verb :)

As is
     git stash
for
     git stash push

And I should guess lots of people like the short form....




> I.e., I'm in favor of universal:
> 
>     git <command> ...
> 
> syntax to Git commands where <command> specifies an action. [Why things
> tend to drift to Lisp all the time, I wonder?]
> 

Because humans are more about the "things".
The way we interact is more ofter derived from the object, than the 
object being purposefully made for an interaction?


>  From that POV, for the commands you mentioned, "git bisect" is probably
> fine, whereas "git worktree", and "git remote" should better be split to
> operations on them, e.g.:
> 
>     git new remote
>     git new worktree
> 

That also makes documentation harder. People who want a worktree, want 
the documentation for it in one place.

So a manpage for "git new" is not desirable. It would have to be split 
into the manpages for the objects. But that is not good either, or is it?


> Once that is regularized, we may as well consider allowing for inverse
> order of the first 2 arguments, by making
> 
>    git new remote
>    git remote new
> 
> the synonyms.

Having even more ways to do one and the same thing....


Btw, missing from the discussion:

    git log

"log" can be a verb, but not in the above.

Because "to log" is to write something into a log.
But "git log" is to show (i.e. read) the log.
Martin July 11, 2021, 10:24 a.m. UTC | #67
On 11/07/2021 11:37, Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
> I did suggest a wording in that post:
> 
> "Allows to reuse <branch-name>. Commits from the former branch may
> become unreferenced."
> 
> Another one could be:
> 
> "Allows to reuse <branch-name>. Commits from the former branch could be
> lost."
> 

"lost" is perfect for me.

"could be" is a good replacement for "may". It much stronger points to 
"this may or may not be"

"could be"  should definitely be used.

Afaik many tech docs try to avoid "may", "can", "must not"....
Sergey Organov July 11, 2021, 12:23 p.m. UTC | #68
Martin <git@mfriebe.de> writes:

> On 11/07/2021 11:04, Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>>>
>>> I don't see the logic in here.
>>>
>>>    git branch topic # here 'branch' is the verb
>> Not to me. I assumed the "branch" is always a noun in "git branch", and
>> the actual meaning of this command is:
>
> Well, it is easy to see it as a noun. But for "branching" creation of
> a branch, it can be seen as verb. 
>
> Yet in
>    git branch --list
> it definitely is a noun.

It's definitely a noun if only consider its description, as output by
"git help":

  "branch            List, create, or delete branches"

So "git branch" is "whatever about branches", not "perform the branch
operation", whatever the latter might be.

>
> But then how would/should those work?
> The action/verb is "list" or "show"
>
>    git show branches
>    git show tags
>    git show ...
>
> That completely tears apart related topics.

Yep, that's it. However, there is no need to immediately do something
about it except considering this as a sound design to be targeted at.

>
> Or is it enough if the subcommand is a verb?
>     git branch create
>     git branch list
> That be ok for me.

This we can't do sanely in a backward-compatible manner, I'm afraid, so
it's likely not an option.

OTOH, adding, say:

      git rm <branch-name>

or, say, adding a whole new "git new" (pun intended) could be considered
to be steps in the right direction if we choose "git <action> ..."
model.

>
>
>>>> is "branch" a noun or a verb?
>>>
>>> Both.
>> No, it's rather noun plus lacking subcommand, sometimes making it look
>> like verb :)
>
> As is
>     git stash
> for
>     git stash push
>
> And I should guess lots of people like the short form....

Maybe. My primary point is inconsistency, not my personal preference for
one way or another. I'm afraid one could find suitable example to
support any model.

>
>> I.e., I'm in favor of universal:
>>     git <command> ...
>> syntax to Git commands where <command> specifies an action. [Why things
>> tend to drift to Lisp all the time, I wonder?]
>> 
>
> Because humans are more about the "things".
> The way we interact is more ofter derived from the object, than the
> object being purposefully made for an interaction?

I don't see it, at least not in the usual human conversations. When one
means an action to be performed, they name the action and then the object:

  "Play football", "Go home", "Set your thoughts straight", "Wash your hands"

No?

Anyway, it's more the consistency that matters, not particular
convention. Git problem is that is has no convention at all. "Just do
what feels right today" seems to be the motto.

Finally, the problem for this particular discussion is that if we decide
that it's rather:

  git <object> <command>

that is the way to go, that I'm pretty fine with as well, we should
simply *obsolete "git switch" right away*, rather than spending time
improving its now almost useless documentation.

>>  From that POV, for the commands you mentioned, "git bisect" is probably
>> fine, whereas "git worktree", and "git remote" should better be split to
>> operations on them, e.g.:
>>     git new remote
>>     git new worktree
>> 
>
> That also makes documentation harder. People who want a worktree, want
> the documentation for it in one place.

  git help worktree

should be able to provide a short manual on worktrees. Please notice
it's again not

  git worktree help


>
> So a manpage for "git new" is not desirable.

Sure it is desirable. That's the primary purpose of manual pages -- to
describe actual commands.

> It would have to be split into the manpages for the objects. But that
> is not good either, or is it?

No-no! Manual pages for describing actual commands are to be there.

It's user/programmer manuals and tutorials that should rather be built
around concepts. It's fine with me if they are available in the format
of manual pages, even though it's not very suitable for that.

>
>> Once that is regularized, we may as well consider allowing for inverse
>> order of the first 2 arguments, by making
>>    git new remote
>>    git remote new
>> the synonyms.
>
> Having even more ways to do one and the same thing....

Python was aiming to have one obvious way of doing every single thing...
Did it succeed in that, I wonder? Maybe this aim is only good in theory?

>
>
> Btw, missing from the discussion:
>
>    git log
>
> "log" can be a verb, but not in the above.

Yep, and "git log" is yet another can of worms I'm not willing to open.

Thanks,
Martin July 11, 2021, 1:39 p.m. UTC | #69
On 11/07/2021 14:23, Sergey Organov wrote:
> Martin <git@mfriebe.de> writes:
>> Because humans are more about the "things".
>> The way we interact is more ofter derived from the object, than the
>> object being purposefully made for an interaction?
> 
> I don't see it, at least not in the usual human conversations. When one
> means an action to be performed, they name the action and then the object:
> 
>    "Play football", "Go home", "Set your thoughts straight", "Wash your hands"
> 
> No?

1) the order does not necessarily indicate the significance.

2) That is English for you. Afaik there are languages which have the 
verb at the end.
Also, in German it is perfectly fine (though not very common) to use 
"object verb subject". Fussball spielen wir.

Even in English you have: Woe is me. Yes "woe" is the Subject.


> Anyway, it's more the consistency that matters, not particular
> convention. Git problem is that is has no convention at all. "Just do
> what feels right today" seems to be the motto.

Well human languages are not as rigid as computer languages.

> 
> Finally, the problem for this particular discussion is that if we decide
> that it's rather:
> 
>    git <object> <command>
> 
> that is the way to go, that I'm pretty fine with as well, we should
> simply *obsolete "git switch" right away*, rather than spending time
> improving its now almost useless documentation.

Actually then we would end up with

    git branch switch
    git tag switch   // detach
    git commit switch   // detach

Well it could be
    git worktree switch
(ignoring the effect on the index / and bringing "worktree" into a 
single worktree setup)



The problem is, that IMHO forcing either verb or noun, ends up with 
grouping commands in ways that create unnecessary dividers between 
related actions. (Continued, next paragraph)

> 
>>>   From that POV, for the commands you mentioned, "git bisect" is probably
>>> fine, whereas "git worktree", and "git remote" should better be split to
>>> operations on them, e.g.:
>>>      git new remote
>>>      git new worktree
>>>

This is what I mean with dividers.

There may be some relation between "new branch", "new tag"

But I can see none between "new branch" and "new remote" and "new 
worktree". None at all. Yet I can see relations between different things 
you can do with a worktree.

I also think that, switching to a commit or branch are to closely 
related, and should not be divided.
(There were even suggestions that switching to a commit, is an unnamed 
branch)

As I said, I have not read any research paper on that topic.
But to me, it severely disrupts the intuitive aspect.


>>
>>> Once that is regularized, we may as well consider allowing for inverse
>>> order of the first 2 arguments, by making
>>>     git new remote
>>>     git remote new
>>> the synonyms.
>>
>> Having even more ways to do one and the same thing....
> 
> Python was aiming to have one obvious way of doing every single thing...
> Did it succeed in that, I wonder? Maybe this aim is only good in theory?

We are way away from having "one single way". But aiming for the extreme 
opposite may not be any smarter.



While there is nothing wrong with going our own way in the end, maybe we 
should look around before?
How do other vcs do it?

svn has at least status and log, which I would consider nouns, the way 
they are used. And it has verbs too.

hg as "branches", "files" which are nouns. And "log".
And it has verbs too.

So there seems to be a pattern to using "mixed" verbs and nouns.
Sergey Organov July 11, 2021, 2:49 p.m. UTC | #70
Martin <git@mfriebe.de> writes:

> On 11/07/2021 14:23, Sergey Organov wrote:

[...]

>>>> Once that is regularized, we may as well consider allowing for inverse
>>>> order of the first 2 arguments, by making
>>>>     git new remote
>>>>     git remote new
>>>> the synonyms.
>>>
>>> Having even more ways to do one and the same thing....
>> Python was aiming to have one obvious way of doing every single thing...
>> Did it succeed in that, I wonder? Maybe this aim is only good in theory?
>
> We are way away from having "one single way". But aiming for the
> extreme opposite may not be any smarter.

I don't like extremes either, but when there is a choice, there should
be at last a stated preferred way of doing things. Guidelines, if not
the rules. Otherwise we end up with an ugly mix of random preferences of
different authors.

>
> While there is nothing wrong with going our own way in the end, maybe
> we should look around before?
>
> How do other vcs do it?
>
> svn has at least status and log, which I would consider nouns, the way
> they are used. And it has verbs too.
>
> hg as "branches", "files" which are nouns. And "log".
> And it has verbs too.
>
> So there seems to be a pattern to using "mixed" verbs and nouns.

There are so many things they did wrong... This could well be just
another one.

Thanks,
Sergey Organov July 11, 2021, 4:51 p.m. UTC | #71
Martin <git@mfriebe.de> writes:

> On 11/07/2021 14:23, Sergey Organov wrote:
>> Martin <git@mfriebe.de> writes:

[...]

>> Anyway, it's more the consistency that matters, not particular
>> convention. Git problem is that is has no convention at all. "Just do
>> what feels right today" seems to be the motto.
>
> Well human languages are not as rigid as computer languages.
>
>> Finally, the problem for this particular discussion is that if we decide
>> that it's rather:
>>    git <object> <command>
>> that is the way to go, that I'm pretty fine with as well, we should
>> simply *obsolete "git switch" right away*, rather than spending time
>> improving its now almost useless documentation.
>
> Actually then we would end up with
>
>    git branch switch
>    git tag switch   // detach
>    git commit switch   // detach

Why? You don't switch tags or commits. You switch only branches, so it'd
be:

    git branch switch <dest>

where <dest> is any commit'ish.

>
> Well it could be
>    git worktree switch
> (ignoring the effect on the index / and bringing "worktree" into a
> single worktree setup)

Yep, it could be, and it could be even both doing similar things.

>
> The problem is, that IMHO forcing either verb or noun, ends up with
> grouping commands in ways that create unnecessary dividers between
> related actions. (Continued, next paragraph)

The problem is that there are multiple ways of grouping, and selecting
the right one is not an easy decision. Having carefully though-of
guidelines would help.

Grouping by action first is more universal than grouping by object
first, but not always more "natural", as you've correctly noticed.

>
>> 
>>>>   From that POV, for the commands you mentioned, "git bisect" is probably
>>>> fine, whereas "git worktree", and "git remote" should better be split to
>>>> operations on them, e.g.:
>>>>      git new remote
>>>>      git new worktree
>>>>
>
> This is what I mean with dividers.
>
> There may be some relation between "new branch", "new tag"
>
> But I can see none between "new branch" and "new remote" and "new
> worktree". None at all. Yet I can see relations between different
> things
> you can do with a worktree.

The only true relation in this model is that if you want to create
*something* new, you use "git new". Simple like hell.

>
> I also think that, switching to a commit or branch are to closely
> related, and should not be divided.

Strictly speaking, there is no need to switch to something that is not
a branch. But we'd need the notion of "unnamed branch" to achieve this
simplicity while not loosing useful functionality, and even gaining
some, see below.

> (There were even suggestions that switching to a commit, is an unnamed
> branch)

Yep. We just switch our current *branch*, so another *branch* becomes
current. If we specify a commit or a tag as the target, the unnamed
branch should be reset to point there, and only then we should switch
our current to this new unnamed branch. That's it. No need for
complications of "detached HEAD", that even sounds awfully and makes me
scared every time I see it.

In fact this "unnamed branch" could have a non-empty name, say "AUTO",
and its own entry in the reflog. That'd give even more functionality
than is currently available with this chilling "detached HEAD". We should
better bury this Nearly Headless Nick finally.

Thanks,
Kerry, Richard July 12, 2021, 10:31 a.m. UTC | #72
> >    git branch switch
> >    git tag switch   // detach
> >    git commit switch   // detach
> 
> Why? You don't switch tags or commits. You switch only branches, 

Yes you do.
You can switch to branches, tags or commits.

If I remember correctly, "branch" is used in Subversion and CVS only for the creation of a branch.  Likewise "tag" for creating a tag.  
And I think they both use "update" to load the required branch/tag/commit into the current working area.

If git were to do that then I think we might get around some of this confusion.

In that case:
git branch = create a branch
git tag = create a tag

And then a new "update", so:
git update <branchname> = make the current working area contain a copy of the given branch, and similarly "git update <tagname>" or "git update <commit-id>"

In all these cases the keyword after "git" is definitely a verb, even where the actual word used could be either, and you need to look at all the definitions in the dictionary to check.

Regards,
Richard.
Sergey Organov July 12, 2021, 11:11 a.m. UTC | #73
"Kerry, Richard" <richard.kerry@atos.net> writes:

>> >    git branch switch
>> >    git tag switch   // detach
>> >    git commit switch   // detach
>> 
>> Why? You don't switch tags or commits. You switch only branches, 
>
> Yes you do.

No, you don't. You probably didn't read my sentence carefully. Please
try to read what is written there, and see below for more explanations.

> You can switch to branches, tags or commits.

1. Switch branch /to a tag/ is not the same as switching /tag/. You can
reset tag to point to another commit, yes, but that was outside of the
scope of the discussion. Switching *commit* doesn't make sense at all.
Overall, you don't switch tags or commits when you switch branches, --
that's the meaning of my original sentence.

2. Event when you switch /to/ tags or commits, you actually still switch
to a branch, as you can still create new commits that will grow that
branch. This "detached HEAD" thingy that has been adopted to support
switching to commits is just a misnomer that obscures understanding, and
should be eventually replaced, probably by means of introducing the
notion of "unnamed" or "automatic" branch.

>
> If I remember correctly, "branch" is used in Subversion and CVS only
> for the creation of a branch. Likewise "tag" for creating a tag.
> And I think they both use "update" to load the required
> branch/tag/commit into the current working area.
>
> If git were to do that then I think we might get around some of this
> confusion.
>
> In that case:
> git branch = create a branch

Sorry, it's too late. I don't think we can actually do it.

> git tag = create a tag

Ditto. Too late.

>
> And then a new "update", so:
> git update <branchname> = make the current working area contain a copy
> of the given branch, and similarly "git update <tagname>" or "git
> update <commit-id>"

It's already called "git restore", no?

>
> In all these cases the keyword after "git" is definitely a verb, even
> where the actual word used could be either, and you need to look at
> all the definitions in the dictionary to check.

In the current "git branch" command "branch" is a noun, and then a verb
defining exact operation follows as an option, or is assumed. You may
well think about it as being "namespace":

  "git" -- enter "git" namespace
  "branch" -- enter "git:branch" namespace

and everything that follows is about Git branches with more or less
random syntax for particular functions to be performed.

Thanks,
Felipe Contreras July 12, 2021, 4:15 p.m. UTC | #74
Martin wrote:
> On 11/07/2021 01:18, Felipe Contreras wrote:

> >> Also "--reset" does not have the same alerting properties to me, as
> >> "force" or "discard" have.
> >> This may be my English, but to me "reset" does not have the same
> >> alerting property.
> > 
> > OK, maybe it's a language issue. I'm not a native English speaker, my
> > mother tongue is Spanish, but I'm pretty sure my understanding of
> > "reset" is what most people understand: set again.
> 
> I am German. And yes "set again" (sometimes "restart", but that does not 
> matter here)
> 
> If a branch is set, as base and head. Then "reset" means to set those 
> two again.
> 
>       "set again" => They will still be there.
>       (changed indeed, but there)
> 
> The commits hold by that branch, are not "set again".
> They may become unreachable.
> 
> The word "reset" gives no indication on knock on effects.
> However, I prefer if those effects are made clear.

I gave plenty of examples where "reset" implies the previous state is
gone after it.
Felipe Contreras July 12, 2021, 4:24 p.m. UTC | #75
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Sergey Organov wrote:
> >> Martin <git@mfriebe.de> writes:
> >> 
> >> > On 10/07/2021 12:24, Sergey Organov wrote:
> >> >> Martin <git@mfriebe.de> writes:
> >> >>> Actually, "new" or "create" would make sense in "git branch". But in
> >> >>> git switch, they actually raise the question "create what?" / "new
> >> >>> what?".
> >> >> I believe that's because "git switch" tries to do too much. "git switch"
> >> >> should rather switch between existing branches, and do nothing else. As
> >> >> I said once in this discussion already: trouble writing good
> >> >> documentation is often indication of some flaws in the design.
> >> >> Creating (a branch) is fundamentally different operation than switching
> >> >> to (a branch), and that's why the former doesn't fit into "git switch".
> >> >> 
> >> >
> >> > Right, yes. But creating a branch is often followed by switching to it.
> >> 
> >> Yep, but here the creation is the primary operation, not switching, so
> >> putting this into "git switch" looks like design flaw. These 2 actions
> >> are fine to co-exist in "git branch" = "whatever you want to do to
> >> branches", but not in "git switch" == "wherever you want to switch".
> >
> > I don't see the logic in here.
> >
> >   git branch topic # here 'branch' is the verb
> 
> Not to me. I assumed the "branch" is always a noun in "git branch", and
> the actual meaning of this command is:
> 
>    git branch [create|new] topic
> 
> I.e., creation just being the default action taken on the branch.

The question is not what you assumed, the question is can other people
assume otherwise?

"branch" can be a verb, that's a fact.

> >> To me, while the latter is obvious, it's verb and specifies the action
> >> to be performed, the former looks more like "whatever you want to do
> >> with branches", and thus the "branch" is a noun there and the command
> >> thus is object-oriented.
> >
> > I agree, and I did have indeed noticed the inconsistency. But there's
> > another category of commands that receive subcommands, like:
> >
> >   git remote $subcommand
> >   git worktree $subcommand
> >   git bisect $subcommand
> >
> > In my opinion `git branch` fits more these subcommand commands, and it
> > was a mistake to make the subcommands options, it should be:
> >
> >   git branch list
> >   git branch new
> >   git branch set-upstream
> >   git branch move
> >   ...
> >
> > Now the verb is crystal-clear.
> 
> Yes, lacking (assumed) subcommands is yet another dimension of
> inconsistencies.
> 
> I mean what I'm after is inconsistency of the first argument to "git".
> It's being the verb more often is where we currently are, at least when
> considering "primary" commands that "git help" outputs. 
> 
> I mean, consider:
> 
>    git branch new nice-feature
> 
> vs
> 
>    git new branch nice-feature
> 
> It should have been the latter, when in fact it's currently the
> [reduced] former.

I disagree. I prefer the former.

Either way this is way too far from the original point. I don't think
you can convince me that `git new branch` makese sense, but there's no
need for that.

To move forward we need to find consensus, and if you and me agree that
`git branch new` makes sense, that's where we should focus on.

Even standardizing `git branch` would be an almost-impossible task, even
if we manage to convince others. `git new branch` even more impossible.
Felipe Contreras July 12, 2021, 4:28 p.m. UTC | #76
Martin wrote:
> On 11/07/2021 01:35, Felipe Contreras wrote:

> > Do this:
> > 
> >    -N <branch>::
> >      Create a new branch like '--new', but if it already exists reset it
> >      like '--reset'.

> Or even shorter
>        See the --new option.
>        Allows to re-use a branch-name and may drop commits
>        [resetting it].

Yes, it is shorter, but now it doesn't even say what it does.
Martin July 12, 2021, 4:33 p.m. UTC | #77
On 12/07/2021 18:28, Felipe Contreras wrote:
> Martin wrote:
>> On 11/07/2021 01:35, Felipe Contreras wrote:
> 
>>> Do this:
>>>
>>>     -N <branch>::
>>>       Create a new branch like '--new', but if it already exists reset it
>>>       like '--reset'.
> 
>> Or even shorter
>>         See the --new option.
>>         Allows to re-use a branch-name and may drop commits
>>         [resetting it].
> 
> Yes, it is shorter, but now it doesn't even say what it does.
> 

Ok instead of " see the --new option"
use "Same as the --new option, but allows...."
Felipe Contreras July 12, 2021, 4:34 p.m. UTC | #78
Martin wrote:
> On 11/07/2021 09:57, Sergey Organov wrote:
> > Martin <git@mfriebe.de> writes:
> > 
> > 
> > [...]
> > 
> >> Currently only the branch is mentioned.
> >> Currently nothing does explicitly say that *commits* can be affected.
> > 
> > Commits cannot be immediately affected. One of the most essential
> > features of Git is that commits could only be affected (deleted) by
> > garbage collection. That's what makes Git so nicely safe in operation.
> > 
> > It'd be unfortunate to have statements in the manual pages that
> > contradict this.
> 
> Tell that a new user, who never heard of "dangling commits" or the reflog.

The user doesn't need to understand what "dangling comments" are, not at
this point. All she needs is to know is that there's a concept she
doesn't understand yet.

> For ages, I wondered what git fsck meant by "dangling commits" and why 
> my repro always had "that problem".
> And what I might do with that hash it gave me.

Yes, but it's a thousand times better to not know what "dangling
commits" are, than to incorrectly think commits are somehow gone
forever.

It is fine that the user has knowledge gaps, and it is fine for the user
knows she has knowledge gaps.
Martin July 12, 2021, 4:39 p.m. UTC | #79
On 12/07/2021 18:24, Felipe Contreras wrote:
> Sergey Organov wrote:
> Even standardizing `git branch` would be an almost-impossible task, even
> if we manage to convince others. `git new branch` even more impossible.
> 

Not sure but from the glance at hg that I took, they seem to use the 
plural for nouns.

So then we could have

   git branch <new-branch-name>

   git branches new   // long version
   git branches list
   git branches delete
   ....

However, standardizing to a fixed verb/noun rule will still be more than 
a challenge.

The above would as guildeline be

   git verb
or
   git plural-noun verb

Yet try to do that with
   git status
   git log

I don't see how a better alternative for those can be found. One that 
actually is accepted because it's better, not just because it follows a 
rule.

status, is not a verb
log is the wrong verb, or again a noun.
Felipe Contreras July 12, 2021, 4:44 p.m. UTC | #80
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Sergey Organov wrote:
> 
> [...]
> 
> >> Creating (a branch) is fundamentally different operation than switching
> >> to (a branch), and that's why the former doesn't fit into "git switch".
> >
> > Not in my mind. Instead of switching to an existing branch, I'm switching
> > to a new branch, which is easily understood by
> > `git switch --new branch`.
> 
> To me:
> 
> "create a new branch" is basic operation.
> 
> "switch to another branch" is basic operation.
> 
> "create a new branch and then switch to it" is compound operation.

Compound operations soon become basic operations in the mind of an
expert.

Lifting your feet, and then landing your feet might be basic operations
when you are 1 yo, but soon enough they become "walking".

Similarly checking out a commit and then cherry-picking a sequence of
commits while resolving conflicts becomes "rebasing".

In my mind I'm not doing two operations, it's one operation with a
modifier:

  git switch --new branch

--new is an adverb, not an operation.
Felipe Contreras July 12, 2021, 4:55 p.m. UTC | #81
Sergey Organov wrote:
> "Kerry, Richard" <richard.kerry@atos.net> writes:

> > If I remember correctly, "branch" is used in Subversion and CVS only
> > for the creation of a branch. Likewise "tag" for creating a tag.
> > And I think they both use "update" to load the required
> > branch/tag/commit into the current working area.
> >
> > If git were to do that then I think we might get around some of this
> > confusion.
> >
> > In that case:
> > git branch = create a branch
> 
> Sorry, it's too late. I don't think we can actually do it.
> 
> > git tag = create a tag
> 
> Ditto. Too late.

It's never too late consider what would have been the correct UI.

Even if ultimately unachievable, exploring these ideas might give you
other ideas that are more achievable.
Felipe Contreras July 12, 2021, 4:58 p.m. UTC | #82
Martin wrote:
> On 12/07/2021 18:28, Felipe Contreras wrote:
> > Martin wrote:
> >> On 11/07/2021 01:35, Felipe Contreras wrote:
> > 
> >>> Do this:
> >>>
> >>>     -N <branch>::
> >>>       Create a new branch like '--new', but if it already exists reset it
> >>>       like '--reset'.
> > 
> >> Or even shorter
> >>         See the --new option.
> >>         Allows to re-use a branch-name and may drop commits
> >>         [resetting it].
> > 
> > Yes, it is shorter, but now it doesn't even say what it does.
> > 
> 
> Ok instead of " see the --new option"
> use "Same as the --new option, but allows...."

Yeah, that explains more, but what happend when you use a branch name
that already exists? Still not explained.
Felipe Contreras July 12, 2021, 5:09 p.m. UTC | #83
Martin wrote:
> On 12/07/2021 18:24, Felipe Contreras wrote:
> > Sergey Organov wrote:
> > Even standardizing `git branch` would be an almost-impossible task, even
> > if we manage to convince others. `git new branch` even more impossible.
> > 
> 
> Not sure but from the glance at hg that I took, they seem to use the 
> plural for nouns.
> 
> So then we could have
> 
>    git branch <new-branch-name>
> 
>    git branches new   // long version
>    git branches list
>    git branches delete
>    ....
> 
> However, standardizing to a fixed verb/noun rule will still be more than 
> a challenge.
> 
> The above would as guildeline be
> 
>    git verb
> or
>    git plural-noun verb

I don't see what's wrong with considering the second form a subcommand:

  git $subcommand $verb

Like `git bisect start`. That way you could consider `branches` to be a
subcommand, it doesn't need to be a plural noun.

> Yet try to do that with
>    git status
>    git log
> 
> I don't see how a better alternative for those can be found. One that 
> actually is accepted because it's better, not just because it follows a 
> rule.
> 
> status, is not a verb
> log is the wrong verb, or again a noun.

If `git branch` is a shorthand for `git branches new`, the you could
consider `git status` to be the a shortcut for `git status show`, but
since there's no other action to be done with the status subcommand,
then it's always implied.
Martin July 12, 2021, 5:52 p.m. UTC | #84
On 12/07/2021 18:58, Felipe Contreras wrote:
> Martin wrote:
>> On 12/07/2021 18:28, Felipe Contreras wrote:
>>> Martin wrote:
>>>> On 11/07/2021 01:35, Felipe Contreras wrote:
>>>
>>>>> Do this:
>>>>>
>>>>>      -N <branch>::
>>>>>        Create a new branch like '--new', but if it already exists reset it
>>>>>        like '--reset'.
>>>
>>>> Or even shorter
>>>>          See the --new option.
>>>>          Allows to re-use a branch-name and may drop commits
>>>>          [resetting it].
>>>
>>> Yes, it is shorter, but now it doesn't even say what it does.
>>>
>>
>> Ok instead of " see the --new option"
>> use "Same as the --new option, but allows...."
> 
> Yeah, that explains more, but what happend when you use a branch name
> that already exists? Still not explained.
> 


I have to look back in the mails.
There was a lot about getting it shorter, I am happy with a verbose 
version too.

Taking a step back.

> -c <new-branch>
> --create <new-branch>
> 
>     Create a new branch named <new-branch> starting at
>     <start-point> before switching to the branch. 
>     This is a convenient shortcut for:

Should that actually say, that it will fail if the branch-name is 
already taken?
IMHO yes.

The "-C" option could then be (incorporating the "could be lost" from a 
prior mail.

 > -C <new-branch> <commit>
 >    Same the --new option.
 >    But allows to use an existing branch-name. The
 >    [existing|old] branch [for the name] will be removed, and
 >    its commits could be lost.

If using "existing" or "old" then "for the name" is *not* needed, and 
vice versa.

And, yes they can be lost. They can be found again, if one knows where 
to look.
Felipe Contreras July 12, 2021, 7:08 p.m. UTC | #85
Martin wrote:
> On 12/07/2021 18:58, Felipe Contreras wrote:

> The "-C" option could then be (incorporating the "could be lost" from a 
> prior mail.
> 
>  > -C <new-branch> <commit>
>  >    Same the --new option.

But it's not the same as --new.

>  >    But allows to use an existing branch-name.

If this is an essential part of the previous sentence, it should be part
of the sentence:.

  Same [as] the --new option, but allows to use an existing branch name.

But this is wasted space:

  Shouting is the same as talking, but with a different volume.

There's no need for another sentence explaining in what way it is
different (higher volume), do it in the same sentence.

What happens when we use an existing branch name?

>  > The [existing|old] branch [for the name] will be removed,

Except this is a lie. At no point is the branch removed; the branch name
is never gone, neither are the commits.

What is actually happening is that the branch head is changed. That is
all. And as I already explained in the subthread, everyone understands
what changing the branch head does to the branch.

Everyone knows what happens when you reset your computer without saving
your Excel spreadsheet. The word "reset" implies loosing state.

If you don't want to use the word "reset", or the term "branch head",
then you can say:

  Same as --new, but if the branch already exists it's replaced.

This *still* doesn't explain what it is doing, you would need to read
--new.

  Create a new branch like '--new', but if the branch already exists
  it's replaced.

Now it is actually self-contained.

> > and its commits could be lost.

The commits are not lost, they are just not part of this branch anymore.
They could easily be part of another branch already.

  Create a new branch like '--new', but if the branch already exists
  it's replaced. The commits that are initially part of the branch might
  not be part of the branch afterwards.

I think the last sentence is superfluous and obvious. Everyone
understands that if A is replaced by B, B might be different from A, and
thus not everything of A might end up in B.

If you want to send a patch with that unnecessary information, go ahead,
what I'm saying is that if the first part is written correctly the last
part is obvious.

Cheers.
Sergey Organov July 12, 2021, 10:58 p.m. UTC | #86
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>> > Sergey Organov wrote:
>> >> Martin <git@mfriebe.de> writes:
>> >> 
>> >> > On 10/07/2021 12:24, Sergey Organov wrote:
>> >> >> Martin <git@mfriebe.de> writes:
>> >> >>> Actually, "new" or "create" would make sense in "git branch". But in
>> >> >>> git switch, they actually raise the question "create what?" / "new
>> >> >>> what?".
>> >> >> I believe that's because "git switch" tries to do too much.
>> >> >> "git switch"
>> >> >> should rather switch between existing branches, and do nothing else. As
>> >> >> I said once in this discussion already: trouble writing good
>> >> >> documentation is often indication of some flaws in the design.
>> >> >> Creating (a branch) is fundamentally different operation than switching
>> >> >> to (a branch), and that's why the former doesn't fit into "git switch".
>> >> >> 
>> >> >
>> >> > Right, yes. But creating a branch is often followed by switching to it.
>> >> 
>> >> Yep, but here the creation is the primary operation, not switching, so
>> >> putting this into "git switch" looks like design flaw. These 2 actions
>> >> are fine to co-exist in "git branch" = "whatever you want to do to
>> >> branches", but not in "git switch" == "wherever you want to switch".
>> >
>> > I don't see the logic in here.
>> >
>> >   git branch topic # here 'branch' is the verb
>> 
>> Not to me. I assumed the "branch" is always a noun in "git branch", and
>> the actual meaning of this command is:
>> 
>>    git branch [create|new] topic
>> 
>> I.e., creation just being the default action taken on the branch.
>
> The question is not what you assumed, the question is can other people
> assume otherwise?

Sure they can, and that's part of the problem. I described how *I* see
it, as I try to interpret things as coherently as possible, and I don't
like to interpret "branch" in "git branch" as either noun or verb
depending on options when universal interpretation as noun is
sufficient.

>
> "branch" can be a verb, that's a fact.

Yep, who argues?

My argument is that specifically in "git branch" it could be universally
interpreted as noun, but can't universally be interpreted as verb, so
/for me/ it's noun there.

>
>> >> To me, while the latter is obvious, it's verb and specifies the action
>> >> to be performed, the former looks more like "whatever you want to do
>> >> with branches", and thus the "branch" is a noun there and the command
>> >> thus is object-oriented.
>> >
>> > I agree, and I did have indeed noticed the inconsistency. But there's
>> > another category of commands that receive subcommands, like:
>> >
>> >   git remote $subcommand
>> >   git worktree $subcommand
>> >   git bisect $subcommand
>> >
>> > In my opinion `git branch` fits more these subcommand commands, and it
>> > was a mistake to make the subcommands options, it should be:
>> >
>> >   git branch list
>> >   git branch new
>> >   git branch set-upstream
>> >   git branch move
>> >   ...
>> >
>> > Now the verb is crystal-clear.
>> 
>> Yes, lacking (assumed) subcommands is yet another dimension of
>> inconsistencies.
>> 
>> I mean what I'm after is inconsistency of the first argument to "git".
>> It's being the verb more often is where we currently are, at least when
>> considering "primary" commands that "git help" outputs. 
>> 
>> I mean, consider:
>> 
>>    git branch new nice-feature
>> 
>> vs
>> 
>>    git new branch nice-feature
>> 
>> It should have been the latter, when in fact it's currently the
>> [reduced] former.
>
> I disagree. I prefer the former.

     git create branch "nice-feature"

Almost plain human language. Isn't it nice? I mean I fail to see why
you prefer the former, but I don't care that much either.

>
> Either way this is way too far from the original point. I don't think
> you can convince me that `git new branch` makese sense, but there's no
> need for that.
>
> To move forward we need to find consensus, and if you and me agree that
> `git branch new` makes sense, that's where we should focus on.

It does make sense, in isolation.

No, I don't think it's an option, as unfortunately for your preferences,

        git branch new

looks impossible to introduce in a backward compatible manner, nor there
is significant need to, as

        git branch

already does the job, even if by introducing syntax irregularity. 

>
> Even standardizing `git branch` would be an almost-impossible task, even
> if we manage to convince others. `git new branch` even more
> impossible.

Quite an opposite. In fact it's easier to add new ways of doing things
that, provided they prove being useful, eventually obsolete and replace
old ways. "git switch" and "git restore" are recent examples of that.

That's why I started to discuss "git new" that does not yet exist. No, I
don't think it will be there any time soon, as there are more important
things to improve in Git, and then overall consistency of Git command
interfaces is not recognized by the community as a valuable design goal
anyway.

Thus, for foreseeable future we will likely continue to witness hot
discussions of what "looks reasonable" and what not, contenders lacking
common ground that some basic principles of design agreed upon would
have provided.

Thanks,
Felipe Contreras July 12, 2021, 11:36 p.m. UTC | #87
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> > Sergey Organov wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:

> >> > I don't see the logic in here.
> >> >
> >> >   git branch topic # here 'branch' is the verb
> >> 
> >> Not to me. I assumed the "branch" is always a noun in "git branch", and
> >> the actual meaning of this command is:
> >> 
> >>    git branch [create|new] topic
> >> 
> >> I.e., creation just being the default action taken on the branch.
> >
> > The question is not what you assumed, the question is can other people
> > assume otherwise?
> 
> Sure they can, and that's part of the problem. I described how *I* see
> it, as I try to interpret things as coherently as possible, and I don't
> like to interpret "branch" in "git branch" as either noun or verb
> depending on options when universal interpretation as noun is
> sufficient.
> 
> > "branch" can be a verb, that's a fact.
> 
> Yep, who argues?
> 
> My argument is that specifically in "git branch" it could be universally
> interpreted as noun, but can't universally be interpreted as verb, so
> /for me/ it's noun there.

Yeah, but universal interpretation is not part of human language.
Context is always relevant.

Sometimes it can be a verb.

> >> > I agree, and I did have indeed noticed the inconsistency. But there's
> >> > another category of commands that receive subcommands, like:
> >> >
> >> >   git remote $subcommand
> >> >   git worktree $subcommand
> >> >   git bisect $subcommand
> >> >
> >> > In my opinion `git branch` fits more these subcommand commands, and it
> >> > was a mistake to make the subcommands options, it should be:
> >> >
> >> >   git branch list
> >> >   git branch new
> >> >   git branch set-upstream
> >> >   git branch move
> >> >   ...
> >> >
> >> > Now the verb is crystal-clear.
> >> 
> >> Yes, lacking (assumed) subcommands is yet another dimension of
> >> inconsistencies.
> >> 
> >> I mean what I'm after is inconsistency of the first argument to "git".
> >> It's being the verb more often is where we currently are, at least when
> >> considering "primary" commands that "git help" outputs. 
> >> 
> >> I mean, consider:
> >> 
> >>    git branch new nice-feature
> >> 
> >> vs
> >> 
> >>    git new branch nice-feature
> >> 
> >> It should have been the latter, when in fact it's currently the
> >> [reduced] former.
> >
> > I disagree. I prefer the former.
> 
>      git create branch "nice-feature"
> 
> Almost plain human language. Isn't it nice?

But I'm not talking to a human. If I wast talking to a human I would say
"create a branch called X", and "with git" would be implied.

But there's no "create" binary on my system. Why would there be? I've
been using Linux systems for more than 20 years, I know that if I want
to do something with vim, I have to start the command with 'vim'.

> > Even standardizing `git branch` would be an almost-impossible task, even
> > if we manage to convince others. `git new branch` even more
> > impossible.
> 
> Quite an opposite. In fact it's easier to add new ways of doing things
> that, provided they prove being useful, eventually obsolete and replace
> old ways. "git switch" and "git restore" are recent examples of that.

That's what *should* be the case, but this discussion proves that even
experimental commands (which are clearly demarcated as experimental) are
hard to change.

Moreover, keep in mind that the person who managed to introduce both
`git switch` and `git resotre` already left the project. That should
give you a pretty good idea of how much faith he has on these commands
eventually being useful.

Sure, at this point in time introducing `git branch new` might be
impossible, however, `git branch --new` isn't. And if we agree on what
should have been the case for `git branch`, then what should be the case
for `git switch` is more attainable.

Cheers.
Martin July 13, 2021, 10:42 a.m. UTC | #88
On 13/07/2021 00:12, Felipe Contreras wrote:
> Martin wrote:
> A user that does:
> 
>    git switch -n <branch>
> 
> Would naturally expect a new branch to be created.
> 
> If that command creates a new branch safely, why would the user do:
> 
>    git switch -N <branch>
> 
> What do you think the user expects to happen without reading the
> documenation?

Well, first of all what would he think it does if he reads the doc? And 
if that doc looses no (explicit) word on the possible loss?

First of all (not sure, if I mentioned that before), I have seen *many* 
case like that:
The user wants to create a new branch on master "my-feature".
    git switch -c my-feature
Then he realizes that he had not been on master, but on some other 
branch. "-c" now gives an error.
So the  user reads the documentation.
Up to this point, everything is exactly as it should be.
Now what the user reads is that "-C" works if the branch already exists. 
At this point, without being prompted those user will not think of any 
content of the branch (they haven't even added some).
"-C" does in that case what they want.

Of course now, that they had no need to think about any commits, an no 
warning that would have prompted that, they believe "-C" to be save.
Next time they will have commit. And they are gone.

And as for the reflog, look at "checkout -B", "switch -C", "branch -f", 
or "reset".
In the context of re-creating/ressetting a branch, neither of them 
mention how to get it back. (and reflog is something most people learn a 
lot later)

As I said, the first part I have seen many times. The 2nd part, 
obviously only a subset. But that is rather down to people being lucky, 
than to people actually understanding that the commits will disappear.

Now, of course I cannot predict how many people would remember a warning 
it the docs.
But I can tell, if I read a doc, and it says "you may loose...", I will 
pay attention.




> 
> And what do you think they'll expect to happen given this documentation:
> 
>    Create a new branch like '--new', but if the branch already exists
>    it's replaced.
> 
> Forget about what they could misunderstand. Nobody does anything without
> a reason, so what would be the reason why a user does `git switch -N`
> instead of `git switch -n`?
> 

You and I will make the connection between "something happens to the 
branch" and "something happens to the commits".
A lot of people with less experience, who a busy looking through lots of 
stuff to solve their problem, they will not make that connection in that 
particular moment.
Heck, I've seen highly educated people missing far more obvious things 
like that.


> To me this is another instance of "do not drink scorching hot coffee".
> Sure, some users might benefit from reading this, but how many? And how
> many would be annoyed by the obvious unnecessary warning?

Well, at least in the U.S, you apparently have to tell your customers 
that the coffee you sell is hot. (If you recall, there was a "famous" 
court case).
I have always thought, that coffee should be hot (except iced coffee).
You also have to warn people not to put their pets into the microwave. 
Again to me: bleeding obvious.



> 
> Moreover, most users don't even read the documentation. Some might even
> be doing `git switch -h`, and others using zsh completion description.
> So we can't just rely on them reading this line.

Well, so we can't warn the rest? Why do we have docs at all?


> 
> If you are really worried about the user losing information, why don't
> we add a true warning:
> 
>    hint: The previous state of the '%s' branch might have been lost.
>    hint: The id was '%s'.
>    hint:
>    hint: If you didn't intend to do this, you can restore the previous
>    hint: state with:
>    hint:
>    hint:  git reset --hard @{1}
>    hint:
>    hint: Disable this message with "git config advice.switchForceNew false"
> 
> That way the user doesn't need to read the documentation.

Well yes, printing a recovery note, may be another helpful addition.

But as you said, a single way of pushing info, will not reach everyone. 
People putting the command in a script, may not read this.
Btw, a better warning would be similar to the one you get, if you leave 
behind a detached commit.
IIRC, print the sha1, and how to create a branch on that sha1.



Of course there is a different alternative, but IMHO it is overdone.
    git switch -C branch
will only force the current "head value" (I.e. the sha1 used a pointer).
So if you have no commits on that branch, or if they are part of another 
branch, then this will work.

If you stand to "loose" commits, you would have to do:
    git switch -D -C branch

(the D is just an example / other letters/words may be better)
   -D  drop commits


But even, then until that is implemented, a temporary fix by changing 
the docs would still be appropriate.
Sergey Organov July 13, 2021, 10:57 a.m. UTC | #89
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>> > Sergey Organov wrote:
>> 
>> [...]
>> 
>> >> Creating (a branch) is fundamentally different operation than switching
>> >> to (a branch), and that's why the former doesn't fit into "git switch".
>> >
>> > Not in my mind. Instead of switching to an existing branch, I'm switching
>> > to a new branch, which is easily understood by
>> > `git switch --new branch`.
>> 
>> To me:
>> 
>> "create a new branch" is basic operation.
>> 
>> "switch to another branch" is basic operation.
>> 
>> "create a new branch and then switch to it" is compound operation.
>
> Compound operations soon become basic operations in the mind of an
> expert.
>
> Lifting your feet, and then landing your feet might be basic operations
> when you are 1 yo, but soon enough they become "walking".

[caveat: please don't take the rest of this post too seriously]

Yeah, using another name for a compound is yet another option indeed.
"git cretching"?

>
> Similarly checking out a commit and then cherry-picking a sequence of
> commits while resolving conflicts becomes "rebasing".

This is very questionable example. Please don't let me even start on
this.

>
> In my mind I'm not doing two operations, it's one operation with a
> modifier:
>
>   git switch --new branch
>
> --new is an adverb, not an operation.

Well, let's see:

    git walk "First Avenue"
    git walk parkway

then, suddenly:

    git walk --new road

Just an adverb, a modifier. As if no any additional operations were
actually needed. Minecraft: who cares? Just saying.

Thanks,
Martin July 13, 2021, 11:20 a.m. UTC | #90
On 13/07/2021 00:58, Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> I disagree. I prefer the former.
> 
>       git create branch "nice-feature"
> 
> Almost plain human language. Isn't it nice? I mean I fail to see why
> you prefer the former, but I don't care that much either.
> 

But human language is not always the best to express something to a 
computer (sometimes not even to a human). Human language for starters is 
often very ambiguous. (Not in this particular example, but in general).

So even if it looks like human language, its not (not a "duck" either;) ).
It still needs each token (each word is a token) to be documented.

The "create" vs "new" is a good example.
- "creating" still happens when you add commits into the branch (human 
language "branch"). Because that's what the branch wants to be, a series 
of commits. You keep creating it, until its done, then you merge it.
- "new" of course is not a verb...

    git prepare branch
would probably be more accurate.
But I am sure it has flaws too.


> No, I don't think it's an option, as unfortunately for your preferences,
> 
>          git branch new
> 
> looks impossible to introduce in a backward compatible manner, nor there
> is significant need to, as
> 
>          git branch
> 
> already does the job, even if by introducing syntax irregularity.

It is not that it already does the job ("git stash push" and "git stash" 
both do the job)

But in
    git branch new
"new" would be the name of a branch. :(

But at some point, it was indicated that this is about finding 
guidelines for future additions.
So not all old commands need to be "fixed".

Not that they are broken. They are fine. We do not need to break them by 
adding a rule like that.

And
    git noun verb <opts>
    git verb <opts>
works as guideline for new additions.

Of course you want to add
    git verb noun
which I personally to not favour.
Felipe Contreras July 13, 2021, 4:02 p.m. UTC | #91
Martin wrote:
> On 13/07/2021 00:12, Felipe Contreras wrote:
> > Martin wrote:
> > A user that does:
> > 
> >    git switch -n <branch>
> > 
> > Would naturally expect a new branch to be created.
> > 
> > If that command creates a new branch safely, why would the user do:
> > 
> >    git switch -N <branch>
> > 
> > What do you think the user expects to happen without reading the
> > documenation?
> 
> Well, first of all what would he think it does if he reads the doc? And 
> if that doc looses no (explicit) word on the possible loss?
> 
> First of all (not sure, if I mentioned that before), I have seen *many* 
> case like that:
> The user wants to create a new branch on master "my-feature".
>     git switch -c my-feature
> Then he realizes that he had not been on master, but on some other 
> branch. "-c" now gives an error.
> So the  user reads the documentation.
> Up to this point, everything is exactly as it should be.
> Now what the user reads is that "-C" works if the branch already exists. 
> At this point, without being prompted those user will not think of any 
> content of the branch (they haven't even added some).
> "-C" does in that case what they want.
> 
> Of course now, that they had no need to think about any commits, an no 
> warning that would have prompted that, they believe "-C" to be save.

Why would they think -C "saves"? And save how?

> > And what do you think they'll expect to happen given this documentation:
> > 
> >    Create a new branch like '--new', but if the branch already exists
> >    it's replaced.
> > 
> > Forget about what they could misunderstand. Nobody does anything without
> > a reason, so what would be the reason why a user does `git switch -N`
> > instead of `git switch -n`?
> 
> You and I will make the connection between "something happens to the 
> branch" and "something happens to the commits".
> A lot of people with less experience, who a busy looking through lots of 
> stuff to solve their problem, they will not make that connection in that 
> particular moment.
> Heck, I've seen highly educated people missing far more obvious things 
> like that.

Once again I'm not talking about what they could miss, I'm talking about
what they are thinking the command will do.

> > To me this is another instance of "do not drink scorching hot coffee".
> > Sure, some users might benefit from reading this, but how many? And how
> > many would be annoyed by the obvious unnecessary warning?
> 
> Well, at least in the U.S, you apparently have to tell your customers 
> that the coffee you sell is hot. (If you recall, there was a "famous" 
> court case).

Yes, and that's stupid. There's plenty of unnecessary warnings.

  * Do not hold the wrong end of a chainsaw.
  * Do not drive with sun shield in place.  
  * Avoid death.

https://www.forbes.com/2011/02/23/dumbest-warning-labels-entrepreneurs-sales-marketing-warning-labels_slide.html

> I have always thought, that coffee should be hot (except iced coffee).
> You also have to warn people not to put their pets into the microwave. 
> Again to me: bleeding obvious.

The fact that you have to do it in USA doesn't mean you should.

> > Moreover, most users don't even read the documentation. Some might even
> > be doing `git switch -h`, and others using zsh completion description.
> > So we can't just rely on them reading this line.
> 
> Well, so we can't warn the rest? Why do we have docs at all?

To explain how to use commands.

> > If you are really worried about the user losing information, why don't
> > we add a true warning:
> > 
> >    hint: The previous state of the '%s' branch might have been lost.
> >    hint: The id was '%s'.
> >    hint:
> >    hint: If you didn't intend to do this, you can restore the previous
> >    hint: state with:
> >    hint:
> >    hint:  git reset --hard @{1}
> >    hint:
> >    hint: Disable this message with "git config advice.switchForceNew false"
> > 
> > That way the user doesn't need to read the documentation.
> 
> Well yes, printing a recovery note, may be another helpful addition.
> 
> But as you said, a single way of pushing info, will not reach everyone. 

Our objective is not to reach everyone.
Felipe Contreras July 13, 2021, 4:10 p.m. UTC | #92
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> 
> > Sergey Organov wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
> >> 
> >> > Sergey Organov wrote:
> >> 
> >> [...]
> >> 
> >> >> Creating (a branch) is fundamentally different operation than switching
> >> >> to (a branch), and that's why the former doesn't fit into "git switch".
> >> >
> >> > Not in my mind. Instead of switching to an existing branch, I'm switching
> >> > to a new branch, which is easily understood by
> >> > `git switch --new branch`.
> >> 
> >> To me:
> >> 
> >> "create a new branch" is basic operation.
> >> 
> >> "switch to another branch" is basic operation.
> >> 
> >> "create a new branch and then switch to it" is compound operation.
> >
> > Compound operations soon become basic operations in the mind of an
> > expert.
> >
> > Lifting your feet, and then landing your feet might be basic operations
> > when you are 1 yo, but soon enough they become "walking".
> 
> [caveat: please don't take the rest of this post too seriously]
> 
> Yeah, using another name for a compound is yet another option indeed.
> "git cretching"?
> 
> > Similarly checking out a commit and then cherry-picking a sequence of
> > commits while resolving conflicts becomes "rebasing".
> 
> This is very questionable example. Please don't let me even start on
> this.

You don't need to validate the concept, but chunking is an established
concept in cognitive pshychology [1]. It's how humans learn (and
possibly machines too).

> > In my mind I'm not doing two operations, it's one operation with a
> > modifier:
> >
> >   git switch --new branch
> >
> > --new is an adverb, not an operation.
> 
> Well, let's see:
> 
>     git walk "First Avenue"
>     git walk parkway
> 
> then, suddenly:
> 
>     git walk --new road
> 
> Just an adverb, a modifier. As if no any additional operations were
> actually needed. Minecraft: who cares? Just saying.

That's how my mind works, regardless of what you think about it.

And any experienced driver of manual cars would tell you that they don't
think in terms of pressing pedals and moving the gear stick. The
individual operations are meaningless.

[1] https://en.wikipedia.org/wiki/Chunking_(psychology)
Sergey Organov July 14, 2021, 7:14 p.m. UTC | #93
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> 
>> > Sergey Organov wrote:
>> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> >> 
>> >> > Sergey Organov wrote:
>> >> 
>> >> [...]
>> >> 
>> >> >> Creating (a branch) is fundamentally different operation than switching
>> >> >> to (a branch), and that's why the former doesn't fit into "git switch".
>> >> >
>> >> > Not in my mind. Instead of switching to an existing branch, I'm switching
>> >> > to a new branch, which is easily understood by
>> >> > `git switch --new branch`.
>> >> 
>> >> To me:
>> >> 
>> >> "create a new branch" is basic operation.
>> >> 
>> >> "switch to another branch" is basic operation.
>> >> 
>> >> "create a new branch and then switch to it" is compound operation.
>> >
>> > Compound operations soon become basic operations in the mind of an
>> > expert.
>> >
>> > Lifting your feet, and then landing your feet might be basic operations
>> > when you are 1 yo, but soon enough they become "walking".
>> 
>> [caveat: please don't take the rest of this post too seriously]
>> 
>> Yeah, using another name for a compound is yet another option indeed.
>> "git cretching"?
>> 
>> > Similarly checking out a commit and then cherry-picking a sequence of
>> > commits while resolving conflicts becomes "rebasing".
>> 
>> This is very questionable example. Please don't let me even start on
>> this.
>
> You don't need to validate the concept, but chunking is an established
> concept in cognitive pshychology [1]. It's how humans learn (and
> possibly machines too).

The urdge to dive into the muddy waters of psychology to support your
example, where pure logic should probably have sufficed, makes the
example only even more suspect.

Thanks,
Felipe Contreras July 14, 2021, 7:51 p.m. UTC | #94
Sergey Organov wrote:
> Felipe Contreras <felipe.contreras@gmail.com> writes:
> > Sergey Organov wrote:
> >> Felipe Contreras <felipe.contreras@gmail.com> writes:

> >> > Compound operations soon become basic operations in the mind of an
> >> > expert.
> >> >
> >> > Lifting your feet, and then landing your feet might be basic operations
> >> > when you are 1 yo, but soon enough they become "walking".
> >> 
> >> [caveat: please don't take the rest of this post too seriously]
> >> 
> >> Yeah, using another name for a compound is yet another option indeed.
> >> "git cretching"?
> >> 
> >> > Similarly checking out a commit and then cherry-picking a sequence of
> >> > commits while resolving conflicts becomes "rebasing".
> >> 
> >> This is very questionable example. Please don't let me even start on
> >> this.
> >
> > You don't need to validate the concept, but chunking is an established
> > concept in cognitive pshychology [1]. It's how humans learn (and
> > possibly machines too).
> 
> The urdge to dive into the muddy waters of psychology to support your
> example, where pure logic should probably have sufficed, makes the
> example only even more suspect.

Suspect to you, maybe, not to anyone who works in the teaching industry,
where this concept is well understood and accepted.

Cheers.
Sergey Organov July 14, 2021, 8:42 p.m. UTC | #95
Felipe Contreras <felipe.contreras@gmail.com> writes:

> Sergey Organov wrote:
>> Felipe Contreras <felipe.contreras@gmail.com> writes:
>> > Sergey Organov wrote:
>> >> Felipe Contreras <felipe.contreras@gmail.com> writes:
>
>> >> > Compound operations soon become basic operations in the mind of an
>> >> > expert.
>> >> >
>> >> > Lifting your feet, and then landing your feet might be basic operations
>> >> > when you are 1 yo, but soon enough they become "walking".
>> >> 
>> >> [caveat: please don't take the rest of this post too seriously]
>> >> 
>> >> Yeah, using another name for a compound is yet another option indeed.
>> >> "git cretching"?
>> >> 
>> >> 
>> >> This is very questionable example. Please don't let me even start on
>> >> this.
>> >
>> > You don't need to validate the concept, but chunking is an established
>> > concept in cognitive pshychology [1]. It's how humans learn (and
>> > possibly machines too).
>> 
>> The urdge to dive into the muddy waters of psychology to support your
>> example, where pure logic should probably have sufficed, makes the
>> example only even more suspect.
>
> Suspect to you, maybe, not to anyone who works in the teaching industry,
> where this concept is well understood and accepted.

Well, if you've replied to them, then I'm sorry.

To me your particular example:

>>> Similarly checking out a commit and then cherry-picking a sequence
>>> of commits while resolving conflicts becomes "rebasing".

remains controversial; concepts or no concepts.

Thanks,
Martin July 16, 2021, 6:12 p.m. UTC | #96
On 13/07/2021 18:02, Felipe Contreras wrote:
> Martin wrote:
>> Of course now, that they had no need to think about any commits, an no
>> warning that would have prompted that, they believe "-C" to be save.
> 
> Why would they think -C "saves"? And save how?
> 
Sorry, spelling.

"safe"
Martin July 16, 2021, 6:31 p.m. UTC | #97
On 13/07/2021 18:02, Felipe Contreras wrote:
> Martin wrote
>> You and I will make the connection between "something happens to the
>> branch" and "something happens to the commits".
>> A lot of people with less experience, who a busy looking through lots of
>> stuff to solve their problem, they will not make that connection in that
>> particular moment.
>> Heck, I've seen highly educated people missing far more obvious things
>> like that.
> 
> Once again I'm not talking about what they could miss, I'm talking about
> what they are thinking the command will do.


Well they think it creates a new branch with the given name. And that is 
*all* they think.

We can argue as much as we want, that from that thought all else should 
follow, in reality that does not apply.

Or rather it applies only if someone really ask the question. But no one 
asks it.

And that leaves as with the point how much of the so called obvious is 
not being thought about. My answer: Quite a lot, and an important lot too.

If people would always consider the consequences of their actions, this 
world would have a lot less trouble.

But that again gets to the point of what is not thought of. People to 
not think of consequence.

If people a told the consequences some will still ignore it, but some 
will take it into account.


> 
> Yes, and that's stupid. There's plenty of unnecessary warnings.

Yes and that is why we do not need to add
"a solarflare may damage your pc while you perform this action"
(As was previously brought up)


> 
> The fact that you have to do it in USA doesn't mean you should.

Well, yes. But the point is, there are people who miss out for more 
obvious things.
And "loosing commits" as results of an action on "branches" is not that 
obvious. Not if you are new.

I understand that it is as bleeding obvious to you (and me) as "hot coffee".
But neither of us is a new user. Not even the average (I guess)

> 
> Our objective is not to reach everyone.
> 

"everyone that uses git" (and wants to be reached)

And that should be an objective.
Felipe Contreras July 16, 2021, 6:56 p.m. UTC | #98
Martin wrote:
> On 13/07/2021 18:02, Felipe Contreras wrote:
> > Martin wrote
> >> You and I will make the connection between "something happens to the
> >> branch" and "something happens to the commits".
> >> A lot of people with less experience, who a busy looking through lots of
> >> stuff to solve their problem, they will not make that connection in that
> >> particular moment.
> >> Heck, I've seen highly educated people missing far more obvious things
> >> like that.
> > 
> > Once again I'm not talking about what they could miss, I'm talking about
> > what they are thinking the command will do.
> 
> Well they think it creates a new branch with the given name. And that is 
> *all* they think.

No. You are avoiding the question.

-c creates a new branch. Obviously -C creates a new branch too.

Once again, *why* would they pick -C over -c? What do they think it will
do differently?

> > Yes, and that's stupid. There's plenty of unnecessary warnings.
> 
> Yes and that is why we do not need to add
> "a solarflare may damage your pc while you perform this action"
> (As was previously brought up)

Exactly. Unnecessary warnings are unnecessary.

> > The fact that you have to do it in USA doesn't mean you should.
> 
> Well, yes. But the point is, there are people who miss out for more 
> obvious things.

That's almost meaningless. Like, *some* people have more than five
fingers per hand.

Yes, but how many? 1 in 2? 1 in 100? 1 in a million?

Bothering 99.99% of users with a useless warning just because one (who
is not the sharpest pencil in the box) might make a mistake is just not
wise.

> > Our objective is not to reach everyone.
> > 
> 
> "everyone that uses git" (and wants to be reached)
> 
> And that should be an objective.

Impossible objectives are no possible to achieve. Just like trying to be
liked by everyone. You are just going to waste your time, and fail.


That being said, we don't have to agree. And we don't have to
continuously discuss forever. At some point you need to send a new
version of your patch, and I think that point is long past due.

Cheers.
Martin July 17, 2021, 7:02 a.m. UTC | #99
On 16/07/2021 20:56, Felipe Contreras wrote:
> Martin wrote:
>> On 13/07/2021 18:02, Felipe Contreras wrote:
>>> Martin wrote
>>>> You and I will make the connection between "something happens to the
>>>> branch" and "something happens to the commits".
>>>> A lot of people with less experience, who a busy looking through lots of
>>>> stuff to solve their problem, they will not make that connection in that
>>>> particular moment.
>>>> Heck, I've seen highly educated people missing far more obvious things
>>>> like that.
>>>
>>> Once again I'm not talking about what they could miss, I'm talking about
>>> what they are thinking the command will do.
>>
>> Well they think it creates a new branch with the given name. And that is
>> *all* they think.
> 
> No. You are avoiding the question.

I did not avoid it. I answered it, as I understood it. Seems your 
question was not very clear.

> 
> -c creates a new branch. Obviously -C creates a new branch too.
> 
> Once again, *why* would they pick -C over -c? What do they think it will
> do differently?
> 

They think: it makes go away that error message. They can use that 
branchname.

What they do not think is: If I take away the old branch name, what 
happens to the commits in it?

I know, you firmly believe everyone must surely make that conclusion.
But that fails several times..
1) It assumes everyone has enough knowledge to make that conclusion.
While I agree: "they should", I acknowledge they might not.
But, ok. lets say: "there fault". And we don't give a sh*t if others get 
into problem, because they did not read lots of pages and memorized 
every detail...e

2) It assumes the can.
I.e. they have the experience and skill to make the connection. Ok, 
probably 99% can do.

3) It assumes they do (the attempt to make a connection)
And this is my point. Many people will not attempt to think ahead.


People at that moment think about the branch, and the branch only. Many 
will not an all think about commits.

And why would they. In git there are plenty of situations where you can 
delete a branch, without loosing anything else (i.e. without loosing 
commits), because there is an upstream or another local branch.
Until they day that you pick a branch where there is no safety net.



> 
> Bothering 99.99% of users with a useless warning just because one (who
> is not the sharpest pencil in the box) might make a mistake is just not
> wise.
> 
Well, I see you did a survey over a representative group of randomly 
picked people?

Well, yes I cannot tell you any final number. But from what I observed 
from those people that I know, there a quite a few how mistook that 
documentation.
Many (almost most) of those where lucky, in that they had yet only done 
it, when indeed it was safe. But upon question they were surprised that 
it could have gone another way.

Yes that is not representative. But even if I say that in real live the 
quota of such misunderstanding is at only 10% of what I saw, that would 
be a considerable total.


> 
> That being said, we don't have to agree. And we don't have to
> continuously discuss forever. At some point you need to send a new
> version of your patch, and I think that point is long past due.

Yes but part of this has been educative.

(and some of it a bit of fun too)

And I said I will.
But right now, I have things in my live, that prevent me from doing so 
immediately.
They should prevent me from spending time on those mails too, but I 
can't always withstand - so some shortened nights ahead.

I will look at sending a patch, when I have good time to do so without 
being in any rush.
Martin July 17, 2021, 10:07 a.m. UTC | #100
On 17/07/2021 02:56, Felipe Contreras wrote:
> Martin wrote:
> It is the Socratic method. If I tell you "the user will think X" you are
> not going to believe me. Therefore I'm asking you what the user will
> think.
> 
>> But no one is taking them by the hand. No one is asking all those
>> questions to them.
>> So they (new users) will not always make that conclusion.
> 
> What conclusion would they reach?

You realize that your question makes no sense?

If the user does not enter the state of concluding, then they will not 
reach a conclusion at all.

If you want to challenge my statement, that the user does not start 
concluding, then you could ask me: Why?
To which I have to admit, I do not know, I did not ask those who didn't.
And frankly it does not matter. Lets assume we knew "why". Then to 
remedy that cause, some change would be needed. So most likely the doc 
would need to be changed to have some trigger added, to overcome that 
reason. In the end, that means more info in the doc. Same as what is 
already proposed.


>>> What do they think it will happen?
>>
>> They do not think about it at all.
> 
> This doesn't make any sense. They used -C instead of -c for a reason.
For the 4th or 5th time (not going to count the exact number of times I 
have answered the exact same question)

The reason is the branchname was used, and the wanted to use it again. 
The doc says they can use it again. So that is all they want at that moment.

Why is there an extra option for doing this, good question but to them 
at that point in time: not relevant. The doc of the option does not say, 
that there may be any consequences, so that is good enough at that moment.

If you want, you can call them ignorant. But in their defence they may 
not even know that. They have whatever other issues to solve at that 
time. They are happy to have found that option, and they really need to 
return to whatever other stuff they were doing. So they trust the docs, 
and the docs have no explicit warning.

Frankly all the above, is a very common pattern that lots of people show 
at some time or another. Whatever the problem, people go for whatever 
*appears* to be the easy fix. No thought on what will happen after that. 
In German their is a saying "Nach mir die Sinnflut".


>>
>> Because they did not correctly understand what the net protected the from.
> 
> Users should not be executing commands they don't understand. If a user
> doesn't understand what `git delete-this-branch` does, then he shouldn't
> run it.
> 
How can they check they understand it?

See also the example of the person that makes *two* the conclusions. How 
can they tell there is nothing further that they need to conclude?


> If the documentation says a command overwrites a branch, and the user
> runs the command anyway,
So is that an admission that people may not always come to the conclusion?
I.e., what I said: They do not think about that part at all.

 > and the branch is overwritten, git did what the
> user told it to do, and what happened is the responsibility of the user.

Well, that is a matter of philosophical debate.

It does not say "commits may be affected".
I think or hope, that we can agree the effect on commits is something, 
that is to be concluded. The discrepancy we have is, whether it will be 
concluded by all users ("all" is to mean a high percentage leaving no 
significant rest).

If we agree on that "conclusion" statement, then the discrepancy we have 
can be further deducted on whether there is such an "significant rest" 
amount of users.

I believe there is. You do afaik not believe this.

But if there is (or "if there were") such an significant amount of 
users, then it would be a valuable addition to add text, that add the 
result of that conclusion.


So then all the "what would they think..." question do not really 
matter. It does not matter what they think, if it is not what they are 
expected to think. If there is a significant amount of people who for 
any reason whatsoever do not think this, then I believe the 
documentation should respect the fact, that those people exist (and more 
than just as an exception).





>>> Let me try yet another analogy.
>>>
>>> If an alarm clock has two buttons "snooze" and "off".
>> How exactly is that connected?
>> This is a random story. Not an analogy.
> 
> The fact that you don't see the analogy doesn't mean it isn't one.
> 
> Did the user click "off" for a reason?

"Off" is not called "force snooze". Off does not require to conclude 
info, as "-C" does.

Lets say, there is a "change timezone" and a "force change timezone" 
button, and the first one would reject to work, if an alarm is active, 
the 2nd would work even if an alarm exists.
Then that would be an analogy. Because then the user has to figure out, 
that changing the timezone would change the displayed hour, and as a 
consequence clear the alarm.

In your example, where is the conclusion the user has to make?



>>> Mistook it for what? What did they expect it was going to happen?
>> I have answered that in great detail, at least 3 times in this mail thread.
> 
> I'm sorry, but no, "they'll think nothing and they'll do it for no
> reason" is not an answer.
Well, that is not what I wrote.
Martin July 17, 2021, 9:23 p.m. UTC | #101
On 17/07/2021 22:37, Felipe Contreras wrote:
>> If the user does not enter the state of concluding, then they will not
>> reach a conclusion at all.
> 
> If they had not reached a conclussion of what the command would do, then
> they would have not typed the command.

Please re-read my previous answers.

> 
> But they did type the command. Therefore they reached a conclussion about
> what the command would do.

Please re-read my previous answers.

> Just like before I click "send" I had already reached a conclussion
> about what that command will do, otherwise why would I click it?
> 

Are you sure that a
- all your information was by conclusion, and none by other means?
- your conclusions where complete?

For the 2 above points, I pointed out several times that the users had 
partial info, and did not realize that it was incomplete.
They were happy with what the partial info was, therefore they run the 
command.
They never realized there was more.

By clicking "send" you have therefore revealed, that you have either not 
read, or otherwise not realized the content of those previous 
explanations of mine.
Did you really conclude that before clicking send?

> I do not want to challenge your statement. Either you see what is
> obvious to me, or you don't.
I think I do see what is obvious to you. Unfortunately however that what 
you (afaik) think to be obvious, that is wrong.

You appear to believe a partial realization of what -C does is not 
possible. That for some reason, a user either realizes the full extend 
or nothing. No middle ground.

But that middle ground exists.

IIRC It was you who suggested something along the lines "taking steps 
becomes walking".
Well, when I walk, I do not think about the steps. I do not realize 
them, nor conclude their existence.
So it is possible to overlook important parts of a given whole.



> To me it's obvious that effect comes after cause.
Which has nothing to do with the issue at hand.

As soon as you see any part of the effect, that statement is satisfied. 
You cause something, you see some effect. All is good.
But if what you saw is only a fraction of the entire effect, then you 
may never know.

When mankind started burning fuel, did they do so knowingly that it 
would destroy the environment, which they need to survive?
According to you they must have, its an effect. They did the cause, they 
burned the fuel. The must have known the effect it would have.

Well they would have, if it had come with a documentation including a 
proper warning ;)


>> For the 4th or 5th time (not going to count the exact number of times I
>> have answered the exact same question)
> 
> Repeating "I have washed the dishes properly" multiple times doesn't mean
> that you actually did it.

Yes, but you repeat the question.
Rather than pointing out, what in your view is incorrect in my 
statement, you ask the same question again hoping for a different answer.

> 
>> The reason is the branchname was used, and the wanted to use it again.
> 
> What does "use it again" mean?

To them: Create a branch of that name at some commit.
To me: much more.


> It does matter to me. Unless I see evidence for the existence of
> something, I'm not going to *assume* that that something exists.
> 
But you assume that the following exists: "With the current doc, all 
users are fully aware of all consequence"

Yet you have no prove for that. You only can have prove that this 
applies to those you know (or those you ask).

So, since you have no proof, you can not assume that a situation exists 
in which the current doc is sufficient.


>> "Off" is not called "force snooze". Off does not require to conclude
>> info, as "-C" does.
> 
> It's a "yes" or "no" question. Did he have a reason to click "off"?
>

Well in the sense that I understand your question: Yes.

And it did do, what the documentation said. Exactly that, and nothing 
more. So there was no surprise of any kind for that user.

If you mean to say, he fell asleep again, and the doc had no warning 
against that, well good (the doc part, not the falling asleep).
I also do not request, that we add warnings to the git doc that say "you 
may do something wrong, get angry, and in your rage destroy parts of 
your work". No we should not add that.

Those are personal issues. The lost commits are a technical issue.
Felipe Contreras July 19, 2021, 5:51 p.m. UTC | #102
I already told you I don't think this extended discussion is of interest
to the mailing list, and that's why I removed it from the receipients.

I'd be more than happy to continue the discussion privately, but please
don't add the mailing list again. I won't reply here.

Cheers.
diff mbox series

Patch

diff --git a/Documentation/git-switch.txt b/Documentation/git-switch.txt
index 5c438cd5058758..80acafad1f4a46 100644
--- a/Documentation/git-switch.txt
+++ b/Documentation/git-switch.txt
@@ -70,8 +70,12 @@  $ git switch <new-branch>
  -C <new-branch>::
  --force-create <new-branch>::
  	Similar to `--create` except that if `<new-branch>` already
-	exists, it will be reset to `<start-point>`. This is a
-	convenient shortcut for:
+	exists, it will be reset to `<start-point>`.
+	This forces the branch to the new location. It also forces
+	any commit hold by the branch to be dropped, unless the
+	commit is also part of any other branch too. You may
+	therefore loose some of your data.
+	This is a convenient shortcut for:
  +
  ------------
  $ git branch -f <new-branch>