Re: Git reset --hard with staged changes
- From
- Yotam Gingold <yotam@yotamgingold.com>
- Date
- May 23, 2016, 00:55 UTC
- Message-ID
- <loom.20160523T023140-975@post.gmane.org>
Pierre-François CLEMENT <likeyn <at> gmail.com> writes:
Show 29 quoted lines
> 2014-06-10 17:27 GMT+02:00 David Kastrup <dak <at> gnu.org>: >> Pierre-François CLEMENT <likeyn <at> gmail.com> writes: >> >>> ... >>> >>> 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-b830b5e3f60cAll 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