{"thread":{"id":"36801","subject":"Reset by checkout?","startedAt":"2014-05-31T05:46:12Z","lastAt":"2014-06-09T20:12:31Z","messageCount":18,"participants":["Atsushi Nakagawa","Andreas Schwab","Felipe Contreras","Kevin Bracey","Junio C Hamano","Philip Oakley"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"243069","messageId":"20140531144610.754B.B013761@chejz.com","threadId":"36801","inReplyTo":null,"subject":"Reset by checkout?","fromName":"Atsushi Nakagawa","fromEmail":"atnak@chejz.com","sentAt":"2014-05-31T05:46:12Z","receivedAt":"2014-05-31T05:46:12Z","isPatch":false,"sender":{"key":"atnak@chejz.com","avatar":null},"body":"Hi all,\n\nOne of the more underrepresented command I use in git use on a regular\nbasis is this \"reset by checkout\".  It's what's currently achieved by\nthis convoluted expression:\n\n  `git checkout -B <current-branch-name> <tree-ish>`\n\nThis is such an useful notion that I can fathom why there isn't a better,\nfirst-tier, alternative.  i.e.  How come there's no 'git reset\n--checkout'?  The command above even prints \"Reset branch\n'<current-branch-name>'\".\n\nThe problem with 'checkout -B' is it's so easy to mistype!  If I had a\nyen for every time I accidentally left off the '<current-branch-name>'\npart and created a branch named \"<tree-ish>\" at HEAD...\n\nSo, I defined alias.become '!git checkout -B \"$(git symbolic-ref --short\nHEAD)\"' and was happy for a while.  Now, the lack is glaring every time\nI'm explaining workflows to people who don't have the the alias.\n\nOk, the typical use case is: I'm on 'master' and I make a few test\ncommits.  Afterwards, I want to discard the commits and move back to\n'origin/master'.  I could type 'reset --hard origin/master' and risk\nblowing away dirty files if I'm not careful.  Or, I could use \"reset by\ncheckout\" and be carefree.\n\nAny ideas?  Am I doing something wrong or unconventional?\n\nCheers,\n\n\n-- \nAtsushi Nakagawa\n<atnak@chejz.com>\nChanges are made when there is inconvenience.\n"},{"id":"243070","messageId":"m261kmmnva.fsf@linux-m68k.org","threadId":"36801","inReplyTo":"20140531144610.754B.B013761@chejz.com","subject":"Re: Reset by checkout?","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2014-05-31T07:03:05Z","receivedAt":"2014-05-31T07:03:05Z","isPatch":false,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Atsushi Nakagawa <atnak@chejz.com> writes:\n\n> Ok, the typical use case is: I'm on 'master' and I make a few test\n> commits.  Afterwards, I want to discard the commits and move back to\n> 'origin/master'.  I could type 'reset --hard origin/master' and risk\n> blowing away dirty files if I'm not careful.  Or, I could use \"reset by\n> checkout\" and be carefree.\n\nI think that is what 'reset --keep' is doing.\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"243076","messageId":"53898448.8040105@bracey.fi","threadId":"36801","inReplyTo":"20140531144610.754B.B013761@chejz.com","subject":"Re: Reset by checkout?","fromName":"Kevin Bracey","fromEmail":"kevin@bracey.fi","sentAt":"2014-05-31T07:27:04Z","receivedAt":"2014-05-31T07:27:04Z","isPatch":false,"sender":{"key":"kevin@bracey.fi","avatar":"https://avatars.githubusercontent.com/u/96079793?v=4"},"body":"On 31/05/2014 08:46, Atsushi Nakagawa wrote:\n>    `git checkout -B <current-branch-name> <tree-ish>`\n>\n> This is such an useful notion that I can fathom why there isn't a better,\n> first-tier, alternative.q\nI'm 100% in agreement. \"Reset current branch to X\" is an extremely \ncommon operation, and I use this all the time. But having to actually \nname the current branch is silly, and like you, I'm prone to swapping \nthe parameters.\n\nI guess in theory using \"checkout\" allows fancier extra options like \n\"--merge\" and \"--patch\", but I don't think I've ever used those with \ncheckout, let alone this mode, where I really do just want a \"reset\", \nwith safety checks.\n\nThe original \"git reset --hard\" used to be a pretty top-level command. \nIt was used for aborting merges in particular. But I think it now stands \nout as being one of the only really dangerous porcelain commands, and I \ncan't think of any real workflow it's still useful for. Maybe it could \nnow be modified to warn and require \"-f\" to overwrite anything in the \nworking tree?\n\nWhile digging into this, it seems \"git reset --keep\" is actually pretty \nclose to \"git checkout -B <current branch>\". It certainly won't lose \nyour workspace file, but unlike checkout it /does /forget what you've \nstaged, which could be annoying. Maybe that could be modified to keep \nthe index too?\n\n(I like your alias.become - might try that).\n\nKevin\n"},{"id":"243074","messageId":"5389b57138645_68b153b2f8a5@nysa.notmuch","threadId":"36801","inReplyTo":"20140531144610.754B.B013761@chejz.com","subject":"RE: Reset by checkout?","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2014-05-31T10:56:49Z","receivedAt":"2014-05-31T10:56:49Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Atsushi Nakagawa wrote:\n> Ok, the typical use case is: I'm on 'master' and I make a few test\n> commits.  Afterwards, I want to discard the commits and move back to\n> 'origin/master'.  I could type 'reset --hard origin/master' and risk\n> blowing away dirty files if I'm not careful.  Or, I could use \"reset by\n> checkout\" and be carefree.\n\nDoesn't 'git reset orign/master' do that?\n\n-- \nFelipe Contreras\n"},{"id":"243082","messageId":"538a682c9540f_140996b2fc71@nysa.notmuch","threadId":"36801","inReplyTo":"5389b57138645_68b153b2f8a5@nysa.notmuch","subject":"RE: Reset by checkout?","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2014-05-31T23:39:24Z","receivedAt":"2014-05-31T23:39:24Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Felipe Contreras wrote:\n> Atsushi Nakagawa wrote:\n> > Ok, the typical use case is: I'm on 'master' and I make a few test\n> > commits.  Afterwards, I want to discard the commits and move back to\n> > 'origin/master'.  I could type 'reset --hard origin/master' and risk\n> > blowing away dirty files if I'm not careful.  Or, I could use \"reset by\n> > checkout\" and be carefree.\n> \n> Doesn't 'git reset orign/master' do that?\n\nUnless you want to keep the staged files, in which case adding the\n--stage and --work options I originally suggested[1] would help.\n\nSo you could do `git reset --no-stage --no-work origin/master`\n\nWhich is essentially the same as `git update-ref refs/heads/master\norigin/master`.\n\n[1] http://article.gmane.org/gmane.comp.version-control.git/247086\n\n-- \nFelipe Contreras\n"},{"id":"243084","messageId":"20140601115619.8218.B013761@chejz.com","threadId":"36801","inReplyTo":"m261kmmnva.fsf@linux-m68k.org","subject":"Re: Reset by checkout?","fromName":"Atsushi Nakagawa","fromEmail":"atnak@chejz.com","sentAt":"2014-06-01T02:56:21Z","receivedAt":"2014-06-01T02:56:21Z","isPatch":false,"sender":{"key":"atnak@chejz.com","avatar":null},"body":"Andreas Schwab <schwab@linux-m68k.org> wrote:\n> Atsushi Nakagawa <atnak@chejz.com> writes:\n> \n> > Ok, the typical use case is: I'm on 'master' and I make a few test\n> > commits.  Afterwards, I want to discard the commits and move back to\n> > 'origin/master'.  I could type 'reset --hard origin/master' and risk\n> > blowing away dirty files if I'm not careful.  Or, I could use \"reset by\n> > checkout\" and be carefree.\n> \n> I think that is what 'reset --keep' is doing.\n\nI must admit, I didn't know about 'reset --keep'.  As you've pointed out,\nit does look like the command I was after all along!  And to think that\nit's been around since 1.7.1.\n\nThanks!\n\n\n-- \nAtsushi Nakagawa\n<atnak@chejz.com>\nChanges are made when there is inconvenience.\n"},{"id":"243085","messageId":"20140601132624.821C.B013761@chejz.com","threadId":"36801","inReplyTo":"53898448.8040105@bracey.fi","subject":"Re: Reset by checkout?","fromName":"Atsushi Nakagawa","fromEmail":"atnak@chejz.com","sentAt":"2014-06-01T04:26:26Z","receivedAt":"2014-06-01T04:26:26Z","isPatch":false,"sender":{"key":"atnak@chejz.com","avatar":null},"body":"Kevin Bracey <kevin@bracey.fi> wrote:\n> On 31/05/2014 08:46, Atsushi Nakagawa wrote:\n> >    `git checkout -B <current-branch-name> <tree-ish>`\n> >\n> > This is such an useful notion that I can fathom why there isn't a better,\n> > first-tier, alternative.q\n> ...\n> \n> I guess in theory using \"checkout\" allows fancier extra options like\n> \"--merge\" and \"--patch\", but I don't think I've ever used those with\n> checkout, let alone this mode, where I really do just want a \"reset\",\n> with safety checks.\n\nIt does indeed have those fancier options.  However, I just noticed\nthere's even a 'reset --merge'!  And like you say, I can't remember ever\nusing 'checkout --merge' together with 'checkout -B'.\n\n> The original \"git reset --hard\" used to be a pretty top-level command.\n> It was used for aborting merges in particular. But I think it now\n> stands out as being one of the only really dangerous porcelain\n> commands, and I can't think of any real workflow it's still useful\n> for. \n\nMy thoughts exactly.  I think the 'reset --soft/--mixed/--hard' pattern\nis so ingrained, that many people just don't realize there's a safer\nalternative.  (I've heard work mates on more than one occasion\nrecommending 'reset --hard' as the go-to command for discarding commits.)\n\nI believe this is likely because many third party GUI tools just don't\nsupport 'reset --keep', and these tools present a \"Reset...\" dialog with\nthe de facto Soft/Mixed/Hard options.  (Even 'gitk' does this.)\n\n> Maybe it could now be modified to warn and require \"-f\" to\n> overwrite anything in the working tree?\n\nIf people just forgot about '--hard' and used '--mixed/--keep' for\nregular cases, '--hard' would effectively be -f. ;)\n\n> While digging into this, it seems \"git reset --keep\" is actually\n> pretty close to \"git checkout -B <current branch>\". It certainly won't\n> lose your workspace file, but unlike checkout it /does /forget what\n> you've staged, which could be annoying.  Maybe that could be modified\n> to keep the index too?\n\nYes, I didn't realize that 'reset --keep' existed and now I'm feeling a\nbit silly for asking.  The index preservation artefact of 'checkout -B'\ncould be useful, though I can't remember at this point if I've relied on\nit in the past.\n\nThe documetation for 'reset --keep' is ambiguous about what happens to\nindex entries of differing files, so modifying it may be an option if\nthere's demand..  I'm going to try out 'reset --keep' for a while and\nsee if it does get annoying.\n\nCheers,\n\n\n-- \nAtsushi Nakagawa\n<atnak@chejz.com>\nChanges are made when there is inconvenience.\n"},{"id":"243086","messageId":"20140601135853.8223.B013761@chejz.com","threadId":"36801","inReplyTo":"538a682c9540f_140996b2fc71@nysa.notmuch","subject":"Re: Reset by checkout?","fromName":"Atsushi Nakagawa","fromEmail":"atnak@chejz.com","sentAt":"2014-06-01T04:58:55Z","receivedAt":"2014-06-01T04:58:55Z","isPatch":false,"sender":{"key":"atnak@chejz.com","avatar":null},"body":"Felipe Contreras <felipe.contreras@gmail.com> wrote:\n> Felipe Contreras wrote:\n> > Atsushi Nakagawa wrote:\n> > > Ok, the typical use case is: I'm on 'master' and I make a few test\n> > > commits.  Afterwards, I want to discard the commits and move back to\n> > > 'origin/master'.  I could type 'reset --hard origin/master' and risk\n> > > blowing away dirty files if I'm not careful.  Or, I could use \"reset by\n> > > checkout\" and be carefree.\n> > \n> > Doesn't 'git reset orign/master' do that?\n> \n> Unless you want to keep the staged files, in which case adding the\n> --stage and --work options I originally suggested[1] would help.\n> ...\n> \n> [1] http://article.gmane.org/gmane.comp.version-control.git/247086\n\nWhat I was looking for is basically what 'git checkout' does to the\nworking tree when it moves from one commit to another, as well as the\nsemantic checks it offers such that I'm incapable of making an\nunrecoverable change (i.e. It aborts if I'm about to blow away changes\nthat aren't committed.).\n\nI was introduced to 'git reset --keep' in another reply and that for\nmost intent and purpose is what I think I was after.\n\nCheers,\n\n\n-- \nAtsushi Nakagawa\n<atnak@chejz.com>\nChanges are made when there is inconvenience.\n"},{"id":"243090","messageId":"538AE814.2010407@bracey.fi","threadId":"36801","inReplyTo":"20140601132624.821C.B013761@chejz.com","subject":"Re: Reset by checkout?","fromName":"Kevin Bracey","fromEmail":"kevin@bracey.fi","sentAt":"2014-06-01T08:45:08Z","receivedAt":"2014-06-01T08:45:08Z","isPatch":false,"sender":{"key":"kevin@bracey.fi","avatar":"https://avatars.githubusercontent.com/u/96079793?v=4"},"body":"On 01/06/2014 07:26, Atsushi Nakagawa wrote:\n> Kevin Bracey <kevin@bracey.fi> wrote:\n>> The original \"git reset --hard\" used to be a pretty top-level command.\n>> It was used for aborting merges in particular. But I think it now\n>> stands out as being one of the only really dangerous porcelain\n>> commands, and I can't think of any real workflow it's still useful\n>> for.\n> My thoughts exactly.  I think the 'reset --soft/--mixed/--hard' pattern\n> is so ingrained, that many people just don't realize there's a safer\n> alternative.  (I've heard work mates on more than one occasion\n> recommending 'reset --hard' as the go-to command for discarding commits.)\n>\n> I believe this is likely because many third party GUI tools just don't\n> support 'reset --keep', and these tools present a \"Reset...\" dialog with\n> the de facto Soft/Mixed/Hard options.  (Even 'gitk' does this.)\nTrue on the GUI - \"hard\" really needs demotion.\n\nIt would help if the documentation explained better straight off what \nthe different reset modes are intended /for/ in a more practical way, \nrather than the technical jargon.\n\nThere is the \"EXAMPLES\" section, but I think the problem is that it's \nnot clearly laid out by mode, meaning people checking to see what \"git \nreset\" can do are inclined to go first to the \"--xxx\" mode list in \n\"DESCRIPTION\", and stop there, baffled, probably not finding any example \nfor that mode. Maybe the examples should have clearer \"--option\" \nsubheadings? (And all the existing examples for --hard should really \nsuggest --keep instead).\n\nBut given that the \"DISCUSSION\" section now has the full internal \ndetails on what exactly each mode does in every state, and now that we \nhave more than the \"simple\" soft/mixed/hard to deal with, I think the \nmain \"DESCRIPTION\" could be simplified for end users.\n\nMost useful for visualisation, I feel, would just showing what \"git \nstatus\" will look like afterwards, primarily from the point of view of a \n\"backwards\" reset to HEAD~n. In particular, normal users don't think in \nterms of the absolute contents of the index, but rather in terms of diffs.\n\nMaybe something like this:\n\n\"All modes move the current branch pointer so that HEAD now points to \nthe specified commit. ORIG_HEAD is set to the original HEAD location. \nThe modes differ in what happens to the contents of ORIG_HEAD, that are \nno longer on the reset branch; and also what happens to your \nnot-yet-committed changes.\n\n--soft\n      Retains the contents of ORIG_HEAD in the index+work area, leaving \nthe difference as \"changes to be committed\". \"git reset --soft HEAD~1\" \nwould be the first step if you want to remove the last commit, but \nintend to recommit most or all of its changes.\n\n\"git status\" after reset --soft shows:\n\n   To be committed:\n        Changes in ORIG_HEAD relative to HEAD\n        (+Any initial staged changes)\n\n   Not staged:\n        (Any initial unstaged changes)\n\n--mixed (default)\n     Retains the contents of ORIG_HEAD in the work area, leaving the \ndifference as unstaged changes. \"git reset HEAD~1\" would be the first \nstep if you want to remove the last commit, and think again from scratch \nabout which of its changes should be committed.\n\n\"git status\" after reset --mixed shows:\n\n    Not staged:\n        Changes in ORIG_HEAD relative to HEAD\n        (+Any initial staged changes)\n        (+Any initial unstaged changes)\n\n--keep\n    The contents of ORIG_HEAD are dropped, leaving the work area and \nindex containing the new HEAD; your uncommitted changes to unaffected \nfiles are retained. If you have uncommitted changes to any files that \ndiffer in the proposed new HEAD, the operation is refused; you would \nneed to \"git stash\" first. \"git reset --keep HEAD~1\" can be used to \ntotally remove the last commit. (This removal can itself be undone with \nanother \"git reset --keep ORIG_HEAD\", or \"git reset --keep \n<branch>@{<n>}\" - see git-reflog(1)). \"git reset --keep\" is a safe \nalternative to \"--hard\", and is roughly equivalent to \"git checkout -B \n<current-branch-name>\".\n\n\"git status\" after reset --keep shows:\n\n    Not staged\n        (Any initial staged changes)  [should these be left staged, as \nper \"git checkout\"?]\n        (+Any initial unstaged changes)\n\n--hard\n    All other changes are dropped, and the work area and index are \nforcibly reset to the new HEAD. Note that this is dangerous if used \ncarelessly: ALL uncommitted changes to ALL tracked files will be lost, \neven if you were only trying to drop an unrelated commit that didn't \ntouch those files. Older documentation often recommends \"git reset \n--hard\" to undo commits; the newer \"--keep\" option is a much better \nalternative in almost all cases.\n\n\"git status\" after reset --hard shows:\n\n    Work area clean (or untracked files present)\n\n--merge\n    Performs the operation of \"git merge --abort\", intended for use \nduring a merge resolution - see git-merge(1) for more information. This \nform is not normally used directly. [Not really true? Still the best \ncommand to abort \"git checkout --merge\"/\"git stash pop|apply\"? Do those \nneed \"--abort\"?]\n\n\n> If people just forgot about '--hard' and used '--mixed/--keep' for\n> regular cases, '--hard' would effectively be -f. ;)\n\nTrue, but this is quite a big shift. And I think \"--keep\" isn't a clear \nname in isolation. It's named relative to \"--hard\", rather than \nabsolutely...  \"Soft/Mixed/Keep\" is a sensible 3-way choice, but it \ndoesn't sound like it. \"Keep\" keeps less than soft or mixed!\n\nMaybe a new parallel naming scheme is in order? Could we instead phrase \nit from the point of view of what we want to do with the stuff in \nORIG_HEAD? \"--to-index\"/\"--to-workspace\"/\"--drop\"? (--hard deliberately \nexcluded...)\n\nKevin\n"},{"id":"243162","messageId":"xmqqvbsj2e6o.fsf@gitster.dls.corp.google.com","threadId":"36801","inReplyTo":"20140531144610.754B.B013761@chejz.com","subject":"Re: Reset by checkout?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-06-02T21:29:19Z","receivedAt":"2014-06-02T21:29:19Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Atsushi Nakagawa <atnak@chejz.com> writes:\n\n> One of the more underrepresented command I use in git use on a regular\n> basis is this \"reset by checkout\".  It's what's currently achieved by\n> this convoluted expression:\n>\n>   `git checkout -B <current-branch-name> <tree-ish>`\n>\n> This is such an useful notion that I can fathom why there isn't a better,\n> first-tier, alternative.\n\nHmph.  checkout *is* the first-tier way to do this.  Why do you even\nwant to do it via \"reset\"?  Is it because you learned \"reset\" first\nand then learned how \"checkout\" with various modes all do useful\nthings?\n"},{"id":"243163","messageId":"xmqqr4372e28.fsf@gitster.dls.corp.google.com","threadId":"36801","inReplyTo":"xmqqvbsj2e6o.fsf@gitster.dls.corp.google.com","subject":"Re: Reset by checkout?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-06-02T21:31:59Z","receivedAt":"2014-06-02T21:31:59Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Atsushi Nakagawa <atnak@chejz.com> writes:\n>\n>> One of the more underrepresented command I use in git use on a regular\n>> basis is this \"reset by checkout\".  It's what's currently achieved by\n>> this convoluted expression:\n>>\n>>   `git checkout -B <current-branch-name> <tree-ish>`\n>>\n>> This is such an useful notion that I can fathom why there isn't a better,\n>> first-tier, alternative.\n>\n> Hmph.  checkout *is* the first-tier way to do this.  Why do you even\n> want to do it via \"reset\"?  Is it because you learned \"reset\" first\n> and then learned how \"checkout\" with various modes all do useful\n> things?\n\nAhh, the \"branch to be checked out\" being the \"current\" branch is\nindeed strange.  That is what \"reset --keep\" was invented for.\n\nI use \"git checkout -B <something-else> <commit>\" all the time, and\nsomehow I thought that was what you were talking about.\n\nSorry for the noise.\n"},{"id":"243166","messageId":"xmqqmwdv2d08.fsf@gitster.dls.corp.google.com","threadId":"36801","inReplyTo":"538AE814.2010407@bracey.fi","subject":"Re: Reset by checkout?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-06-02T21:54:47Z","receivedAt":"2014-06-02T21:54:47Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Kevin Bracey <kevin@bracey.fi> writes:\n\n> Maybe something like this:\n\nI like the overall direction to re-organize the description by\noperations, but the new description seem to introduce a bit of new\nconfusion.\n\n> \"All modes move the current branch pointer so that HEAD now points to\n> the specified commit. ORIG_HEAD is set to the original HEAD\n> location. The modes differ in what happens to the contents of\n> ORIG_HEAD, that are no longer on the reset branch; and also what\n> happens to your not-yet-committed changes.\n>\n> --soft\n>      Retains the contents of ORIG_HEAD in the index+work area,\n> leaving the difference as \"changes to be committed\".\n\nThis (and everything that talks about ORIG_HEAD) asks the user to\nthink of the working tree state as a combination of \"the state the\ncommit you were on represents\" plus \"the changes you made relative\nto it\".\n\nGiven that everything Git records is a whole-tree snapshot, \"state\"\n(not \"changes\"), and that is how tutorials teach Git, I wonder if\nthe \"what is done to ORIG_HEAD and changes\" gets the user into right\nmindset to understand various modes of operations.\n\nAnd with that \"ORIG_HEAD and changes\" mindset, a --soft reset\nbecomes very hard to explain.  \"ORIG_HEAD and changes (you had\nbefore you issued the 'reset --soft' command)\" are left in the\nindex/work, \"HEAD\" becomes the named commit, \"changes from that\nupdated HEAD\" becomes the original changes (you had since ORIG_HEAD)\nmixed with the differences between ORIG_HEAD and HEAD.\n\nIf you explain this in terms of \"state\", a --soft reset will keep\nthe state of the index and the working tree as-is and changes the\nHEAD pointer to point at a different commit.\n\n> \"git reset --soft HEAD~1\"\n> would be the first step if you want to remove the last commit, but\n> intend to recommit most or all of its changes.\n>\n> \"git status\" after reset --soft shows:\n>\n>   To be committed:\n>        Changes in ORIG_HEAD relative to HEAD\n>        (+Any initial staged changes)\n\nThere would be overlapping parts of \"Any initial staged changes\" and\n\"Changes in ORIG_HEAD relative to HEAD\".  They may be mixed, they may\nbe partly reverted, or they may totally cancel out, depending on the\nchanges the user made since starting to work on ORIG_HEAD.\n\n\n>   Not staged:\n>        (Any initial unstaged changes)\n>\n> --mixed (default)\n>     Retains the contents of ORIG_HEAD in the work area, leaving the\n> difference as unstaged changes.\n\nI am confused by the above the same way.  If the operation \"retains\nthe contents of ORIG_HEAD\" in the working tree, would that mean the\nedit I made is somehow reverted?  No, because you say \"leaving the\ndifference ...\", but then the operation is not really retaining the\ncontents of ORIG_HEAD.  It is leaving the state I had in my working\ntree as-is, regardless of ORIG_HEAD and/or HEAD that is updated.\n\nNot that I can think of a better way to update these descriptions,\nand not that I am opposing to update these descriptions to make it\neasier for new people to learn, but I am not sure if these \"treat\nORIG_HEAD and the changes since that commit as separate entities\"\nis a good approach to do so.\n\nSomewhat frustrated, not by your patch but by being unable to\nsuggest a better way X-<.\n"},{"id":"243205","messageId":"538E26A1.5020509@bracey.fi","threadId":"36801","inReplyTo":"xmqqmwdv2d08.fsf@gitster.dls.corp.google.com","subject":"Re: Reset by checkout?","fromName":"Kevin Bracey","fromEmail":"kevin@bracey.fi","sentAt":"2014-06-03T19:48:49Z","receivedAt":"2014-06-03T19:48:49Z","isPatch":false,"sender":{"key":"kevin@bracey.fi","avatar":"https://avatars.githubusercontent.com/u/96079793?v=4"},"body":"On 03/06/2014 00:54, Junio C Hamano wrote:\n>\n> Not that I can think of a better way to update these descriptions,\n> and not that I am opposing to update these descriptions to make it\n> easier for new people to learn, but I am not sure if these \"treat\n> ORIG_HEAD and the changes since that commit as separate entities\"\n> is a good approach to do so.\n>\n> Somewhat frustrated, not by your patch but by being unable to\n> suggest a better way X-<.\n>\n>\n\nI know. I started off myself knowing what I meant to say, and then got \nbogged down somewhat trying to be detailed enough for a full \nexplanation. I think it's just inherently very hard for anyone to \nvisualise what these do in the /general/ case.\n\nThis is one of those commands where the structure of a man page gets in \nthe way. We have to give a summary of what the mode options /do/, but \nthat's not what people want to know. They want to know what they're /for/.\n\n(And, to some extent, reset, like checkout, is two separate commands. \nOne being the path manipulator, the other being the HEAD manipulator. \nJust bogs us down further).\n\nI think these are the most important HEAD resets, covering 95%+ of uses:\n\n    git reset --soft HEAD~<n>\n    git reset HEAD~<n>\n    git reset --keep HEAD~<n>\n    git reset --keep ORIG_HEAD\n    git reset --keep @{<n>}\n    git reset --keep <some other arbitary place>\n\n(and possibly\n\n    git reset --merge\n\nalthough I think this should be fully covered by \"git xxx --abort\" - \nmaybe a couple of those missing like git stash pop/apply --abort?)\n\nAnything more than those, I think, are pretty far-fetched. I can't 100% \ngrok \"--soft/--mixed\" onto a different branch, for example. (But at \nleast we do define those cases in the A/B/C/D \"discussion\" section for \nthe real geeks.)\n\nMaybe we just need to tighten up the EXAMPLES section? Give it \neasy-to-locate <path>/--soft/--mixed/--keep subheadings, covering all \nthose common use cases (in clean trees...), including a before/after git \nstatus views. Then normal users could skip the top technical section \nwaffling about indexes and go straight there instead.\n\nKevin\n"},{"id":"243253","messageId":"538e429981ec_77a9ef30482@nysa.notmuch","threadId":"36801","inReplyTo":"538E26A1.5020509@bracey.fi","subject":"Re: Reset by checkout?","fromName":"Felipe Contreras","fromEmail":"felipe.contreras@gmail.com","sentAt":"2014-06-03T21:48:09Z","receivedAt":"2014-06-03T21:48:09Z","isPatch":false,"sender":{"key":"felipe.contreras@gmail.com","avatar":"https://avatars.githubusercontent.com/u/8358?v=4"},"body":"Kevin Bracey wrote:\n> Maybe we just need to tighten up the EXAMPLES section? Give it\n> easy-to-locate <path>/--soft/--mixed/--keep subheadings, covering all\n> those common use cases (in clean trees...), including a before/after\n> git status views. Then normal users could skip the top technical\n> section waffling about indexes and go straight there instead.\n\nOr maybe we need to have sane options, like --stage, --work, and --keep.\n\n-- \nFelipe Contreras\n"},{"id":"243570","messageId":"20140607135439.7893.B013761@chejz.com","threadId":"36801","inReplyTo":"538AE814.2010407@bracey.fi","subject":"Re: Reset by checkout?","fromName":"Atsushi Nakagawa","fromEmail":"atnak@chejz.com","sentAt":"2014-06-07T04:54:42Z","receivedAt":"2014-06-07T04:54:42Z","isPatch":false,"sender":{"key":"atnak@chejz.com","avatar":null},"body":"Kevin Bracey <kevin@bracey.fi> wrote:\n> On 01/06/2014 07:26, Atsushi Nakagawa wrote:\n> > Kevin Bracey <kevin@bracey.fi> wrote:\n> >> The original \"git reset --hard\" used to be a pretty top-level command.\n> >> It was used for aborting merges in particular. But I think it now\n> >> stands out as being one of the only really dangerous porcelain\n> >> commands, and I can't think of any real workflow it's still useful\n> >> for.\n> > My thoughts exactly.  I think the 'reset --soft/--mixed/--hard' pattern\n> > is so ingrained, that many people just don't realize there's a safer\n> > alternative.  (I've heard work mates on more than one occasion\n> > recommending 'reset --hard' as the go-to command for discarding commits.)\n> >\n> > I believe this is likely because many third party GUI tools just don't\n> > support 'reset --keep', and these tools present a \"Reset...\" dialog with\n> > the de facto Soft/Mixed/Hard options.  (Even 'gitk' does this.)\n> True on the GUI - \"hard\" really needs demotion.\n> \n> It would help if the documentation explained better straight off what\n> the different reset modes are intended /for/ in a more practical way,\n> rather than the technical jargon.\n\nOn one hand, I agree that improving man git-reset and making it easier\nto understand would be of benefit.\n\nHowever, one of the main culprits of confusion here seems to be the mere\nexistance of '--keep', which is somewhat of a conceptual black sheep.\n\nThe --soft/--mixed/--hard trio seems quite easy to explain, /if/ you\ndidn't need to also explain --keep...\n\nTo that end, I'm wondering if it's better to just deprecate 'reset\n--keep' and shift the use-case over to 'checkout':\n\ncheckout [-u|--update] [<commit>|<branch>]\n\n-u\n--update\n    Rather than checking out a branch to work on it, check out a commit\n    and reset the current branch to that commit.\n\n    This is functionally equivalent to 'checkout -B CURRENT_BRANCH <commit>'.\n\n    (...Maybe a warning here about commits becoming unreachable...)\n\n\nThen, as an added bonus, anything I've staged is kept intact.  *And*, I\ncan attempt 'checkout -u --merge' if I'm feeling particulary careless.\n\n> --hard\n>     All [] changes are dropped[] and the [working tree] and index are\n>     forcibly reset to the [state of <commit>].  Note that this is\n>     dangerous if used carelessly.  ALL uncommitted changes to ALL\n>     tracked files will be lost[].\n>\n>     Older documentation often recommends \"git reset --hard\" to\n>     undo commits; the newer \"--keep\" option is [safer and is now the\n>     recommended] alternative [for use in this situation].\n\nI like this explaination of '--hard' and prefer it over current, which\ndoesn't much explain the gravity of the command.  I've made some edits\nabove.\n\n> --merge\n>     Performs the operation of \"git merge --abort\", intended for use\n>     during a merge resolution - see git-merge(1) for more information.\n>     This form is not normally used directly.\n\nAha, so that's what that's for.  I couldn't really understand the\nexplanation in the current manpage, but your version at least tells me\nthat it's an option I don't need to worry about.\n\nCheers,\n\n\n-- \nAtsushi Nakagawa\n<atnak@chejz.com>\nChanges are made when there is inconvenience.\n"},{"id":"243571","messageId":"20140607135556.7894.B013761@chejz.com","threadId":"36801","inReplyTo":"20140601132624.821C.B013761@chejz.com","subject":"Re: Reset by checkout?","fromName":"Atsushi Nakagawa","fromEmail":"atnak@chejz.com","sentAt":"2014-06-07T04:55:58Z","receivedAt":"2014-06-07T04:55:58Z","isPatch":false,"sender":{"key":"atnak@chejz.com","avatar":null},"body":"Atsushi Nakagawa <atnak@chejz.com> wrote:\n> Kevin Bracey <kevin@bracey.fi> wrote:\n> > On 31/05/2014 08:46, Atsushi Nakagawa wrote:\n> > >    `git checkout -B <current-branch-name> <tree-ish>`\n> > >\n> > > This is such an useful notion that I can fathom why there isn't a better,\n> > > first-tier, alternative.q\n> > ...\n> > \n> > I guess in theory using \"checkout\" allows fancier extra options like\n> > \"--merge\" and \"--patch\", but I don't think I've ever used those with\n> > checkout, let alone this mode, where I really do just want a \"reset\",\n> > with safety checks.\n> \n> It does indeed have those fancier options.  However, I just noticed\n> there's even a 'reset --merge'!  And like you say, I can't remember ever\n> using 'checkout --merge' together with 'checkout -B'.\n\nI'd assumed 'reset --merge' was like 'checkout --merge' and was elated..,\nbut it was something else entirely.\n\nCheers,\n\n\n-- \nAtsushi Nakagawa\n<atnak@chejz.com>\nChanges are made when there is inconvenience.\n"},{"id":"243595","messageId":"241E3E5EB7AE44E6821EA5DFAA24C28F@PhilipOakley","threadId":"36801","inReplyTo":"20140607135439.7893.B013761@chejz.com","subject":"Re: Reset by checkout?","fromName":"Philip Oakley","fromEmail":"philipoakley@iee.org","sentAt":"2014-06-07T14:52:58Z","receivedAt":"2014-06-07T14:52:58Z","isPatch":false,"sender":{"key":"philipoakley@iee.email","avatar":"https://avatars.githubusercontent.com/u/914343?v=4"},"body":"From: \"Atsushi Nakagawa\" <atnak@chejz.com>\n> Kevin Bracey <kevin@bracey.fi> wrote:\n>> On 01/06/2014 07:26, Atsushi Nakagawa wrote:\n>> > Kevin Bracey <kevin@bracey.fi> wrote:\n>> >> The original \"git reset --hard\" used to be a pretty top-level \n>> >> command.\n>> >> It was used for aborting merges in particular. But I think it now\n>> >> stands out as being one of the only really dangerous porcelain\n>> >> commands, and I can't think of any real workflow it's still useful\n>> >> for.\n>> > My thoughts exactly.  I think the 'reset --soft/--mixed/--hard' \n>> > pattern\n>> > is so ingrained, that many people just don't realize there's a \n>> > safer\n>> > alternative.  (I've heard work mates on more than one occasion\n>> > recommending 'reset --hard' as the go-to command for discarding \n>> > commits.)\n>> >\n>> > I believe this is likely because many third party GUI tools just \n>> > don't\n>> > support 'reset --keep', and these tools present a \"Reset...\" dialog \n>> > with\n>> > the de facto Soft/Mixed/Hard options.  (Even 'gitk' does this.)\n>> True on the GUI - \"hard\" really needs demotion.\n>>\n>> It would help if the documentation explained better straight off what\n>> the different reset modes are intended /for/ in a more practical way,\n>> rather than the technical jargon.\n>\n> On one hand, I agree that improving man git-reset and making it easier\n> to understand would be of benefit.\n>\n> However, one of the main culprits of confusion here seems to be the \n> mere\n> existance of '--keep', which is somewhat of a conceptual black sheep.\n>\n> The --soft/--mixed/--hard trio seems quite easy to explain, /if/ you\n> didn't need to also explain --keep...\n>\n> To that end, I'm wondering if it's better to just deprecate 'reset\n> --keep' and shift the use-case over to 'checkout':\n>\n> checkout [-u|--update] [<commit>|<branch>]\n>\n> -u\n> --update\n>    Rather than checking out a branch to work on it, check out a commit\n>    and reset the current branch to that commit.\n>\n>    This is functionally equivalent to 'checkout -B CURRENT_BRANCH \n> <commit>'.\n>\n>    (...Maybe a warning here about commits becoming unreachable...)\n>\n>\n> Then, as an added bonus, anything I've staged is kept intact.  *And*, \n> I\n> can attempt 'checkout -u --merge' if I'm feeling particulary careless.\n>\n>> --hard\n>>     All [] changes are dropped[] and the [working tree] and index are\n>>     forcibly reset to the [state of <commit>].  Note that this is\n>>     dangerous if used carelessly.  ALL uncommitted changes to ALL\n>>     tracked files will be lost[].\n>>\n>>     Older documentation often recommends \"git reset --hard\" to\n>>     undo commits; the newer \"--keep\" option is [safer and is now the\n>>     recommended] alternative [for use in this situation].\n>\n> I like this explaination of '--hard' and prefer it over current, which\n> doesn't much explain the gravity of the command.  I've made some edits\n> above.\n>\n>> --merge\n>>     Performs the operation of \"git merge --abort\", intended for use\n>>     during a merge resolution - see git-merge(1) for more \n>> information.\n>>     This form is not normally used directly.\n>\n> Aha, so that's what that's for.  I couldn't really understand the\n> explanation in the current manpage, but your version at least tells me\n> that it's an option I don't need to worry about.\n>\n\nJust to say there has been a similar confusion about 'git reset' \nreported on the Git Users group for the case of reset with added \n(staged), but uncommitted changes being wiped out, which simlarly \nreports on the difficulty of explaining some of the conditions \nespecially when some are wrong ;-)\n\n https://groups.google.com/forum/#!topic/git-users/27_FxIV_100\n\n\n--\nPhilip \n"},{"id":"243674","messageId":"5396152F.4020704@bracey.fi","threadId":"36801","inReplyTo":"241E3E5EB7AE44E6821EA5DFAA24C28F@PhilipOakley","subject":"Re: Reset by checkout?","fromName":"Kevin Bracey","fromEmail":"kevin@bracey.fi","sentAt":"2014-06-09T20:12:31Z","receivedAt":"2014-06-09T20:12:31Z","isPatch":false,"sender":{"key":"kevin@bracey.fi","avatar":"https://avatars.githubusercontent.com/u/96079793?v=4"},"body":"On 07/06/2014 17:52, Philip Oakley wrote:\n>\n>\n> Just to say there has been a similar confusion about 'git reset' \n> reported on the Git Users group for the case of reset with added \n> (staged), but uncommitted changes being wiped out, which simlarly \n> reports on the difficulty of explaining some of the conditions \n> especially when some are wrong ;-)\n>\n> https://groups.google.com/forum/#!topic/git-users/27_FxIV_100\n\nI'm coming around to the view that \"git reset <mode>\" should be (almost) \ndemoted to plumbing, leaving only the \"reset <file>\" that reverses \"add \n<file>\" as everyday Porcelain.\n\nI think \"reset --keep\" and \"--merge\" were a step in the wrong direction, \nat least for the Porcelain - trying to make reset <mode> \"more useful\", \nrather than less necessary. Normal users shouldn't be needing to touch \nthese hard-to-explain-and-slightly-dangerous commands.\n\nThe addition of \"--abort\" to merge and other commands was much more \nsolid. They helped a lot, and I think we should follow that model by \nadding \"--undo\" to various commands. That would mop up all the common \n\"reset\"s, in conjunction with Atsushi's proposed \"checkout -u\" \nalternative to -B, which I quite like.\n\nMain few:\n\ncommit --undo = reset --soft HEAD^\nmerge --undo  = reset --keep HEAD^\nrebase --undo = reset --keep ORIG_HEAD   [bug report: rebase -p doesn't \nset ORIG_HEAD reliably]\npull --undo = merge/rebase --undo depending on rebase settings [could we \ngo nuts and undo the fetch too?]\n\nBonus:\n\ncommit --amend --undo: reset --soft HEAD@{1}\n\nThe undos can also have a bit of extra veneer that checks the log/reflog \nfor whether it matches the proposed undo, and also checks the upstream \nto see if the thing being undone is already public.\n\nGiven those, I honestly don't think I'd ever need to explain git reset \n<mode> to anyone again. Which would be nice...\n\n(Note I propose no \"--mixed\" equivalent for the commit undos, but it's \neasy enough to follow the \"commit --undo\" with a normal \"git reset\". I'd \nrather re-document the normal git reset under \"commit --undo\" than add \nand document yet another option).\n\nKevin\n"}]}