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