Message ID | c593a699-eaf2-c7ab-b522-bfd224fce829@mfriebe.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | PATCH: improve git switch documentation | expand |
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.
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.
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.
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.
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.
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.
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.
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,
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: + ------------
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.
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,
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.
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
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.
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>
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,
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.
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,
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?
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/
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.
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
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,
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?
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.
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.
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.
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.
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?
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
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.
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 @`.
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.
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.
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.
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
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.
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
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.
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.
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?
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,
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,
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>`).
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.
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,
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.
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
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`.
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.
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.
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.
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.
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.
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?
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
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.
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...
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,
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,
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].
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).
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,
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,
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,
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.
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"....
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,
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.
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,
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,
> > 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.
"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,
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.
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.
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.
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...."
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.
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.
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.
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.
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.
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.
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.
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.
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,
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.
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.
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,
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.
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.
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)
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,
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.
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,
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"
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.
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.
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.
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.
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.
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 --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>
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(-)