Re: Git reset --hard with staged changes

2 messages, 2 authors, 2016-06-16 · open the first message on its own page

Re: Git reset --hard with staged changes

From: Yotam Gingold <hidden>
Date: 2016-06-16 02:19:33

Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
2014-06-10 17:27 GMT+02:00 David Kastrup <dak <at> gnu.org>:
quoted
Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
quoted
...

Hm I see. Even though the documentation doesn't make it very clear
about what happens to such files, it turns out the scenario we
stumbled upon seems to be the special use case after all. Thanks for
shedding some light on this :) I wonder why does git-reset's hard mode
not always remove untracked files then?
Because it never removes them?  Git only removes files once it tracks
them.  This includes the operation of removing _and_ untracking them,
like with git reset --hard.

The only command which explicitly messes with untracked files is
git-clean.

--
David Kastrup
... I couldn't find a definition that backs this in the man
pages (maybe the git-glossary would be a good place for it?), and the
one from the Git-Scm book only confused me in thinking the opposite.
Thanks for the clarification

--
Pierre-François CLEMENT
Application developer at Upcast Social
Jumping into this conversation two years later*. There's confusion about what
constitutes a tracked file for git reset --hard, and good reasons for git reset
--hard's behavior. Nevertheless, I think we can all agree that the man page
entry for git reset --hard is woefully deficient:

--hard Resets the index and working tree. Any changes to tracked files in the
working tree since <commit> are discarded.

This should be clarified to define what a tracked file is. I propose appending:

    A file is considered tracked if it exists in a prior commit or in the
    staging area. Note that a newly added file not in any prior commit will be
    removed.

I would also like to propose that the staging area's tree object be saved,
perhaps in the reflog or perhaps just as a dangling object. This would allow
graceful recovery from git reset --hard. Witness the many questions and answers
on recovery:
    http://stackoverflow.com/questions/7374069/undo-git-reset-hard-with-uncommitted-files-in-the-
staging-area
    http://stackoverflow.com/questions/5788037/recover-from-git-reset-hard
    http://stackoverflow.com/questions/5473/how-can-i-undo-git-reset-hard-head1
    http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html
    https://bani.com.br/2014/10/recovering-lost-files-after-a-git-reset-hard/
    https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c

All of these solutions recover the contents of files, but not their names or the
directory structure. Saving the tree object somewhere (anywhere!) would solve
this problem.

I was bitten by this in a vicious way. I was setting up a new repository for a
bunch of code and data (git init; git add .), changed my mind about adding the
data (git reset --hard), and nearly lost everything. The only tree object that
could be found was an empty one, so I got file contents without names or
directories (not good, because experimental conditions for the data were encoded
in the directory structure).

Cheers,
Yotam

Re: Git reset --hard with staged changes

From: Christian Couder <hidden>
Date: 2016-06-16 02:19:34

On Mon, May 23, 2016 at 2:55 AM, Yotam Gingold [off-list ref] wrote:
Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
quoted
2014-06-10 17:27 GMT+02:00 David Kastrup <dak <at> gnu.org>:
quoted
Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
quoted
...

Hm I see. Even though the documentation doesn't make it very clear
about what happens to such files, it turns out the scenario we
stumbled upon seems to be the special use case after all. Thanks for
shedding some light on this :) I wonder why does git-reset's hard mode
not always remove untracked files then?
Because it never removes them?  Git only removes files once it tracks
them.  This includes the operation of removing _and_ untracking them,
like with git reset --hard.

The only command which explicitly messes with untracked files is
git-clean.

--
David Kastrup
... I couldn't find a definition that backs this in the man
pages (maybe the git-glossary would be a good place for it?), and the
one from the Git-Scm book only confused me in thinking the opposite.
Thanks for the clarification

--
Pierre-François CLEMENT
Application developer at Upcast Social
Jumping into this conversation two years later*. There's confusion about what
constitutes a tracked file for git reset --hard, and good reasons for git reset
--hard's behavior. Nevertheless, I think we can all agree that the man page
entry for git reset --hard is woefully deficient:

--hard Resets the index and working tree. Any changes to tracked files in the
working tree since <commit> are discarded.

This should be clarified to define what a tracked file is. I propose appending:

    A file is considered tracked if it exists in a prior commit or in the
    staging area. Note that a newly added file not in any prior commit will be
    removed.
Would you like to send a patch with something like the above?

I don't know if something about why it is like this, or why it is the
right thing to do, at least for recovering from merges, should be
added though.
I would also like to propose that the staging area's tree object be saved,
perhaps in the reflog or perhaps just as a dangling object. This would allow
graceful recovery from git reset --hard. Witness the many questions and answers
on recovery:
    http://stackoverflow.com/questions/7374069/undo-git-reset-hard-with-uncommitted-files-in-the-
staging-area
    http://stackoverflow.com/questions/5788037/recover-from-git-reset-hard
    http://stackoverflow.com/questions/5473/how-can-i-undo-git-reset-hard-head1
    http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html
    https://bani.com.br/2014/10/recovering-lost-files-after-a-git-reset-hard/
    https://medium.com/@CarrieGuss/how-to-recover-from-a-git-hard-reset-b830b5e3f60c

All of these solutions recover the contents of files, but not their names or the
directory structure. Saving the tree object somewhere (anywhere!) would solve
this problem.
Yeah, it might be a good idea.
I was bitten by this in a vicious way. I was setting up a new repository for a
bunch of code and data (git init; git add .), changed my mind about adding the
data (git reset --hard), and nearly lost everything.
I think we could also perhaps have a special case when the current
branch doesn't really exist yet.

At least if you had used "git reset --keep", it would have failed with:

$ git reset --keep
error: You do not have a valid HEAD.
fatal: Could not reset index file to revision 'HEAD'.

Also if there had already been a commit, with --keep the new files
would not have been deleted.
The only tree object that
could be found was an empty one, so I got file contents without names or
directories (not good, because experimental conditions for the data were encoded
in the directory structure).
Best,
Christian.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help