git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Reset by checkout?

From
Kevin Bracey <kevin@bracey.fi>
Date
Jun 1, 2014, 08:45 UTC
Message-ID
<538AE814.2010407@bracey.fi>
In-Reply-To
<20140601132624.821C.B013761@chejz.com>
On 01/06/2014 07:26, Atsushi Nakagawa wrote:
Show 14 quoted lines
> Kevin Bracey <kevin@bracey.fi> wrote:
>> The original "git reset --hard" used to be a pretty top-level command.
>> It was used for aborting merges in particular. But I think it now
>> stands out as being one of the only really dangerous porcelain
>> commands, and I can't think of any real workflow it's still useful
>> for.
> My thoughts exactly.  I think the 'reset --soft/--mixed/--hard' pattern
> is so ingrained, that many people just don't realize there's a safer
> alternative.  (I've heard work mates on more than one occasion
> recommending 'reset --hard' as the go-to command for discarding commits.)
>
> I believe this is likely because many third party GUI tools just don't
> support 'reset --keep', and these tools present a "Reset..." dialog with
> the de facto Soft/Mixed/Hard options.  (Even 'gitk' does this.)
True on the GUI - "hard" really needs demotion.

It would help if the documentation explained better straight off what the different reset modes are intended /for/ in a more practical way, rather than the technical jargon.

There is the "EXAMPLES" section, but I think the problem is that it's not clearly laid out by mode, meaning people checking to see what "git reset" can do are inclined to go first to the "--xxx" mode list in "DESCRIPTION", and stop there, baffled, probably not finding any example for that mode. Maybe the examples should have clearer "--option" subheadings? (And all the existing examples for --hard should really suggest --keep instead).

But given that the "DISCUSSION" section now has the full internal details on what exactly each mode does in every state, and now that we have more than the "simple" soft/mixed/hard to deal with, I think the main "DESCRIPTION" could be simplified for end users.

Most useful for visualisation, I feel, would just showing what "git status" will look like afterwards, primarily from the point of view of a "backwards" reset to HEAD~n. In particular, normal users don't think in terms of the absolute contents of the index, but rather in terms of diffs.

Maybe something like this:

"All modes move the current branch pointer so that HEAD now points to the specified commit. ORIG_HEAD is set to the original HEAD location. The modes differ in what happens to the contents of ORIG_HEAD, that are no longer on the reset branch; and also what happens to your not-yet-committed changes.

--soft
      Retains the contents of ORIG_HEAD in the index+work area, leaving 
the difference as "changes to be committed". "git reset --soft HEAD~1" 
would be the first step if you want to remove the last commit, but 
intend to recommit most or all of its changes.
"git status" after reset --soft shows:
   To be committed:
        Changes in ORIG_HEAD relative to HEAD
        (+Any initial staged changes)
   Not staged:
        (Any initial unstaged changes)
--mixed (default)
     Retains the contents of ORIG_HEAD in the work area, leaving the 
difference as unstaged changes. "git reset HEAD~1" would be the first 
step if you want to remove the last commit, and think again from scratch 
about which of its changes should be committed.
"git status" after reset --mixed shows:
    Not staged:
        Changes in ORIG_HEAD relative to HEAD
        (+Any initial staged changes)
        (+Any initial unstaged changes)
--keep
    The contents of ORIG_HEAD are dropped, leaving the work area and 
index containing the new HEAD; your uncommitted changes to unaffected 
files are retained. If you have uncommitted changes to any files that 
differ in the proposed new HEAD, the operation is refused; you would 
need to "git stash" first. "git reset --keep HEAD~1" can be used to 
totally remove the last commit. (This removal can itself be undone with 
another "git reset --keep ORIG_HEAD", or "git reset --keep 
<branch>@{<n>}" - see git-reflog(1)). "git reset --keep" is a safe 
alternative to "--hard", and is roughly equivalent to "git checkout -B 
<current-branch-name>".
"git status" after reset --keep shows:
    Not staged
        (Any initial staged changes)  [should these be left staged, as 
per "git checkout"?]
        (+Any initial unstaged changes)
--hard
    All other changes are dropped, and the work area and index are 
forcibly reset to the new HEAD. Note that this is dangerous if used 
carelessly: ALL uncommitted changes to ALL tracked files will be lost, 
even if you were only trying to drop an unrelated commit that didn't 
touch those files. Older documentation often recommends "git reset 
--hard" to undo commits; the newer "--keep" option is a much better 
alternative in almost all cases.
"git status" after reset --hard shows:
    Work area clean (or untracked files present)
--merge
    Performs the operation of "git merge --abort", intended for use 
during a merge resolution - see git-merge(1) for more information. This 
form is not normally used directly. [Not really true? Still the best 
command to abort "git checkout --merge"/"git stash pop|apply"? Do those 
need "--abort"?]
> If people just forgot about '--hard' and used '--mixed/--keep' for
> regular cases, '--hard' would effectively be -f. ;)

True, but this is quite a big shift. And I think "--keep" isn't a clear name in isolation. It's named relative to "--hard", rather than absolutely... "Soft/Mixed/Keep" is a sensible 3-way choice, but it doesn't sound like it. "Keep" keeps less than soft or mixed!

Maybe a new parallel naming scheme is in order? Could we instead phrase it from the point of view of what we want to do with the stuff in ORIG_HEAD? "--to-index"/"--to-workspace"/"--drop"? (--hard deliberately excluded...)

Kevin
Previous: Atsushi NakagawaNext: Junio C Hamano
Message 6 of 18 in “Reset by checkout?”
  1. Atsushi NakagawaMay 31, 2014
  2. Andreas SchwabMay 31, 2014
  3. Atsushi NakagawaJun 1, 2014
  4. Kevin BraceyMay 31, 2014
  5. Atsushi NakagawaJun 1, 2014
  6. Kevin BraceyJun 1, 2014
  7. Junio C HamanoJun 2, 2014
  8. Kevin BraceyJun 3, 2014
  9. Felipe ContrerasJun 3, 2014
  10. Atsushi NakagawaJun 7, 2014
  11. Philip OakleyJun 7, 2014
  12. Kevin BraceyJun 9, 2014
  13. Atsushi NakagawaJun 7, 2014
  14. Felipe ContrerasMay 31, 2014
  15. Felipe ContrerasMay 31, 2014
  16. Atsushi NakagawaJun 1, 2014
  17. Junio C HamanoJun 2, 2014
  18. Junio C HamanoJun 2, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.