Re: Why not git reset --hard <path>?
Show 11 quoted lines
> I agree with you if we limit the scope to "reset --hard" that does
> not mention any commit on the command line (or says "HEAD").
>
> However, for things like:
>
> $ git reset --hard HEAD^ Makefile
> $ git reset --hard HEAD@{4.hours.ago} Makefile
>
> I do not think "reset --hard" is a good match. Conceptually, you
> are grabbing what was stored in a given commit and checking that out
> to your current workspace (that is, the index and the working tree).I actually disagree, BUT that was based on an inaccurate mental model, so I'm not sure if my judgement can be trusted. Still, I'll blather on just to give a different perspective.
To me, "git reset --hard" is "git reset" plus checking out from the index to the working directory. That's the difference and the only difference.
So any difference in behaviour between
git reset --hard <revision> -- <paths>
and
git reset --mixed <revision> -- <paths>
git checkout -- <paths>
needs to be justified. (There might be some if a file does not exist in
the revision.)
Show 7 quoted lines
> All modes of "git reset" are primarily about updating where in the
> history DAG your HEAD points at, and then adjusting your current
> workspace to that update, taking into account the reason why you are
> repointing your HEAD in the history DAG (e.g. when doing --hard
> reset, you want the workspace to match what the commit your HEAD now
> points at; when doing --soft reset, you don't want any changes
> done).
Er... no. Re-pointing HEAD can *only* be done as a global operation. That's the single most fundamental difference between git and CVS.
Any time you specify a path, *obviously* that part can't be done, so git-reset just skips that part and goes on to the index-updating part..
Git reset also skips that part in the single most common invocation scenario: un-doing git-add. That's for a different reason (pointing HEAD to HEAD is a no-op), but it contributes to the mental model that git-reset is fundamentally used for copying from history to the index.
That's my mental model, for what little it's worth (given the caveat above):
- git checkout is fundamentally about copying from the index to the
working directory. If can also move HEAD first (and create branches!)
as a convenience feature.
- git reset is fundamentally about copying from HEAD to the index.
Like git-checkout, it can also move HEAD first (and copy to the working
directory) as a convenience feature.
To me, "git reset" is "throw the changes away and get me back to some previous state". That's why it's the tool I reached for in the merge-conflict situation that started this thread.
I didn't think to try "git checkout" because I needed to overwrite the merge conflict in the index, and I don't think of "git checkout" as doing that. (Globally, it fails if there are unresolved conflits.)