{"thread":{"id":"56025","subject":"feedback/idea about \"switch -C\" force create","startedAt":"2021-06-29T11:20:02Z","lastAt":"2021-06-29T15:11:13Z","messageCount":4,"participants":["Martin","Ævar Arnfjörð Bjarmason"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"428738","messageId":"20eb626d-89b4-fe2a-7cf4-c596b634f0f8@mfriebe.de","threadId":"56025","inReplyTo":null,"subject":"feedback/idea about \"switch -C\" force create","fromName":"Martin","fromEmail":"git@mfriebe.de","sentAt":"2021-06-29T11:11:49Z","receivedAt":"2021-06-29T11:20:02Z","isPatch":false,"sender":{"key":"git@mfriebe.de","avatar":null},"body":"First of all, my first post, hope it's the correct place.\n\nI've been using the new git switch for some time, and also I have helped \npeople new to git.\nWhen people are new to git, I try to avoid introducing them to commands \nthat can loose them commits (such as git reset).\n\n\"git switch\" however has to be on the list of commands that new user \nhave to learn early, but unfortunately when used with \"-C\" it may cause \nthe loss of commits.\nI am aware, it is a force option. But I still think it may be better if \nit could emit a warning, or even reject the job.\n\nReasons:\n1) Newcomers may not be aware of the extend of such a force at all. \nNewcomers may not expect loss of commits, on such an elementary command.\n\n2) People aware that it is a \"force\" may not be aware of the extend of \nthe force, because there are either up to 2 actions forced.\n\nAction 1)\nThe move of the branch is forced.\n- That means, the info which commit was on the top of the branch before \nwill be lost.\n- Also the move may affect push-ability without \"force\"\n\nAction 2)\nThe commit may be lost (except for the reflog, but many less experienced \npeople do not know that).\nThis loss is dependent on other factors. It may or may not happen.\nBecause it does not always happen, people may not expect it.\n\nAs a result:\n- A user could believe the force is for the effect on the branch, and be \nunaware of the loss of commit\n- A user (ever experienced) could opt for the force in the good belief \nthat their commits are held by other branches, when maybe they are not.\n\nTherefore I believe, it would be best, if   git -C  branch new-location\nwould give an error, if this will lose commits.\n\nThere could be\n- a git config to  toggle this\n- an additional command line option to extend the force to drop commits\n\n\nI would like to know if that idea might in general be acceptable at all.\nIf so, where it could or should be made as a feature request \n(unfortunately I wont be able to provide a patch myself)\n\n\nOn top, I would propose that the documentation of the current behaviour \nshould be made more clear.\n\nhttps://git-scm.com/docs/git-switch about -C / --force-create\n>   Similar to --create except that if <new-branch> already exists, it \n> will be reset to <start-point>. This is a convenient shortcut for:\n>\n>   $ git branch -f <new-branch>\n>   $ git switch <new-branch>\nWhile the word \"force\" is in the option itself, the description does not \nexplain what is forced, or what effects this may have.\nInstead it only refers the user to study another option.\nI believe the documentation should state directly\n- commits currently in part of that branch may be lost [under certain \ncircumstances]\n\nand maybe, but less important\n- the old location of the branch will be lost\n\n\n"},{"id":"428740","messageId":"87wnqcg9k1.fsf@evledraar.gmail.com","threadId":"56025","inReplyTo":"20eb626d-89b4-fe2a-7cf4-c596b634f0f8@mfriebe.de","subject":"Re: feedback/idea about \"switch -C\" force create","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-06-29T11:33:12Z","receivedAt":"2021-06-29T12:05:55Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Jun 29 2021, Martin wrote:\n\n> First of all, my first post, hope it's the correct place.\n\nHi Martin. Welcome, and yes you're in the right place.\n\n> I've been using the new git switch for some time, and also I have\n> helped people new to git.\n> When people are new to git, I try to avoid introducing them to\n> commands that can loose them commits (such as git reset).\n>\n> \"git switch\" however has to be on the list of commands that new user\n> have to learn early, but unfortunately when used with \"-C\" it may\n> cause the loss of commits.\n> I am aware, it is a force option. But I still think it may be better\n> if it could emit a warning, or even reject the job.\n>\n> Reasons:\n> 1) Newcomers may not be aware of the extend of such a force at\n> all. Newcomers may not expect loss of commits, on such an elementary\n> command.\n>\n> 2) People aware that it is a \"force\" may not be aware of the extend of\n> the force, because there are either up to 2 actions forced.\n>\n> Action 1)\n> The move of the branch is forced.\n> - That means, the info which commit was on the top of the branch\n>   before will be lost.\n> - Also the move may affect push-ability without \"force\"\n>\n> Action 2)\n> The commit may be lost (except for the reflog, but many less\n> experienced people do not know that).\n> This loss is dependent on other factors. It may or may not happen.\n> Because it does not always happen, people may not expect it.\n>\n> As a result:\n> - A user could believe the force is for the effect on the branch, and\n>   be unaware of the loss of commit\n> - A user (ever experienced) could opt for the force in the good belief\n>   that their commits are held by other branches, when maybe they are\n>  not.\n\nMakes sense. So basically the users are not using \"-C\" as some typo for\n\"-c\" (e.g. as a result of using the readline M-u key-combo), but mean\n\"force\", they just don't know what \"force\" actually does, and lose data.\n\nWhile I suspect the answer is something like \"they had no idea, git\nerrored, and they tried another option\" I'd be interested if you know\nwhat these users were expecting the \"force version of -c\" to do in this\ncase & what the use-case is.\n\nE.g. are they using this to (re-)create a local topic branch for an\nupstream PR that may or may not have advanced, and they may or may not\nhave local work they forgot about, so they get in the habit of using it\n& sometimes it destroys their data. More below...\n\n> Therefore I believe, it would be best, if   git -C  branch new-location\n> would give an error, if this will lose commits.\n\n...so just to clarify, do you mean that forcing it would be OK if you\nadvance the branch, so in git.git terms you could do:\n\n    git switch -c mynewbranch master # creates new branch\n    git switch -C mynewbranch next\n\nWhich would be OK since what's in \"next\" is in \"master\", But doing the\nreverse would error:\n\n    git switch -c mynewbranch next # creates new branch\n    git switch -C mynewbranch master\n\nDo you think just a plain \"-c\" should also error if you \"lose\" a commit\nby committing on a detached head, or that should be treated differently\n(and if so, why?). I.e.:\n\n    git checkout master^0\n    touch foo && git add foo && git commit -m\"foo\"\n    git switch -c a-branch master\n\nWhich gives you something like:\n    \n    $ git switch -c a-branch master\n    Warning: you are leaving 1 commit behind, not connected to\n    any of your branches:\n    \n      ceccd14206 foo\n    \n    If you want to keep it by creating a new branch, this may be a good time\n    to do so with:\n    \n     git branch <new-branch-name> ceccd14206\n\nI mean, you could pun on that warning for what you're suggesting, but it\nseems to me that it would be sensible that they're consistent, no?\n\nI.e. either we don't error on -C and give a similar useful warning (now\nwe don't say anything), or error on both.\n\nDon't read any of the above as disagreement with your proposal, just\nspitballing ideas & edge cases.\n\n> There could be\n> - a git config to  toggle this\n> - an additional command line option to extend the force to drop commits\n>\n>\n> I would like to know if that idea might in general be acceptable at all.\n> If so, where it could or should be made as a feature request\n> (unfortunately I wont be able to provide a patch myself)\n\nIdeas are most welcome, unfortunately the git project is almost entirely\nlimited by who can come up with patches.\n\nI had some more general proposals for the UI of \"git switch\" recently at\nhttps://lore.kernel.org/git/877dkdwgfe.fsf@evledraar.gmail.com/\n\nNone of that steps on the toes of the idea you have explicitly, but it's\na very adjacent area, so I'd be interested to know what you think.\n\nI haven't had the time or desire to write up complete patches for that\nidea of mine, so it's gone nowhere thus far. I'm afraid yours will\nprobably similarly languish unless you or someone else is willing to\npick it up...\n\n> On top, I would propose that the documentation of the current\n> behaviour should be made more clear.\n>\n> https://git-scm.com/docs/git-switch about -C / --force-create\n>>   Similar to --create except that if <new-branch> already exists, it\n>> will be reset to <start-point>. This is a convenient shortcut for:\n>>\n>>   $ git branch -f <new-branch>\n>>   $ git switch <new-branch>\n> While the word \"force\" is in the option itself, the description does\n> not explain what is forced, or what effects this may have.\n> Instead it only refers the user to study another option.\n> I believe the documentation should state directly\n> - commits currently in part of that branch may be lost [under certain\n>   circumstances]\n>\n> and maybe, but less important\n> - the old location of the branch will be lost\n\n...realistically unless you provide a patch or someone interested\nhappens to pick this up (which I'd deem to be not likely) this\nobservation is likely to just languish in our ML archive.\n\nIf the \"I won't be able to provide a patch\" has to do with not thinking\nyou have the know-how to do so I and others would be happy to\nhelp.\n\nE.g. in the case of the documentation change you can even do the change\nentirely on the github.com/git/git web UI, no C compilation\netc. needed. Our Documentation/SubmittingPatches has more info on the\ngeneral process.\n\nMost of the actual work in doing the sort of change you're suggesting is\nthe leg-work of figuring out the relevant UI edge cases. E.g. I could\nwrite (and could provide you, if you want to run with it) a patch for\n\"git switch\" that dies on \"-C\" unless \"--force-i-really-mean-it\" or\nwhatever is provided. The real work is then going through the test\nfailures, checking/explaining that each thing you need to change as a\nresult makes sense etc.\n\nI think your idea of a config option for this sort of thing might make\nsense, but really only if it's done in a more holistic way. That's\nbasically saying \"I wouldn't like the small change you want unless it's\na more general feature\", but I think for users having just *one* of our\nmany --force options behave this way would just be more confusing than\nnot.\n\nE.g. Emacs has a general facility for disabling the training wheels it\ncomes with by default, certain commands are considered dangerous or\nconfusing to newbies and disabled by default.\n\nI'd think such a mode would be useful e.g. for this, replacing \"git push\n--force\" with the \"--force-with-lease\" option etc., but starting on an\nend-state where a user who means \"--force\" eventually needs to tweak a\n\"yes I mean force\" for all the commands they regularly use would be\nworse for everyone.\n"},{"id":"428746","messageId":"eb3e0019-a127-cf75-6679-347b6d98140d@mfriebe.de","threadId":"56025","inReplyTo":"87wnqcg9k1.fsf@evledraar.gmail.com","subject":"Re: feedback/idea about \"switch -C\" force create","fromName":"Martin","fromEmail":"git@mfriebe.de","sentAt":"2021-06-29T13:44:42Z","receivedAt":"2021-06-29T13:45:31Z","isPatch":false,"sender":{"key":"git@mfriebe.de","avatar":null},"body":"On 29/06/2021 13:33, Ævar Arnfjörð Bjarmason wrote:\n>\n> Makes sense. So basically the users are not using \"-C\" as some typo for\n> \"-c\" (e.g. as a result of using the readline M-u key-combo), but mean\n> \"force\", they just don't know what \"force\" actually does, and lose data.\n>\n> While I suspect the answer is something like \"they had no idea, git\n> errored, and they tried another option\" I'd be interested if you know\n> what these users were expecting the \"force version of -c\" to do in this\n> case & what the use-case is.\nThere are 2 groups of scenarios.\n\n1)\nNew users sometime mess up their branches. They may have started on the \nwrong branch and now want to fix the fork point, or the branch diverted \nfrom the remote and they try to fix the \"cannot fast forward\". Or they \ncreated an earlier branch with the same name, and want to re-use it.\nOften it is something where a local branch needs rebasing.\nIn the last case, the earlier branch should be renamed. So that is a \nreal user error. But new users are not always aware, how commits are \nhold by branches (I.e. they expect them to stay without needing a branch).\n\nOf course, here the extra force flag needed, only helps, if the error \nexplains what is going to happen. So users will not just blindly add the \nforce flag.\n\n2)\nFor the more experienced users, it comes down to oversight. The may \nhonestly believe that there was a 2nd branch holding the commits.\nI've seen people having a 2nd branch on their feature branch. Maybe \nwhere the 2nd branch added some commits on top of the feature branch, \nbut the feature branch has not yet diverged.\n\nHowever if you believe your feature branch hasn't diverged -- while in \nreality it has diverged -- then you would expect commits to be hold by \nthe 2nd branch.\nTherefore you would not expect any loss, from the switch -C.\nThis could be because you want to push feature~10, and then fast forward \nto your 2nd branch and continue on your local work.\n   git switch -C feature  feature~10\n\nAnd that should mean: I have another branch holding the commits, and I \nuse force because I do not care about the exact commit this branch was on.\n\nWhile, if you really mean: \"Move my branch, and drop whatever may get \ndropped\" you do\n   git switch -f -C feature  new-location\nindicating your additional awareness, that there are (or could be) \ncommits that will get dropped (you could do -D instead of -f (Drop/Delete))\n\nSo you give 2 params that say both \"force\", if you mean to force 2 actions.\n\n\n> ...so just to clarify, do you mean that forcing it would be OK if you\n> advance the branch, so in git.git terms you could do:\n>\n>      git switch -c mynewbranch master # creates new branch\n>      git switch -C mynewbranch next\n>\n> Which would be OK since what's in \"next\" is in \"master\", But doing the\n> reverse would error:\n>\n>      git switch -c mynewbranch next # creates new branch\n>      git switch -C mynewbranch master\nYes going forward (move to children of the current commit) will preserve \nthe existing commit, and is fine.\n\nGoing to parents, would loose commits. Unless those commits are hold by \nany other branch.\nI.e. if an feature branch diverge from some child of the current commit, \nthen the feature branch will hold the commit that you move away from.\n\nSo it is not needed for the branch that is moved, to keep holding the \ncommit. Any other branch does fine too.\n\n\n\n> Do you think just a plain \"-c\" should also error if you \"lose\" a commit\n> by committing on a detached head, or that should be treated differently\n> (and if so, why?). I.e.:\n>      \nThis is an interesting idea.\n\nAnd, yes I think that this should be done too.\nAt least for \"git switch\", which being marked as experimental does allow \nfor those changes.\nChanging \"git checkout\", may cause problems for users relaying on the \nbehaviour.\n\nHowever, I agree for the reason of treating it equal, and only for that \nreason.\n\nThe scenario with the detached commit, is something that an experienced \nuser could fall for, if they \"forget\".\n\nBut it is less an issue for newbies. At least, if they are taught to use \n\"git switch\", and don't use \"git checkout\" at all.\n\"git switch\" does not let you detach by accident. It requires you to \nspecify --detach.\nSo users should be aware they are detached.\n\nWith \"git checkout\" you can indeed get easily detached, without having \nintended this. (Back in my newby days, when git switch did not even \nexist as an idea, I learned that the hard way)\n\n\n> I mean, you could pun on that warning for what you're suggesting, but it\n> seems to me that it would be sensible that they're consistent, no?\nYes.\n\n> I.e. either we don't error on -C and give a similar useful warning (now\n> we don't say anything), or error on both.\nYes.\nAdding a warning would be an option too.\n\nI think the error is more sensible though. It makes sure it is not \noverlooked.\nAnd, this is why there are \"force\" options.\n\nI.e. switching from a detached commit, requires one count of force (to \nloose the commit)\ngit switch -f some-branch\n\nRecreation of an existing branch, and at the same time loosing commits, \nshould require to counts of force\ngit switch -f -C existing-branch new-location\n\nIf force is used, the warning can be reduced to\n         $ git switch -f -C existing-branch new-location\n         Info: The commit ABC123456 and <n> parents were dropped.\n\nSince the user forced it, recovery info is not needed. But I would not \nobject to include a line\n        To recover those commits run\n          git branch new-name ABC123456\n\n\n> Don't read any of the above as disagreement with your proposal, just\n> spitballing ideas & edge cases.\nAbsolutely. I did not expect my idea to be pitch perfect.\nIt's an idea, it needs to grow into a well formulated plan.\n\n>> There could be\n>> - a git config to  toggle this\n\n> Ideas are most welcome, unfortunately the git project is almost entirely\n> limited by who can come up with patches.\nI understand this too. I participate in other open source projects, so those limitations are not new to me.\n\n  \n> I had some more general proposals for the UI of \"git switch\" recently at\n> https://lore.kernel.org/git/877dkdwgfe.fsf@evledraar.gmail.com/\n>\n> None of that steps on the toes of the idea you have explicitly, but it's\n> a very adjacent area, so I'd be interested to know what you think.\n\nI will reply in a 2nd email.\n\n  \n\n> If the \"I won't be able to provide a patch\" has to do with not thinking\n> you have the know-how to do so I and others would be happy to\n> help.\nAt the moment it is a time restraint.\n\n\n> E.g. in the case of the documentation change you can even do the change\n> entirely on the github.com/git/git web UI, no C compilation\n> etc. needed. Our Documentation/SubmittingPatches has more info on the\n> general process.\nMaking a mental note of it.\n\n> Most of the actual work in doing the sort of change you're suggesting is\n> the leg-work of figuring out the relevant UI edge cases. E.g. I could\n> write (and could provide you, if you want to run with it) a patch for\n> \"git switch\" that dies on \"-C\" unless \"--force-i-really-mean-it\" or\n> whatever is provided. The real work is then going through the test\n> failures, checking/explaining that each thing you need to change as a\n> result makes sense etc.\nAs I said, it's a not enough time issue.\nAnd C is not my main field. I do not even have a work environment set up \nfor it. Not an excuse, just an \"needs even more spare time\"\nUnfortunately it's not likely I will find that time soon, but if I can \nfind it, and get to the point were I can set up an environment to run \nthe tests, I may come back on this.\nIt is a slim \"if\" though.\n\n\n> I think your idea of a config option for this sort of thing might make\n> sense, but really only if it's done in a more holistic way. That's\n> basically saying \"I wouldn't like the small change you want unless it's\n> a more general feature\", but I think for users having just *one* of our\n> many --force options behave this way would just be more confusing than\n> not.\nAgreed. But then that part can currently be left out.\nIt becomes an entire feature of it's own.\n\n"},{"id":"428755","messageId":"7ba8386c-9355-fa99-3a9f-986a0b616e0f@mfriebe.de","threadId":"56025","inReplyTo":"87wnqcg9k1.fsf@evledraar.gmail.com","subject":"Re: feedback/idea about \"switch -C\" force create","fromName":"Martin","fromEmail":"git@mfriebe.de","sentAt":"2021-06-29T15:01:45Z","receivedAt":"2021-06-29T15:11:13Z","isPatch":false,"sender":{"key":"git@mfriebe.de","avatar":null},"body":"On 29/06/2021 13:33, Ævar Arnfjörð Bjarmason wrote:\n> I had some more general proposals for the UI of \"git switch\" recently at\n> https://lore.kernel.org/git/877dkdwgfe.fsf@evledraar.gmail.com/\n>\n> None of that steps on the toes of the idea you have explicitly, but it's\n> a very adjacent area, so I'd be interested to know what you think.\n>\n\n> I think it's quite confusing that \"git switch\" doesn't switch to a new\n> \"doesnotexist\" branch on something like:\n>\n>      git switch doesnotexist\n>\n> But requires:\n>\n>      git switch -c doesnotexist\n\nI think that creation should require a parameter.\nIf not you end up on a non tracking branch, while you might expect to be \non a local tracking branch.\n\n\n>   But it really\n> should be:\n>\n>      # -n or -N for --new / --new --force (the latter just in case of a\n>      # race, and just for consistency)\n>      git switch -n doesnotexist\n\nThis is an interesting one. I haven't taken the time to check if there \nare other commands where a letter used as option, translates to a \ndifferent option between different commands.\nUsing -n would be ok.\n\nBUT it is only halve the issue\n> (branch: add a --copy (-c) option to go\n> with --move (-m), 2017-06-18) has the knock-on effect that we can't\n> mirror the \"git branch\" UI. I.e. to make \"switch\" be \"branch with\n> checkout\" for these common cases.\neven if -c became -n, there still be plenty of people/scripts who would \nnot be aware.\n\n\"-c\" would have to be disused for a real long time, before I would feel \ncomfortable to use it for another purpose.\n\nSome users are stuck for long time on an old git version, depending on \ntheir OS. When they upgrade they may skip many releases.\nSo they could easily issue a -c for create, and trigger a copy.\n\nAs for \"move\", this is not the most intuitive name for \"rename\" anyway. \n(I get it, move the content to the new name, but its also move the old \nname, since that does not remain)\nBut all good letters are take (branch -r => list remotes)\n\nI can see some sense, in a shortcut for \"copy and switch\".\nBut does git switch, need to have move/rename ?\n\nEspecially in the one branch only specified version\n       git switch -m newname\ndoes the same as\n     git branch -m newname\nThe branch is renamed. There is no actual switch happening. The same \nbranch is still checked out, just under new name.\n\n       git switch -m newname  existingbranch\nThat would be a shortcut for rename, then switch. (not sure if that common)\n\n> I.e. to me the ideal end state would be to deprecate (or at least\n> warn/discourage) the \"git branch -m\" case where it does its own checkout\n> (but for nothing else), and to make \"git switch\" a \"branch with\n> checkout\" with the same -c/-C/-m/-M semantics, just also with a -n/-N\n> for \"create first\".\nI never thought as \"git switch\" as a \"git branch\" replacement.\n\nI think those 2 are (and should be) distinct entities.\nMy understanding is, that \"git switch\" (and restore) are a result of \nthe  fact that \"git checkout\" combined to many functions in one command.\n\nBtw, a general issue...\n\"git reset\" also is a case of \"grab all\".\n\n\n> I.e. to me the ideal end state would be to deprecate (or at least\n> warn/discourage) the \"git branch -m\" case where it does its own checkout\n> (but for nothing else),\nI am missing something?\n   git branch -m\ndoes not seem to perform a checkout?\n\nWell, maybe it is depending on how you view it.\n     git branch --move  current-name   new-name\n\nIf you say, it moves the content of current to new, then yes it does \ncheckout new.\nBut it also does delete current (because the old name no longer exists.)\n\nThis is, why I think the whole think is more of a \"rename\".\nBut if this is a rename command, then you are still on the same branch, \nonly under new name. And then, there was no checkout.\n\n\n> So at the end of the day you still have to use \"git branch\" for these\n> common (at least for me) operations of copy/move, *and* maintain a\n> mental model that \"-c\" means \"xyz\" here, but \"abc\" there.\nI think \"git branch\" should be the main command to deal with branches, \nbut it should not do any checkout.\nIf it currently does \"switch\" depends on what --move really is.\n\n> The \"switch\" command also solves the very real problem (and I believe\n> this was the main motivation) of not knowing beforehand if \"checkout\"\n> will interpret your \"foo\" as a file, a branch or whatever.\nOn top of that, by splitting the different operations that checkout \nperforms to new commands (with IMHO easier to remember name) also makes \nit easier to learn.\nFor a new user checkout just combined to many things.\nFor a seasoned user this is of course not that much of an issue.\n\nFor example  if you give \"git checkout\" a branch name, then you switch \nto that branch. Ok.\nBut If you give \"git checkout\" a branch and a file, you do not switch:  \ngit checkout master~2 Makefile  (get only the file)\n\nThe latter is now\n    git restore --source=master~2  Makefile\n\nIt is a few chars more to type. But it is much more expressive what it does.\nThe command name alone makes it clear, this is not \"switch\".\n\n\nThere are also small improvements, like switch now insists on --detach. \ncheckout would be happy to go without it.\n\n\n\n\n"}]}