Subject: Re: Reset by checkout?

From: Junio C Hamano <[email-masked]>
Date: Mon, 02 Jun 2014 14:54:47 -0700

Kevin Bracey <[email-masked]> writes:

> Maybe something like this:

I like the overall direction to re-organize the description by
operations, but the new description seem to introduce a bit of new
confusion.

> "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".

This (and everything that talks about ORIG_HEAD) asks the user to
think of the working tree state as a combination of "the state the
commit you were on represents" plus "the changes you made relative
to it".

Given that everything Git records is a whole-tree snapshot, "state"
(not "changes"), and that is how tutorials teach Git, I wonder if
the "what is done to ORIG_HEAD and changes" gets the user into right
mindset to understand various modes of operations.

And with that "ORIG_HEAD and changes" mindset, a --soft reset
becomes very hard to explain.  "ORIG_HEAD and changes (you had
before you issued the 'reset --soft' command)" are left in the
index/work, "HEAD" becomes the named commit, "changes from that
updated HEAD" becomes the original changes (you had since ORIG_HEAD)
mixed with the differences between ORIG_HEAD and HEAD.

If you explain this in terms of "state", a --soft reset will keep
the state of the index and the working tree as-is and changes the
HEAD pointer to point at a different commit.

> "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)

There would be overlapping parts of "Any initial staged changes" and
"Changes in ORIG_HEAD relative to HEAD".  They may be mixed, they may
be partly reverted, or they may totally cancel out, depending on the
changes the user made since starting to work on ORIG_HEAD.

>   Not staged:
>        (Any initial unstaged changes)
>
> --mixed (default)
>     Retains the contents of ORIG_HEAD in the work area, leaving the
> difference as unstaged changes.

I am confused by the above the same way.  If the operation "retains
the contents of ORIG_HEAD" in the working tree, would that mean the
edit I made is somehow reverted?  No, because you say "leaving the
difference ...", but then the operation is not really retaining the
contents of ORIG_HEAD.  It is leaving the state I had in my working
tree as-is, regardless of ORIG_HEAD and/or HEAD that is updated.

Not that I can think of a better way to update these descriptions,
and not that I am opposing to update these descriptions to make it
easier for new people to learn, but I am not sure if these "treat
ORIG_HEAD and the changes since that commit as separate entities"
is a good approach to do so.

Somewhat frustrated, not by your patch but by being unable to
suggest a better way X-<.